@@ -35,10 +35,13 @@
#include "hw/misc/unimp.h"
#include "qom/object.h"
+#define TYPE_BCM_SOC_PERIPHERALS_BASE "bcm-soc-peripherals-base"
+OBJECT_DECLARE_TYPE(BCMSocPeripheralBaseState, BCMSocPeripheralBaseClass,
+ BCM_SOC_PERIPHERALS_BASE)
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PeripheralState, BCM2835_PERIPHERALS)
-struct BCM2835PeripheralState {
+struct BCMSocPeripheralBaseState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -60,12 +63,9 @@ struct BCM2835PeripheralState {
OrIRQState orgated_dma_irq;
BCM2835ICState ic;
BCM2835PropertyState property;
- BCM2835RngState rng;
BCM2835MboxState mboxes;
SDHCIState sdhci;
BCM2835SDHostState sdhost;
- BCM2835GpioState gpio;
- Bcm2835ThermalState thermal;
UnimplementedDeviceState i2s;
BCM2835SPIState spi[1];
UnimplementedDeviceState i2c[3];
@@ -79,4 +79,25 @@ struct BCM2835PeripheralState {
UnimplementedDeviceState sdramc;
};
+struct BCMSocPeripheralBaseClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+ uint64_t peri_size; /* Peripheral range size */
+};
+
+struct BCM2835PeripheralState {
+ /*< private >*/
+ BCMSocPeripheralBaseState parent_obj;
+ /*< public >*/
+ BCM2835RngState rng;
+ Bcm2835ThermalState thermal;
+ BCM2835GpioState gpio;
+};
+
+void create_unimp(BCMSocPeripheralBaseState *ps,
+ UnimplementedDeviceState *uds,
+ const char *name, hwaddr ofs, hwaddr size);
+void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp);
+
#endif /* BCM2835_PERIPHERALS_H */
@@ -64,6 +64,7 @@ struct BCM283XState {
BCM2835PeripheralState peripherals;
};
-bool bcm283x_common_realize(DeviceState *dev, Error **errp);
+bool bcm283x_common_realize(DeviceState *dev, BCMSocPeripheralBaseState *ps,
+ Error **errp);
#endif /* BCM2836_H */
@@ -30,9 +30,9 @@
#define SEPARATE_DMA_IRQ_MAX 10
#define ORGATED_DMA_IRQ_COUNT 4
-static void create_unimp(BCM2835PeripheralState *ps,
- UnimplementedDeviceState *uds,
- const char *name, hwaddr ofs, hwaddr size)
+void create_unimp(BCMSocPeripheralBaseState *ps,
+ UnimplementedDeviceState *uds,
+ const char *name, hwaddr ofs, hwaddr size)
{
object_initialize_child(OBJECT(ps), name, uds, TYPE_UNIMPLEMENTED_DEVICE);
qdev_prop_set_string(DEVICE(uds), "name", name);
@@ -45,9 +45,36 @@ static void create_unimp(BCM2835PeripheralState *ps,
static void bcm2835_peripherals_init(Object *obj)
{
BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
+ BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
+
+ /* Random Number Generator */
+ object_initialize_child(obj, "rng", &s->rng, TYPE_BCM2835_RNG);
+
+ /* Thermal */
+ object_initialize_child(obj, "thermal", &s->thermal, TYPE_BCM2835_THERMAL);
+
+ /* GPIO */
+ object_initialize_child(obj, "gpio", &s->gpio, TYPE_BCM2835_GPIO);
+
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
+ OBJECT(&s_base->sdhci.sdbus));
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
+ OBJECT(&s_base->sdhost.sdbus));
+
+ /* Gated DMA interrupts */
+ object_initialize_child(obj, "orgated-dma-irq",
+ &s_base->orgated_dma_irq, TYPE_OR_IRQ);
+ object_property_set_int(OBJECT(&s_base->orgated_dma_irq), "num-lines",
+ ORGATED_DMA_IRQ_COUNT, &error_abort);
+}
+
+static void raspi_peripherals_base_init(Object *obj)
+{
+ BCMSocPeripheralBaseState *s = BCM_SOC_PERIPHERALS_BASE(obj);
+ BCMSocPeripheralBaseClass *bc = BCM_SOC_PERIPHERALS_BASE_GET_CLASS(obj);
/* Memory region for peripheral devices, which we export to our parent */
- memory_region_init(&s->peri_mr, obj,"bcm2835-peripherals", 0x1000000);
+ memory_region_init(&s->peri_mr, obj, "bcm2835-peripherals", bc->peri_size);
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
/* Internal memory region for peripheral bus addresses (not exported) */
@@ -98,9 +125,6 @@ static void bcm2835_peripherals_init(Object *obj)
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
OBJECT(&s->gpu_bus_mr));
- /* Random Number Generator */
- object_initialize_child(obj, "rng", &s->rng, TYPE_BCM2835_RNG);
-
/* Extended Mass Media Controller */
object_initialize_child(obj, "sdhci", &s->sdhci, TYPE_SYSBUS_SDHCI);
@@ -110,25 +134,9 @@ static void bcm2835_peripherals_init(Object *obj)
/* DMA Channels */
object_initialize_child(obj, "dma", &s->dma, TYPE_BCM2835_DMA);
- object_initialize_child(obj, "orgated-dma-irq",
- &s->orgated_dma_irq, TYPE_OR_IRQ);
- object_property_set_int(OBJECT(&s->orgated_dma_irq), "num-lines",
- ORGATED_DMA_IRQ_COUNT, &error_abort);
-
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
OBJECT(&s->gpu_bus_mr));
- /* Thermal */
- object_initialize_child(obj, "thermal", &s->thermal, TYPE_BCM2835_THERMAL);
-
- /* GPIO */
- object_initialize_child(obj, "gpio", &s->gpio, TYPE_BCM2835_GPIO);
-
- object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
- OBJECT(&s->sdhci.sdbus));
- object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
- OBJECT(&s->sdhost.sdbus));
-
/* Mphi */
object_initialize_child(obj, "mphi", &s->mphi, TYPE_BCM2835_MPHI);
@@ -152,7 +160,72 @@ static void bcm2835_peripherals_init(Object *obj)
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
{
+ MemoryRegion *mphi_mr;
BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
+ BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+ int n;
+
+ bcm_soc_peripherals_common_realize(dev, errp);
+
+ /* Extended Mass Media Controller */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s_base->sdhci), 0,
+ qdev_get_gpio_in_named(DEVICE(&s_base->ic), BCM2835_IC_GPU_IRQ,
+ INTERRUPT_ARASANSDIO));
+
+ /* Connect DMA 0-12 to the interrupt controller */
+ for (n = 0; n <= SEPARATE_DMA_IRQ_MAX; n++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s_base->dma), n,
+ qdev_get_gpio_in_named(DEVICE(&s_base->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_DMA0 + n));
+ }
+
+ if (!qdev_realize(DEVICE(&s_base->orgated_dma_irq), NULL, errp)) {
+ return;
+ }
+ for (n = 0; n < ORGATED_DMA_IRQ_COUNT; n++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s_base->dma),
+ SEPARATE_DMA_IRQ_MAX + 1 + n,
+ qdev_get_gpio_in(DEVICE(&s_base->orgated_dma_irq), n));
+ }
+ qdev_connect_gpio_out(DEVICE(&s_base->orgated_dma_irq), 0,
+ qdev_get_gpio_in_named(DEVICE(&s_base->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_DMA0 + SEPARATE_DMA_IRQ_MAX + 1));
+
+ /* Random Number Generator */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->rng), errp)) {
+ return;
+ }
+ memory_region_add_subregion(
+ &s_base->peri_mr, RNG_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
+
+ /* THERMAL */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->thermal), errp)) {
+ return;
+ }
+ memory_region_add_subregion(&s_base->peri_mr, THERMAL_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->thermal), 0));
+
+ /* Map MPHI to the peripherals memory map */
+ mphi_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s_base->mphi), 0);
+ memory_region_add_subregion(&s_base->peri_mr, MPHI_OFFSET, mphi_mr);
+
+ /* GPIO */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
+ return;
+ }
+ memory_region_add_subregion(
+ &s_base->peri_mr, GPIO_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
+
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus");
+}
+
+void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp)
+{
+ BCMSocPeripheralBaseState *s = BCM_SOC_PERIPHERALS_BASE(dev);
Object *obj;
MemoryRegion *ram;
Error *err = NULL;
@@ -285,14 +358,6 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
- /* Random Number Generator */
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->rng), errp)) {
- return;
- }
-
- memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
-
/* Extended Mass Media Controller
*
* Compatible with:
@@ -315,9 +380,6 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->peri_mr, EMMC1_OFFSET,
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
- INTERRUPT_ARASANSDIO));
/* SDHOST */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhost), errp)) {
@@ -340,49 +402,11 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET,
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1));
- for (n = 0; n <= SEPARATE_DMA_IRQ_MAX; n++) {
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n,
- qdev_get_gpio_in_named(DEVICE(&s->ic),
- BCM2835_IC_GPU_IRQ,
- INTERRUPT_DMA0 + n));
- }
- if (!qdev_realize(DEVICE(&s->orgated_dma_irq), NULL, errp)) {
- return;
- }
- for (n = 0; n < ORGATED_DMA_IRQ_COUNT; n++) {
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma),
- SEPARATE_DMA_IRQ_MAX + 1 + n,
- qdev_get_gpio_in(DEVICE(&s->orgated_dma_irq), n));
- }
- qdev_connect_gpio_out(DEVICE(&s->orgated_dma_irq), 0,
- qdev_get_gpio_in_named(DEVICE(&s->ic),
- BCM2835_IC_GPU_IRQ,
- INTERRUPT_DMA0 + SEPARATE_DMA_IRQ_MAX + 1));
-
- /* THERMAL */
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->thermal), errp)) {
- return;
- }
- memory_region_add_subregion(&s->peri_mr, THERMAL_OFFSET,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->thermal), 0));
-
- /* GPIO */
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
- return;
- }
-
- memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
-
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus");
-
/* Mphi */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->mphi), errp)) {
return;
}
- memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0,
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
INTERRUPT_HOSTPORT));
@@ -436,21 +460,27 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ BCMSocPeripheralBaseClass *bc = BCM_SOC_PERIPHERALS_BASE_CLASS(oc);
+ bc->peri_size = 0x1000000;
dc->realize = bcm2835_peripherals_realize;
}
-static const TypeInfo bcm2835_peripherals_type_info = {
- .name = TYPE_BCM2835_PERIPHERALS,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(BCM2835PeripheralState),
- .instance_init = bcm2835_peripherals_init,
- .class_init = bcm2835_peripherals_class_init,
+static const TypeInfo bcm2835_peripherals_types[] = {
+ {
+ .name = TYPE_BCM2835_PERIPHERALS,
+ .parent = TYPE_BCM_SOC_PERIPHERALS_BASE,
+ .instance_size = sizeof(BCM2835PeripheralState),
+ .instance_init = bcm2835_peripherals_init,
+ .class_init = bcm2835_peripherals_class_init,
+ }, {
+ .name = TYPE_BCM_SOC_PERIPHERALS_BASE,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCMSocPeripheralBaseState),
+ .instance_init = raspi_peripherals_base_init,
+ .class_size = sizeof(BCMSocPeripheralBaseClass),
+ .abstract = true,
+ }
};
-static void bcm2835_peripherals_register_types(void)
-{
- type_register_static(&bcm2835_peripherals_type_info);
-}
-
-type_init(bcm2835_peripherals_register_types)
+DEFINE_TYPES(bcm2835_peripherals_types)
@@ -68,10 +68,10 @@ static void bcm283x_init(Object *obj)
"vcram-size");
}
-bool bcm283x_common_realize(DeviceState *dev, Error **errp)
+bool bcm283x_common_realize(DeviceState *dev, BCMSocPeripheralBaseState *ps,
+ Error **errp)
{
- BCM283XState *s = BCM283X(dev);
- BCM283XBaseState *s_base = BCM283X_BASE(dev);
+ BCM283XBaseState *s = BCM283X_BASE(dev);
BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
Object *obj;
@@ -79,17 +79,15 @@ bool bcm283x_common_realize(DeviceState *dev, Error **errp)
obj = object_property_get_link(OBJECT(dev), "ram", &error_abort);
- object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj);
+ object_property_add_const_link(OBJECT(ps), "ram", obj);
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) {
+ if (!sysbus_realize(SYS_BUS_DEVICE(ps), errp)) {
return false;
}
- object_property_add_alias(OBJECT(s_base), "sd-bus",
- OBJECT(&s->peripherals), "sd-bus");
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(ps), "sd-bus");
- sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals),
- 0, bc->peri_base, 1);
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(ps), 0, bc->peri_base, 1);
return true;
}
@@ -97,8 +95,10 @@ static void bcm2835_realize(DeviceState *dev, Error **errp)
{
BCM283XState *s = BCM283X(dev);
BCM283XBaseState *s_base = BCM283X_BASE(dev);
+ BCMSocPeripheralBaseState *ps_base
+ = BCM_SOC_PERIPHERALS_BASE(&s->peripherals);
- if (!bcm283x_common_realize(dev, errp)) {
+ if (!bcm283x_common_realize(dev, ps_base, errp)) {
return;
}
@@ -119,8 +119,10 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
BCM283XState *s = BCM283X(dev);
BCM283XBaseState *s_base = BCM283X_BASE(dev);
BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
+ BCMSocPeripheralBaseState *ps_base
+ = BCM_SOC_PERIPHERALS_BASE(&s->peripherals);
- if (!bcm283x_common_realize(dev, errp)) {
+ if (!bcm283x_common_realize(dev, ps_base, errp)) {
return;
}