It adds the possibility to add 2 gpios to control the warm and cold reset. With theses ios, the reset can be maintained during some time. Each io is associated with a state to detect level changes.
The cold reset io function is named power_gate as it is really the meaning of this io. Signed-off-by: Damien Hedde <damien.he...@greensocs.com> --- hw/core/qdev-vmstate.c | 2 ++ hw/core/qdev.c | 57 ++++++++++++++++++++++++++++++++++++++++++ include/hw/qdev-core.h | 44 ++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/hw/core/qdev-vmstate.c b/hw/core/qdev-vmstate.c index a9834f1a1c..dec6a72f75 100644 --- a/hw/core/qdev-vmstate.c +++ b/hw/core/qdev-vmstate.c @@ -20,6 +20,8 @@ const struct VMStateDescription device_vmstate_reset = { .minimum_version_id = 0, .fields = (VMStateField[]) { VMSTATE_UINT32(resetting, DeviceState), + VMSTATE_BOOL(cold_reset_input.state, DeviceState), + VMSTATE_BOOL(warm_reset_input.state, DeviceState), VMSTATE_END_OF_LIST() } }; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 884a49efa4..8dae26d957 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -464,6 +464,61 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) qdev_init_gpio_in_named(dev, handler, NULL, n); } +static void device_reset_handler(DeviceState *dev, bool cold, bool level) +{ + DeviceResetInputState *dris; + + dris = cold ? &dev->cold_reset_input : &dev->warm_reset_input; + + if (level == dris->state) { + /* io state has not changed */ + return; + } + + dris->state = level; + switch (dris->type) { + case DEVICE_ACTIVE_LOW: + level = !level; + case DEVICE_ACTIVE_HIGH: + if (level) { + resettable_assert_reset(OBJECT(dev), cold); + } else { + resettable_deassert_reset(OBJECT(dev)); + } + break; + } +} + +static void device_cold_reset_handler(void *opaque, int n, int level) +{ + device_reset_handler((DeviceState *) opaque, true, level); +} + +static void device_warm_reset_handler(void *opaque, int n, int level) +{ + device_reset_handler((DeviceState *) opaque, false, level); +} + +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name, + bool cold, DeviceActiveType type) +{ + qemu_irq_handler handler; + + if (cold) { + assert(!dev->cold_reset_input.exists); + dev->cold_reset_input.exists = true; + dev->cold_reset_input.type = type; + handler = device_cold_reset_handler; + } else { + assert(!dev->warm_reset_input.exists); + dev->warm_reset_input.exists = true; + dev->warm_reset_input.type = type; + handler = device_warm_reset_handler; + } + + qdev_init_gpio_in_named(dev, handler, name, 1); +} + void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n) { @@ -1021,6 +1076,8 @@ static void device_initfn(Object *obj) dev->instance_id_alias = -1; dev->realized = false; dev->resetting = 0; + dev->cold_reset_input.exists = false; + dev->warm_reset_input.exists = false; object_property_add_bool(obj, "realized", device_get_realized, device_set_realized, NULL); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index baad2e7066..db997cc47d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -130,6 +130,17 @@ struct NamedGPIOList { QLIST_ENTRY(NamedGPIOList) node; }; +typedef enum DeviceActiveType { + DEVICE_ACTIVE_LOW, + DEVICE_ACTIVE_HIGH, +} DeviceActiveType; + +typedef struct DeviceResetInputState { + bool exists; + DeviceActiveType type; + bool state; +} DeviceResetInputState; + /** * DeviceState: * @realized: Indicates whether the device has been fully constructed. @@ -157,6 +168,8 @@ struct DeviceState { int instance_id_alias; int alias_required_for_version; uint32_t resetting; + DeviceResetInputState cold_reset_input; + DeviceResetInputState warm_reset_input; }; struct DeviceListener { @@ -361,6 +374,37 @@ static inline void qdev_init_gpio_in_named(DeviceState *dev, void qdev_pass_gpios(DeviceState *dev, DeviceState *container, const char *name); +/** + * qdev_init_reset_gpio_in_named: + * Create a gpio controlling the warm or cold reset of the device. + * @cold specify whether it triggers cold or warm reset + * @type what kind of reset io it is + */ +void qdev_init_reset_gpio_in_named(DeviceState *dev, const char *name, + bool cold, DeviceActiveType type); + +/** + * qdev_init_warm_reset_gpio: + * Create a reset input to control the device warm reset. + */ +static inline void qdev_init_warm_reset_gpio(DeviceState *dev, + const char *name, + DeviceActiveType type) +{ + qdev_init_reset_gpio_in_named(dev, name, false, type); +} + +/** + * qdev_init_power_gate_gpio: + * Create a power gate input to control the device cold reset. + */ +static inline void qdev_init_power_gate_gpio(DeviceState *dev, + const char *name, + DeviceActiveType type) +{ + qdev_init_reset_gpio_in_named(dev, name, true, type); +} + BusState *qdev_get_parent_bus(DeviceState *dev); /*** BUS API. ***/ -- 2.21.0