@@ -73,6 +73,7 @@ struct SysBusDevice {
} mmio[QDEV_MAX_MMIO];
int num_pio;
uint32_t pio[QDEV_MAX_PIO];
+ ClockIn *bus_itf_clk;
};
typedef void FindSysbusDeviceFunc(SysBusDevice *sbdev, void *opaque);
@@ -135,4 +136,25 @@ static inline DeviceState *sysbus_try_create_simple(const char *name,
return sysbus_try_create_varargs(name, addr, irq, NULL);
}
+/**
+ * sysbus_init_bus_interface_clock:
+ * @dev: the sysbus device
+ * @name: the name of the clock
+ *
+ * Add the bus interface clock to the device. Mmios will be enabled/disabled
+ * according to the clock status. Must not be called more than once on the same
+ * device.
+ *
+ * Note: if this clock remains unconnected, the sysbus device will work as if
+ * the clock was absent (no side-effect).
+ */
+void sysbus_init_bus_interface_clock(SysBusDevice *dev, const char *name);
+
+/**
+ * sysbus_init_get_interface_clock:
+ * @dev: the sysbus device
+ * @retuns: the clock previously added by sysbus_init_bus_interface_clock.
+ */
+ClockIn *sysbus_get_bus_interface_clock(SysBusDevice *dev);
+
#endif /* HW_SYSBUS_H */
@@ -324,6 +324,31 @@ MemoryRegion *sysbus_address_space(SysBusDevice *dev)
return get_system_memory();
}
+static void sysbus_device_clock_callback(void *opaque, ClockState *clk)
+{
+ SysBusDevice *dev = opaque;
+ bool enable = clock_state_is_domain_running(clk);
+ int i;
+
+ /* set/clear mmio visible flag on clock change */
+ for (i = 0; i < dev->num_mmio && i < QDEV_MAX_MMIO; i++) {
+ MemoryRegion *mr = sysbus_mmio_get_region(dev, i);
+ memory_region_set_enabled(mr, enable);
+ }
+}
+
+void sysbus_init_bus_interface_clock(SysBusDevice *dev, const char *name)
+{
+ assert(dev->bus_itf_clk == NULL);
+ dev->bus_itf_clk = qdev_init_clock_in(DEVICE(dev), name,
+ sysbus_device_clock_callback, dev);
+}
+
+ClockIn *sysbus_get_bus_interface_clock(SysBusDevice *dev)
+{
+ return dev->bus_itf_clk;
+}
+
static void sysbus_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);