mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
clock: Add ClockEvent parameter to callbacks
The Clock framework allows users to specify a callback which is called after the clock's period has been updated. Some users need to also have a callback which is called before the clock period is updated. As the first step in adding support for notifying Clock users on pre-update events, add an argument to the ClockCallback to specify what event is being notified, and add an argument to the various functions for registering a callback to specify which events are of interest to that callback. Note that the documentation update renders correct the previously incorrect claim in 'Adding a new clock' that callbacks "will be explained in a following section". Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Luc Michel <luc@lmichel.fr> Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210219144617.4782-2-peter.maydell@linaro.org
This commit is contained in:
parent
0436c55edf
commit
5ee0abed51
20 changed files with 161 additions and 58 deletions
|
@ -80,11 +80,12 @@ Adding clocks to a device must be done during the init method of the Device
|
|||
instance.
|
||||
|
||||
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 callback (this will be explained in a following section).
|
||||
must be used. It takes the name, a callback, an opaque parameter
|
||||
for the callback and a mask of events when the callback should be
|
||||
called (this will be explained in a following section).
|
||||
Output is simpler; only the name is required. Typically::
|
||||
|
||||
qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev);
|
||||
qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev, ClockUpdate);
|
||||
qdev_init_clock_out(DEVICE(dev), "clk_out");
|
||||
|
||||
Both functions return the created Clock pointer, which should be saved in the
|
||||
|
@ -113,7 +114,7 @@ output.
|
|||
* callback for the input clock (see "Callback on input clock
|
||||
* change" section below for more information).
|
||||
*/
|
||||
static void clk_in_callback(void *opaque);
|
||||
static void clk_in_callback(void *opaque, ClockEvent event);
|
||||
|
||||
/*
|
||||
* static array describing clocks:
|
||||
|
@ -124,7 +125,7 @@ output.
|
|||
* the clk_out field of a MyDeviceState structure.
|
||||
*/
|
||||
static const ClockPortInitArray mydev_clocks = {
|
||||
QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback),
|
||||
QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback, ClockUpdate),
|
||||
QDEV_CLOCK_OUT(MyDeviceState, clk_out),
|
||||
QDEV_CLOCK_END
|
||||
};
|
||||
|
@ -153,6 +154,40 @@ nothing else to do. This value will be propagated to other clocks when
|
|||
connecting the clocks together and devices will fetch the right value during
|
||||
the first reset.
|
||||
|
||||
Clock callbacks
|
||||
---------------
|
||||
|
||||
You can give a clock a callback function in several ways:
|
||||
|
||||
* by passing it as an argument to ``qdev_init_clock_in()``
|
||||
* as an argument to the ``QDEV_CLOCK_IN()`` macro initializing an
|
||||
array to be passed to ``qdev_init_clocks()``
|
||||
* by directly calling the ``clock_set_callback()`` function
|
||||
|
||||
The callback function must be of this type:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef void ClockCallback(void *opaque, ClockEvent event);
|
||||
|
||||
The ``opaque`` argument is the pointer passed to ``qdev_init_clock_in()``
|
||||
or ``clock_set_callback()``; for ``qdev_init_clocks()`` it is the
|
||||
``dev`` device pointer.
|
||||
|
||||
The ``event`` argument specifies why the callback has been called.
|
||||
When you register the callback you specify a mask of ClockEvent values
|
||||
that you are interested in. The callback will only be called for those
|
||||
events.
|
||||
|
||||
The events currently supported are:
|
||||
|
||||
* ``ClockUpdate`` : called after the input clock's period has changed
|
||||
|
||||
Note that a clock only has one callback: it is not possible to register
|
||||
different functions for different events. You must register a single
|
||||
callback which listens for all of the events you are interested in,
|
||||
and use the ``event`` argument to identify which event has happened.
|
||||
|
||||
Retrieving clocks from a device
|
||||
-------------------------------
|
||||
|
||||
|
@ -231,7 +266,7 @@ object during device instance init. For example:
|
|||
.. code-block:: c
|
||||
|
||||
clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
|
||||
dev);
|
||||
dev, ClockUpdate);
|
||||
/* set initial value to 10ns / 100MHz */
|
||||
clock_set_ns(clk, 10);
|
||||
|
||||
|
@ -267,11 +302,12 @@ next lowest integer. This implies some inaccuracy due to the rounding,
|
|||
so be cautious about using it in calculations.
|
||||
|
||||
It is also possible to register a callback on clock frequency changes.
|
||||
Here is an example:
|
||||
Here is an example, which assumes that ``clock_callback`` has been
|
||||
specified as the callback for the ``ClockUpdate`` event:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void clock_callback(void *opaque) {
|
||||
void clock_callback(void *opaque, ClockEvent event) {
|
||||
MyDeviceState *s = (MyDeviceState *) opaque;
|
||||
/*
|
||||
* 'opaque' is the argument passed to qdev_init_clock_in();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue