object_initialize_child(obj, "plb", &s->plb, TYPE_PPC4xx_PLB);
object_initialize_child(obj, "mal", &s->mal, TYPE_PPC4xx_MAL);
+
+ object_initialize_child(obj, "sdram", &s->sdram, TYPE_PPC4xx_SDRAM_DDR);
+ object_property_add_alias(obj, "dram", OBJECT(&s->sdram), "dram");
}
static void ppc405_reset(void *opaque)
qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_CINT));
/* SDRAM controller */
+ /*
+ * We use the 440 DDR SDRAM controller which has more regs and features
+ * but it's compatible enough for now
+ */
+ object_property_set_int(OBJECT(&s->sdram), "nbanks", 2, &error_abort);
+ if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->sdram), &s->cpu, errp)) {
+ return;
+ }
/* XXX 405EP has no ECC interrupt */
- ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(&s->uic), 17), 1,
- s->dram_mr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdram), 0,
+ qdev_get_gpio_in(DEVICE(&s->uic), 17));
/* External bus controller */
if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ebc), &s->cpu, errp)) {
/* Uses UIC IRQs 9, 15, 17 */
}
-static Property ppc405_soc_properties[] = {
- DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
- MemoryRegion *),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void ppc405_soc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = ppc405_soc_realize;
/* Reason: only works as part of a ppc405 board/machine */
dc->user_creatable = false;
- device_class_set_props(dc, ppc405_soc_properties);
}
static const TypeInfo ppc405_types[] = {
#define PPC440EP_PCI_IO 0xe8000000
#define PPC440EP_PCI_IOLEN 0x00010000
-#define PPC440EP_SDRAM_NR_BANKS 4
-
static hwaddr entry;
static int bamboo_load_device_tree(hwaddr addr,
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
/* SDRAM controller */
+ dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
+ object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
+ &error_abort);
+ ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
+ object_unref(OBJECT(dev));
/* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
- ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 14),
- PPC440EP_SDRAM_NR_BANKS, machine->ram);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
/* Enable SDRAM memory regions, this should be done by the firmware */
- ppc4xx_sdram_enable(env);
+ ppc4xx_sdram_enable(PPC4xx_SDRAM_DDR(dev));
/* PCI */
dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
/*****************************************************************************/
/* SDRAM controller */
-typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
-struct ppc4xx_sdram_t {
- uint32_t addr;
- int nbanks; /* Banks to use from the 4, e.g. when board has less slots */
- Ppc4xxSdramBank bank[4];
- uint32_t besr0;
- uint32_t besr1;
- uint32_t bear;
- uint32_t cfg;
- uint32_t status;
- uint32_t rtr;
- uint32_t pmit;
- uint32_t tr;
- uint32_t ecccfg;
- uint32_t eccesr;
- qemu_irq irq;
-};
-
enum {
SDRAM0_CFGADDR = 0x010,
SDRAM0_CFGDATA = 0x011,
* there are type inconsistencies, mixing hwaddr, target_ulong
* and uint32_t
*/
-static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
+static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
{
uint32_t bcr;
return size;
}
-static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
+static void sdram_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
uint32_t bcr, int enabled)
{
if (sdram->bank[i].bcr & 0x00000001) {
}
}
-static void sdram_map_bcr(ppc4xx_sdram_t *sdram)
+static void sdram_map_bcr(Ppc4xxSdramDdrState *sdram)
{
int i;
for (i = 0; i < sdram->nbanks; i++) {
if (sdram->bank[i].size != 0) {
- sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
- sdram->bank[i].size), 1);
+ sdram_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base,
+ sdram->bank[i].size), 1);
} else {
sdram_set_bcr(sdram, i, 0x00000000, 0);
}
}
}
-static void sdram_unmap_bcr(ppc4xx_sdram_t *sdram)
+static void sdram_unmap_bcr(Ppc4xxSdramDdrState *sdram)
{
int i;
}
}
-static uint32_t dcr_read_sdram(void *opaque, int dcrn)
+static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
{
- ppc4xx_sdram_t *sdram;
+ Ppc4xxSdramDdrState *sdram = opaque;
uint32_t ret;
- sdram = opaque;
switch (dcrn) {
case SDRAM0_CFGADDR:
ret = sdram->addr;
return ret;
}
-static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
+static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
{
- ppc4xx_sdram_t *sdram;
+ Ppc4xxSdramDdrState *sdram = opaque;
- sdram = opaque;
switch (dcrn) {
case SDRAM0_CFGADDR:
sdram->addr = val;
}
}
-static void sdram_reset(void *opaque)
+static void ppc4xx_sdram_ddr_reset(DeviceState *dev)
{
- ppc4xx_sdram_t *sdram;
+ Ppc4xxSdramDdrState *sdram = PPC4xx_SDRAM_DDR(dev);
- sdram = opaque;
sdram->addr = 0x00000000;
sdram->bear = 0x00000000;
sdram->besr0 = 0x00000000; /* No error */
sdram->cfg = 0x00800000;
}
-void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks,
- MemoryRegion *ram)
+static void ppc4xx_sdram_ddr_realize(DeviceState *dev, Error **errp)
{
- ppc4xx_sdram_t *sdram;
+ Ppc4xxSdramDdrState *s = PPC4xx_SDRAM_DDR(dev);
+ Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
const ram_addr_t valid_bank_sizes[] = {
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
};
- sdram = g_new0(ppc4xx_sdram_t, 1);
- sdram->irq = irq;
- sdram->nbanks = nbanks;
- ppc4xx_sdram_banks(ram, sdram->nbanks, sdram->bank, valid_bank_sizes);
- qemu_register_reset(&sdram_reset, sdram);
- ppc_dcr_register(env, SDRAM0_CFGADDR,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
- ppc_dcr_register(env, SDRAM0_CFGDATA,
- sdram, &dcr_read_sdram, &dcr_write_sdram);
+ if (s->nbanks < 1 || s->nbanks > 4) {
+ error_setg(errp, "Invalid number of RAM banks");
+ return;
+ }
+ if (!s->dram_mr) {
+ error_setg(errp, "Missing dram memory region");
+ return;
+ }
+ ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+
+ ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR,
+ s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
+ ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA,
+ s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
}
-void ppc4xx_sdram_enable(CPUPPCState *env)
+static Property ppc4xx_sdram_ddr_props[] = {
+ DEFINE_PROP_LINK("dram", Ppc4xxSdramDdrState, dram_mr, TYPE_MEMORY_REGION,
+ MemoryRegion *),
+ DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdrState, nbanks, 4),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ppc4xx_sdram_ddr_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = ppc4xx_sdram_ddr_realize;
+ dc->reset = ppc4xx_sdram_ddr_reset;
+ /* Reason: only works as function of a ppc4xx SoC */
+ dc->user_creatable = false;
+ device_class_set_props(dc, ppc4xx_sdram_ddr_props);
+}
+
+void ppc4xx_sdram_enable(Ppc4xxSdramDdrState *s)
{
- ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20);
- ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x80000000);
+ sdram_ddr_dcr_write(s, SDRAM0_CFGADDR, 0x20);
+ sdram_ddr_dcr_write(s, SDRAM0_CFGDATA, 0x80000000);
}
/*
static const TypeInfo ppc4xx_types[] = {
{
+ .name = TYPE_PPC4xx_SDRAM_DDR,
+ .parent = TYPE_PPC4xx_DCR_DEVICE,
+ .instance_size = sizeof(Ppc4xxSdramDdrState),
+ .class_init = ppc4xx_sdram_ddr_class_init,
+ }, {
.name = TYPE_PPC4xx_MAL,
.parent = TYPE_PPC4xx_DCR_DEVICE,
.instance_size = sizeof(Ppc4xxMalState),