|
@@ -80,11 +80,12 @@ Adding clocks to a device must be done during the init method of the Device
|
|
instance.
|
|
instance.
|
|
|
|
|
|
To add an input clock to a device, the function ``qdev_init_clock_in()``
|
|
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::
|
|
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");
|
|
qdev_init_clock_out(DEVICE(dev), "clk_out");
|
|
|
|
|
|
Both functions return the created Clock pointer, which should be saved in the
|
|
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
|
|
* callback for the input clock (see "Callback on input clock
|
|
* change" section below for more information).
|
|
* 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:
|
|
* static array describing clocks:
|
|
@@ -124,7 +125,7 @@ output.
|
|
* the clk_out field of a MyDeviceState structure.
|
|
* the clk_out field of a MyDeviceState structure.
|
|
*/
|
|
*/
|
|
static const ClockPortInitArray mydev_clocks = {
|
|
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_OUT(MyDeviceState, clk_out),
|
|
QDEV_CLOCK_END
|
|
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
|
|
connecting the clocks together and devices will fetch the right value during
|
|
the first reset.
|
|
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
|
|
Retrieving clocks from a device
|
|
-------------------------------
|
|
-------------------------------
|
|
|
|
|
|
@@ -231,7 +266,7 @@ object during device instance init. For example:
|
|
.. code-block:: c
|
|
.. code-block:: c
|
|
|
|
|
|
clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
|
|
clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
|
|
- dev);
|
|
|
|
|
|
+ dev, ClockUpdate);
|
|
/* set initial value to 10ns / 100MHz */
|
|
/* set initial value to 10ns / 100MHz */
|
|
clock_set_ns(clk, 10);
|
|
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.
|
|
so be cautious about using it in calculations.
|
|
|
|
|
|
It is also possible to register a callback on clock frequency changes.
|
|
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
|
|
.. code-block:: c
|
|
|
|
|
|
- void clock_callback(void *opaque) {
|
|
|
|
|
|
+ void clock_callback(void *opaque, ClockEvent event) {
|
|
MyDeviceState *s = (MyDeviceState *) opaque;
|
|
MyDeviceState *s = (MyDeviceState *) opaque;
|
|
/*
|
|
/*
|
|
* 'opaque' is the argument passed to qdev_init_clock_in();
|
|
* 'opaque' is the argument passed to qdev_init_clock_in();
|