qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v5 5/9] docs/clocks: add device's clock documentatio


From: Damien Hedde
Subject: [Qemu-devel] [PATCH v5 5/9] docs/clocks: add device's clock documentation
Date: Tue, 2 Oct 2018 16:24:39 +0200

Add the documentation about the clock inputs and outputs in devices.

This is based on the original work of Frederic Konrad.

Signed-off-by: Damien Hedde <address@hidden>
---
 docs/devel/clock.txt | 163 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)
 create mode 100644 docs/devel/clock.txt

diff --git a/docs/devel/clock.txt b/docs/devel/clock.txt
new file mode 100644
index 0000000000..6dd8abdee6
--- /dev/null
+++ b/docs/devel/clock.txt
@@ -0,0 +1,163 @@
+
+What are device's clocks
+========================
+
+Clocks are ports representing input and output clocks of a device. They are QOM
+objects developed for the purpose of modeling the distribution of clocks in
+QEMU.
+
+This allows us to model the clock distribution of a platform and detect
+configuration errors in the clock tree such as badly configured PLL, clock
+source selection or disabled clock.
+
+The objects are CLOCK_IN for the input and CLOCK_OUT for the output.
+
+The clock value: ClockState
+===========================
+
+The ClockState is the structure carried by the CLOCK_OUT and CLOCK_IN objects.
+It contains one integer field representing the frequency of the clock in Hertz.
+
+It only simulates the clock by transmitting the frequency value and
+doesn't model the signal itself such as pin toggle or duty cycle.
+The special value 0 as a frequency is legal and represent the clock being
+inactive or gated.
+
+Adding clocks to a device
+=========================
+
+Adding clocks to a device must be done during the init phase of the Device
+object.
+
+To add an input clock to a device, the function qdev_init_clock_in must be 
used.
+It takes the name, a callback, and an opaque parameter for the clock.
+Output is more simple, only the name is required. Typically:
+qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback, dev);
+qdev_init_clock_out(DEVICE(dev), "clk-out");
+
+Both functions return the created CLOCK_IN/OUT pointer, which should be saved
+in the device's state structure.
+
+Theses objects will be automatically deleted by the qom reference mechanism.
+
+Note that it is possible to create a static array describing clock inputs and
+outputs. The function qdev_init_clocks must be called with the array as
+parameters to initialize the clocks: it has the same behaviour as calling the
+qdev_init_clock/out for each clock in the array.
+
+Unconnected input clocks
+========================
+
+Unconnected input clocks have a default frequency value of 0. It means the
+clock will be considered as disabled. If this is not the wanted behaviour,
+clock_init_frequency should be called on the ClockIn object during device init.
+For example:
+clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback, dev);
+clock_init_frequency(clk, 100 * 1000 * 1000); // init value is 100Mhz
+
+Forwarding clocks
+=================
+
+Sometimes, one needs to forward, or inherit, a clock from another device.
+Typically, when doing device composition, a device might expose a sub-device's
+clock without interfering with it.
+The function qdev_pass_clock can be used to achieve this behaviour. Note, that
+it is possible to expose the clock under a different name. This works for both
+inputs or outputs.
+
+For example, if device B is a child of device A, device_a_instance_init may
+do something like this:
+void device_a_instance_init(Object *obj)
+{
+    AState *A = DEVICE_A(obj);
+    BState *B;
+    [...] /* create B object as child of A */
+    qdev_pass_clock(A, "b_clk", B, "clk");
+    /*
+     * Now A has a clock "b_clk" which forwards to
+     * the "clk" of its child B.
+     */
+}
+
+This function does not returns any clock object. It is not possible to add
+a callback on a forwarded input clock.
+
+Connecting two clocks together
+==============================
+
+Let's say we have 2 devices A and B. A has an output clock named "clkout" and B
+has an input clock named "clkin".
+
+The clocks are connected together using the function qdev_connect_clock:
+qdev_connect_clock(B, "clkin", A, "clkout", &error_abort);
+The device which has the input must be the first argument.
+
+It is possible to connect several input clocks to the same output. Every
+input callback will be called when the output changes.
+
+It is not possible to disconnect a clock or to change the clock connection
+after it is done.
+
+Changing a clock output
+=======================
+
+A device can change its outputs using the clock_set function. It will trigger
+updates on any connected inputs.
+
+For example, let's say that we have an output clock "clkout" and we have a
+pointer to it in the device state because we did the following in init phase:
+dev->clkout = qdev_init_clock_out(DEVICE(dev), "clkout");
+
+Then at any time, it is possible to change the clock value by doing:
+clock_set_frequency(dev->clkout, 1000 * 1000 * 1000); /* 1Mhz */
+
+Callback on input clock change
+==============================
+
+Here is an example of an input callback:
+void clock_callback(void *opaque) {
+    MyDeviceState *s = (MyDeviceState *) opaque;
+    /*
+     * opaque may not be the device state pointer, but most probably it is.
+     * (It depends on what is given to the qdev_init_clock_in function)
+     */
+
+    /* do something with the new frequency */
+    fprintf(stdout, "device new frequency is %" PRIu64 "Hz\n",
+                    clock_get_frequency(dev->my_clk_input));
+}
+
+The state argument needs only to be copied if the device needs to use the value
+later: the state pointer argument of the pointer will not be valid anymore
+after the end of the function.
+
+Migration
+=========
+
+Only the CLOCK_IN object has a state. CLOCK_OUT frequency should not be set
+in migration post_load.
+
+In case the frequency of in input clock is needed for a device's migration,
+this state must be migrated. The VMSTATE_CLOCKIN macro defines an entry to
+be added in a vmstate description.
+
+For example, if a device has a clock input and the device state looks like:
+MyDeviceState {
+    DeviceState parent_obj;
+    ClockIn *clk;
+};
+
+Then, to add the clock frequency to the device's migrated state, the vmstate
+description is:
+VMStateDescription my_device_vmstate = {
+    .name = "my_device",
+    .fields = (VMStateField[]) {
+        VMSTATE_CLOCKIN(clk, MyDeviceState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+When adding a input clock support to an existing device, you must care about
+migration compatibility. To this end, you can use the clock_init_frequency in
+a pre_load function to setup a default value in case the source vm does not
+migrate the frequency.
-- 
2.19.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]