xref: /qemu/include/hw/qdev-clock.h (revision 79854b95)
1 /*
2  * Device's clock input and output
3  *
4  * Copyright GreenSocs 2016-2020
5  *
6  * Authors:
7  *  Frederic Konrad
8  *  Damien Hedde
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11  * See the COPYING file in the top-level directory.
12  */
13 
14 #ifndef QDEV_CLOCK_H
15 #define QDEV_CLOCK_H
16 
17 #include "hw/clock.h"
18 
19 /**
20  * qdev_init_clock_in:
21  * @dev: the device to add an input clock to
22  * @name: the name of the clock (can't be NULL).
23  * @callback: optional callback to be called on update or NULL.
24  * @opaque: argument for the callback
25  * @events: the events the callback should be called for
26  *          (logical OR of ClockEvent enum values)
27  * @returns: a pointer to the newly added clock
28  *
29  * Add an input clock to device @dev as a clock named @name.
30  * This adds a child<> property.
31  * The callback will be called with @opaque as opaque parameter.
32  */
33 Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
34                           ClockCallback *callback, void *opaque,
35                           unsigned int events);
36 
37 /**
38  * qdev_init_clock_out:
39  * @dev: the device to add an output clock to
40  * @name: the name of the clock (can't be NULL).
41  * @returns: a pointer to the newly added clock
42  *
43  * Add an output clock to device @dev as a clock named @name.
44  * This adds a child<> property.
45  */
46 Clock *qdev_init_clock_out(DeviceState *dev, const char *name);
47 
48 /**
49  * qdev_get_clock_in:
50  * @dev: the device which has the clock
51  * @name: the name of the clock (can't be NULL).
52  * @returns: a pointer to the clock
53  *
54  * Get the input clock @name from @dev or NULL if does not exist.
55  */
56 Clock *qdev_get_clock_in(DeviceState *dev, const char *name);
57 
58 /**
59  * qdev_get_clock_out:
60  * @dev: the device which has the clock
61  * @name: the name of the clock (can't be NULL).
62  * @returns: a pointer to the clock
63  *
64  * Get the output clock @name from @dev or NULL if does not exist.
65  */
66 Clock *qdev_get_clock_out(DeviceState *dev, const char *name);
67 
68 /**
69  * qdev_connect_clock_in:
70  * @dev: a device
71  * @name: the name of an input clock in @dev
72  * @source: the source clock (an output clock of another device for example)
73  *
74  * Set the source clock of input clock @name of device @dev to @source.
75  * @source period update will be propagated to @name clock.
76  *
77  * Must be called before @dev is realized.
78  */
79 void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source);
80 
81 /**
82  * qdev_alias_clock:
83  * @dev: the device which has the clock
84  * @name: the name of the clock in @dev (can't be NULL)
85  * @alias_dev: the device to add the clock
86  * @alias_name: the name of the clock in @container
87  * @returns: a pointer to the clock
88  *
89  * Add a clock @alias_name in @alias_dev which is an alias of the clock @name
90  * in @dev. The direction _in_ or _out_ will the same as the original.
91  * An alias clock must not be modified or used by @alias_dev and should
92  * typically be only only for device composition purpose.
93  */
94 Clock *qdev_alias_clock(DeviceState *dev, const char *name,
95                         DeviceState *alias_dev, const char *alias_name);
96 
97 /**
98  * qdev_finalize_clocklist:
99  * @dev: the device being finalized
100  *
101  * Clear the clocklist from @dev. Only used internally in qdev.
102  */
103 void qdev_finalize_clocklist(DeviceState *dev);
104 
105 /**
106  * ClockPortInitElem:
107  * @name: name of the clock (can't be NULL)
108  * @output: indicates whether the clock is input or output
109  * @callback: for inputs, optional callback to be called on clock's update
110  * with device as opaque
111  * @callback_events: mask of ClockEvent values for when callback is called
112  * @offset: optional offset to store the ClockIn or ClockOut pointer in device
113  * state structure (0 means unused)
114  */
115 struct ClockPortInitElem {
116     const char *name;
117     bool is_output;
118     ClockCallback *callback;
119     unsigned int callback_events;
120     size_t offset;
121 };
122 
123 #define clock_offset_value(devstate, field) \
124     (offsetof(devstate, field) + \
125      type_check(Clock *, typeof_field(devstate, field)))
126 
127 #define QDEV_CLOCK(out_not_in, devstate, field, cb, cbevents) {  \
128     .name = (stringify(field)), \
129     .is_output = out_not_in, \
130     .callback = cb, \
131     .callback_events = cbevents, \
132     .offset = clock_offset_value(devstate, field), \
133 }
134 
135 /**
136  * QDEV_CLOCK_(IN|OUT):
137  * @devstate: structure type. @dev argument of qdev_init_clocks below must be
138  * a pointer to that same type.
139  * @field: a field in @_devstate (must be Clock*)
140  * @callback: (for input only) callback (or NULL) to be called with the device
141  * state as argument
142  * @cbevents: (for input only) ClockEvent mask for when callback is called
143  *
144  * The name of the clock will be derived from @field
145  */
146 #define QDEV_CLOCK_IN(devstate, field, callback, cbevents)       \
147     QDEV_CLOCK(false, devstate, field, callback, cbevents)
148 
149 #define QDEV_CLOCK_OUT(devstate, field) \
150     QDEV_CLOCK(true, devstate, field, NULL, 0)
151 
152 #define QDEV_CLOCK_END { .name = NULL }
153 
154 typedef struct ClockPortInitElem ClockPortInitArray[];
155 
156 /**
157  * qdev_init_clocks:
158  * @dev: the device to add clocks to
159  * @clocks: a QDEV_CLOCK_END-terminated array which contains the
160  * clocks information.
161  */
162 void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks);
163 
164 #endif /* QDEV_CLOCK_H */
165