qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: Damien Hedde <damien.hedde@greensocs.com>, qemu-devel@nongnu.org
Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org,
	alistair@alistair23.me, mark.burton@greensocs.com,
	saipava@xilinx.com, qemu-arm@nongnu.org, pbonzini@redhat.com,
	konrad@adacore.com, luc.michel@greensocs.com
Subject: Re: [Qemu-devel] [PATCH v5 5/9] docs/clocks: add device's clock documentation
Date: Wed, 3 Oct 2018 01:48:02 +0200	[thread overview]
Message-ID: <5bd8bb78-e894-7e63-93fc-241d57f8cbd3@redhat.com> (raw)
In-Reply-To: <20181002142443.30976-6-damien.hedde@greensocs.com>

On 10/2/18 4:24 PM, 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 <damien.hedde@greensocs.com>
> ---
>  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.

A simple ASCII diagram would help to make this clearer.

> +
> +The clock value: ClockState
> +===========================
> +
> +The ClockState is the structure carried by the CLOCK_OUT and CLOCK_IN objects.

This is only true for ClockIn, right?

> +It contains one integer field representing the frequency of the clock in Hertz.

               unsigned

> +
> +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.

OK.

> +
> +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

ClockIn/ClockOut

> +in the device's state structure.
> +
> +Theses objects will be automatically deleted by the qom reference mechanism.

QOM

> +
> +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".

Maybe "clk_in" "clk_out" to avoid confusion with ClkIn and ClkOut.

> +
> +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 */

1GHz

> +
> +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));

Yes.

> +}
> +
> +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

ClkIn ClkOut

> +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.
> 

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

  reply	other threads:[~2018-10-02 23:48 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-02 14:24 [Qemu-devel] [PATCH v5 0/9] Clock framework API Damien Hedde
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 1/9] hw/core/clock-port: introduce clock port objects Damien Hedde
2018-10-02 23:53   ` Philippe Mathieu-Daudé
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 2/9] qdev: add clock input&output support to devices Damien Hedde
2018-10-02 23:36   ` Philippe Mathieu-Daudé
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 3/9] qdev-monitor: print the device's clock with info qtree Damien Hedde
2018-10-02 22:42   ` Philippe Mathieu-Daudé
2018-10-12 10:20     ` Damien Hedde
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 4/9] qdev-clock: introduce an init array to ease the device construction Damien Hedde
2018-10-03  8:23   ` Philippe Mathieu-Daudé
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 5/9] docs/clocks: add device's clock documentation Damien Hedde
2018-10-02 23:48   ` Philippe Mathieu-Daudé [this message]
2018-10-03  8:18   ` Philippe Mathieu-Daudé
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 6/9] hw/misc/zynq_slcr: use standard register definition Damien Hedde
2018-10-04 17:24   ` Alistair Francis
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 7/9] hw/misc/zynq_slcr: add clock generation for uarts Damien Hedde
2018-10-02 23:10   ` Philippe Mathieu-Daudé
2018-10-12 13:24     ` Damien Hedde
2018-10-12 13:27       ` Peter Maydell
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 8/9] hw/char/cadence_uart: add clock support Damien Hedde
2018-10-02 23:26   ` Philippe Mathieu-Daudé
2018-10-12 13:42     ` Damien Hedde
2018-10-02 14:24 ` [Qemu-devel] [PATCH v5 9/9] hw/arm/xilinx_zynq: connect uart clocks to slcr Damien Hedde
2018-10-02 23:28   ` Philippe Mathieu-Daudé
2018-10-04 16:13 ` [Qemu-devel] [PATCH v5 0/9] Clock framework API Philippe Mathieu-Daudé
2018-10-11 16:20   ` Damien Hedde
2018-10-11 16:23     ` Peter Maydell
2018-10-11 17:00       ` Philippe Mathieu-Daudé
2018-10-11 17:12         ` Peter Maydell
2018-10-11 17:16           ` Philippe Mathieu-Daudé
2018-10-12 15:26 ` Damien Hedde
2018-10-16 15:48   ` Peter Maydell
2018-12-18 15:24     ` Damien Hedde

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5bd8bb78-e894-7e63-93fc-241d57f8cbd3@redhat.com \
    --to=philmd@redhat.com \
    --cc=alistair@alistair23.me \
    --cc=damien.hedde@greensocs.com \
    --cc=edgar.iglesias@xilinx.com \
    --cc=konrad@adacore.com \
    --cc=luc.michel@greensocs.com \
    --cc=mark.burton@greensocs.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=saipava@xilinx.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).