[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [Qemu-devel] [PATCH v5 5/9] docs/clocks: add device's clo
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [Qemu-arm] [Qemu-devel] [PATCH v5 5/9] docs/clocks: add device's clock documentation |
Date: |
Wed, 3 Oct 2018 10:18:36 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 |
Hi Damien,
On 02/10/2018 16:24, Damien Hedde wrote:
> 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.
Can you add a simple example here?
> +
> +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.
>
- Re: [Qemu-arm] [Qemu-devel] [PATCH v5 9/9] hw/arm/xilinx_zynq: connect uart clocks to slcr, (continued)
- [Qemu-arm] [PATCH v5 8/9] hw/char/cadence_uart: add clock support, Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 6/9] hw/misc/zynq_slcr: use standard register definition, Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 2/9] qdev: add clock input&output support to devices., Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 5/9] docs/clocks: add device's clock documentation, Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 4/9] qdev-clock: introduce an init array to ease the device construction, Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 3/9] qdev-monitor: print the device's clock with info qtree, Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 7/9] hw/misc/zynq_slcr: add clock generation for uarts, Damien Hedde, 2018/10/02
- [Qemu-arm] [PATCH v5 1/9] hw/core/clock-port: introduce clock port objects, Damien Hedde, 2018/10/02