10e6934f2SDamien Hedde /* 20e6934f2SDamien Hedde * Device's clock input and output 30e6934f2SDamien Hedde * 40e6934f2SDamien Hedde * Copyright GreenSocs 2016-2020 50e6934f2SDamien Hedde * 60e6934f2SDamien Hedde * Authors: 70e6934f2SDamien Hedde * Frederic Konrad 80e6934f2SDamien Hedde * Damien Hedde 90e6934f2SDamien Hedde * 100e6934f2SDamien Hedde * This work is licensed under the terms of the GNU GPL, version 2 or later. 110e6934f2SDamien Hedde * See the COPYING file in the top-level directory. 120e6934f2SDamien Hedde */ 130e6934f2SDamien Hedde 140e6934f2SDamien Hedde #ifndef QDEV_CLOCK_H 150e6934f2SDamien Hedde #define QDEV_CLOCK_H 160e6934f2SDamien Hedde 170e6934f2SDamien Hedde #include "hw/clock.h" 180e6934f2SDamien Hedde 190e6934f2SDamien Hedde /** 200e6934f2SDamien Hedde * qdev_init_clock_in: 210e6934f2SDamien Hedde * @dev: the device to add an input clock to 220e6934f2SDamien Hedde * @name: the name of the clock (can't be NULL). 230e6934f2SDamien Hedde * @callback: optional callback to be called on update or NULL. 240e6934f2SDamien Hedde * @opaque: argument for the callback 25*5ee0abedSPeter Maydell * @events: the events the callback should be called for 26*5ee0abedSPeter Maydell * (logical OR of ClockEvent enum values) 270e6934f2SDamien Hedde * @returns: a pointer to the newly added clock 280e6934f2SDamien Hedde * 290e6934f2SDamien Hedde * Add an input clock to device @dev as a clock named @name. 300e6934f2SDamien Hedde * This adds a child<> property. 310e6934f2SDamien Hedde * The callback will be called with @opaque as opaque parameter. 320e6934f2SDamien Hedde */ 330e6934f2SDamien Hedde Clock *qdev_init_clock_in(DeviceState *dev, const char *name, 34*5ee0abedSPeter Maydell ClockCallback *callback, void *opaque, 35*5ee0abedSPeter Maydell unsigned int events); 360e6934f2SDamien Hedde 370e6934f2SDamien Hedde /** 380e6934f2SDamien Hedde * qdev_init_clock_out: 390e6934f2SDamien Hedde * @dev: the device to add an output clock to 400e6934f2SDamien Hedde * @name: the name of the clock (can't be NULL). 410e6934f2SDamien Hedde * @returns: a pointer to the newly added clock 420e6934f2SDamien Hedde * 430e6934f2SDamien Hedde * Add an output clock to device @dev as a clock named @name. 440e6934f2SDamien Hedde * This adds a child<> property. 450e6934f2SDamien Hedde */ 460e6934f2SDamien Hedde Clock *qdev_init_clock_out(DeviceState *dev, const char *name); 470e6934f2SDamien Hedde 480e6934f2SDamien Hedde /** 490e6934f2SDamien Hedde * qdev_get_clock_in: 500e6934f2SDamien Hedde * @dev: the device which has the clock 510e6934f2SDamien Hedde * @name: the name of the clock (can't be NULL). 520e6934f2SDamien Hedde * @returns: a pointer to the clock 530e6934f2SDamien Hedde * 540e6934f2SDamien Hedde * Get the input clock @name from @dev or NULL if does not exist. 550e6934f2SDamien Hedde */ 560e6934f2SDamien Hedde Clock *qdev_get_clock_in(DeviceState *dev, const char *name); 570e6934f2SDamien Hedde 580e6934f2SDamien Hedde /** 590e6934f2SDamien Hedde * qdev_get_clock_out: 600e6934f2SDamien Hedde * @dev: the device which has the clock 610e6934f2SDamien Hedde * @name: the name of the clock (can't be NULL). 620e6934f2SDamien Hedde * @returns: a pointer to the clock 630e6934f2SDamien Hedde * 640e6934f2SDamien Hedde * Get the output clock @name from @dev or NULL if does not exist. 650e6934f2SDamien Hedde */ 660e6934f2SDamien Hedde Clock *qdev_get_clock_out(DeviceState *dev, const char *name); 670e6934f2SDamien Hedde 680e6934f2SDamien Hedde /** 690e6934f2SDamien Hedde * qdev_connect_clock_in: 700e6934f2SDamien Hedde * @dev: a device 710e6934f2SDamien Hedde * @name: the name of an input clock in @dev 720e6934f2SDamien Hedde * @source: the source clock (an output clock of another device for example) 730e6934f2SDamien Hedde * 740e6934f2SDamien Hedde * Set the source clock of input clock @name of device @dev to @source. 750e6934f2SDamien Hedde * @source period update will be propagated to @name clock. 76739fa325SPhilippe Mathieu-Daudé * 77739fa325SPhilippe Mathieu-Daudé * Must be called before @dev is realized. 780e6934f2SDamien Hedde */ 79f129360cSPhilippe Mathieu-Daudé void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source); 800e6934f2SDamien Hedde 810e6934f2SDamien Hedde /** 820e6934f2SDamien Hedde * qdev_alias_clock: 830e6934f2SDamien Hedde * @dev: the device which has the clock 840e6934f2SDamien Hedde * @name: the name of the clock in @dev (can't be NULL) 850e6934f2SDamien Hedde * @alias_dev: the device to add the clock 860e6934f2SDamien Hedde * @alias_name: the name of the clock in @container 870e6934f2SDamien Hedde * @returns: a pointer to the clock 880e6934f2SDamien Hedde * 890e6934f2SDamien Hedde * Add a clock @alias_name in @alias_dev which is an alias of the clock @name 900e6934f2SDamien Hedde * in @dev. The direction _in_ or _out_ will the same as the original. 910e6934f2SDamien Hedde * An alias clock must not be modified or used by @alias_dev and should 920e6934f2SDamien Hedde * typically be only only for device composition purpose. 930e6934f2SDamien Hedde */ 940e6934f2SDamien Hedde Clock *qdev_alias_clock(DeviceState *dev, const char *name, 950e6934f2SDamien Hedde DeviceState *alias_dev, const char *alias_name); 960e6934f2SDamien Hedde 970e6934f2SDamien Hedde /** 980e6934f2SDamien Hedde * qdev_finalize_clocklist: 990e6934f2SDamien Hedde * @dev: the device being finalized 1000e6934f2SDamien Hedde * 1010e6934f2SDamien Hedde * Clear the clocklist from @dev. Only used internally in qdev. 1020e6934f2SDamien Hedde */ 1030e6934f2SDamien Hedde void qdev_finalize_clocklist(DeviceState *dev); 1040e6934f2SDamien Hedde 105f0bc2a64SDamien Hedde /** 106f0bc2a64SDamien Hedde * ClockPortInitElem: 107f0bc2a64SDamien Hedde * @name: name of the clock (can't be NULL) 108f0bc2a64SDamien Hedde * @output: indicates whether the clock is input or output 109f0bc2a64SDamien Hedde * @callback: for inputs, optional callback to be called on clock's update 110f0bc2a64SDamien Hedde * with device as opaque 111*5ee0abedSPeter Maydell * @callback_events: mask of ClockEvent values for when callback is called 112f0bc2a64SDamien Hedde * @offset: optional offset to store the ClockIn or ClockOut pointer in device 113f0bc2a64SDamien Hedde * state structure (0 means unused) 114f0bc2a64SDamien Hedde */ 115f0bc2a64SDamien Hedde struct ClockPortInitElem { 116f0bc2a64SDamien Hedde const char *name; 117f0bc2a64SDamien Hedde bool is_output; 118f0bc2a64SDamien Hedde ClockCallback *callback; 119*5ee0abedSPeter Maydell unsigned int callback_events; 120f0bc2a64SDamien Hedde size_t offset; 121f0bc2a64SDamien Hedde }; 122f0bc2a64SDamien Hedde 123f0bc2a64SDamien Hedde #define clock_offset_value(devstate, field) \ 124f0bc2a64SDamien Hedde (offsetof(devstate, field) + \ 125f0bc2a64SDamien Hedde type_check(Clock *, typeof_field(devstate, field))) 126f0bc2a64SDamien Hedde 127*5ee0abedSPeter Maydell #define QDEV_CLOCK(out_not_in, devstate, field, cb, cbevents) { \ 128f0bc2a64SDamien Hedde .name = (stringify(field)), \ 129f0bc2a64SDamien Hedde .is_output = out_not_in, \ 130f0bc2a64SDamien Hedde .callback = cb, \ 131*5ee0abedSPeter Maydell .callback_events = cbevents, \ 132f0bc2a64SDamien Hedde .offset = clock_offset_value(devstate, field), \ 133f0bc2a64SDamien Hedde } 134f0bc2a64SDamien Hedde 135f0bc2a64SDamien Hedde /** 136f0bc2a64SDamien Hedde * QDEV_CLOCK_(IN|OUT): 137f0bc2a64SDamien Hedde * @devstate: structure type. @dev argument of qdev_init_clocks below must be 138f0bc2a64SDamien Hedde * a pointer to that same type. 139f0bc2a64SDamien Hedde * @field: a field in @_devstate (must be Clock*) 140f0bc2a64SDamien Hedde * @callback: (for input only) callback (or NULL) to be called with the device 141f0bc2a64SDamien Hedde * state as argument 142*5ee0abedSPeter Maydell * @cbevents: (for input only) ClockEvent mask for when callback is called 143f0bc2a64SDamien Hedde * 144f0bc2a64SDamien Hedde * The name of the clock will be derived from @field 145f0bc2a64SDamien Hedde */ 146*5ee0abedSPeter Maydell #define QDEV_CLOCK_IN(devstate, field, callback, cbevents) \ 147*5ee0abedSPeter Maydell QDEV_CLOCK(false, devstate, field, callback, cbevents) 148f0bc2a64SDamien Hedde 149f0bc2a64SDamien Hedde #define QDEV_CLOCK_OUT(devstate, field) \ 150*5ee0abedSPeter Maydell QDEV_CLOCK(true, devstate, field, NULL, 0) 151f0bc2a64SDamien Hedde 152f0bc2a64SDamien Hedde #define QDEV_CLOCK_END { .name = NULL } 153f0bc2a64SDamien Hedde 154f0bc2a64SDamien Hedde typedef struct ClockPortInitElem ClockPortInitArray[]; 155f0bc2a64SDamien Hedde 156f0bc2a64SDamien Hedde /** 157f0bc2a64SDamien Hedde * qdev_init_clocks: 158f0bc2a64SDamien Hedde * @dev: the device to add clocks to 159f0bc2a64SDamien Hedde * @clocks: a QDEV_CLOCK_END-terminated array which contains the 160f0bc2a64SDamien Hedde * clocks information. 161f0bc2a64SDamien Hedde */ 162f0bc2a64SDamien Hedde void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks); 163f0bc2a64SDamien Hedde 1640e6934f2SDamien Hedde #endif /* QDEV_CLOCK_H */ 165