diff options
Diffstat (limited to 'hw')
51 files changed, 1347 insertions, 1315 deletions
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index f4349eba83..c502c8c62a 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -20,8 +20,6 @@ #include "qemu/datadir.h" #include "net/net.h" -#define MAX_IDE_BUS 2 - static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) { if (((addr >> 41) & 3) == 2) { diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 0cbc2fb4cb..9c235bf66e 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -690,7 +690,7 @@ static const MemoryRegionOps pflash_cfi01_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void pflash_cfi01_fill_cfi_table(PFlashCFI01 *pfl) +static void pflash_cfi01_fill_cfi_table(PFlashCFI01 *pfl, Error **errp) { uint64_t blocks_per_device, sector_len_per_device, device_len; int num_devices; @@ -708,6 +708,10 @@ static void pflash_cfi01_fill_cfi_table(PFlashCFI01 *pfl) sector_len_per_device = pfl->sector_len / num_devices; } device_len = sector_len_per_device * blocks_per_device; + if (!is_power_of_2(device_len)) { + error_setg(errp, "Device size must be a power of two."); + return; + } /* Hardcoded CFI table */ /* Standard "QRY" string */ @@ -865,7 +869,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) */ pfl->cmd = 0x00; pfl->status = 0x80; /* WSM ready */ - pflash_cfi01_fill_cfi_table(pfl); + pflash_cfi01_fill_cfi_table(pfl, errp); } static void pflash_cfi01_system_reset(DeviceState *dev) diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 2a99b286b0..ff2fe154c1 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -880,6 +880,11 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) return; } + if (!is_power_of_2(pfl->chip_len)) { + error_setg(errp, "Device size must be a power of two."); + return; + } + memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), &pflash_cfi02_ops, pfl, pfl->name, pfl->chip_len, errp); diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 19ea7c2c66..de1cc7ab71 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -30,8 +30,6 @@ #include "qemu/log.h" #include "net/net.h" -#define MAX_IDE_BUS 2 - #define MIN_SEABIOS_HPPA_VERSION 6 /* require at least this fw version */ #define HPA_POWER_BUTTON (FIRMWARE_END - 0x10) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 3e86083db3..ef14da5094 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -47,7 +47,6 @@ #include "multiboot.h" #include "hw/rtc/mc146818rtc.h" #include "hw/intc/i8259.h" -#include "hw/dma/i8257.h" #include "hw/timer/i8254.h" #include "hw/input/i8042.h" #include "hw/irq.h" @@ -1320,8 +1319,6 @@ void pc_basic_device_init(struct PCMachineState *pcms, pcspk_init(pcms->pcspk, isa_bus, pit); } - i8257_dma_init(isa_bus, 0); - /* Super I/O */ pc_superio_init(isa_bus, create_fdctrl, pcms->i8042_enabled, pcms->vmport != ON_OFF_AUTO_ON); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 0b1a79c0fa..0ad0ed1603 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -26,6 +26,7 @@ #include CONFIG_DEVICES #include "qemu/units.h" +#include "hw/dma/i8257.h" #include "hw/loader.h" #include "hw/i386/x86.h" #include "hw/i386/pc.h" @@ -39,6 +40,7 @@ #include "hw/usb.h" #include "net/net.h" #include "hw/ide/pci.h" +#include "hw/ide/piix.h" #include "hw/irq.h" #include "sysemu/kvm.h" #include "hw/kvm/clock.h" @@ -225,6 +227,7 @@ static void pc_init1(MachineState *machine, pci_bus = NULL; isa_bus = isa_bus_new(NULL, get_system_memory(), system_io, &error_abort); + i8257_dma_init(isa_bus, 0); pcms->hpet_enabled = false; } isa_bus_irqs(isa_bus, x86ms->gsi); @@ -257,7 +260,7 @@ static void pc_init1(MachineState *machine, if (pcmc->pci_enabled) { PCIDevice *dev; - dev = pci_create_simple(pci_bus, piix3_devfn + 1, "piix3-ide"); + dev = pci_create_simple(pci_bus, piix3_devfn + 1, TYPE_PIIX3_IDE); pci_ide_create_devs(dev); idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 1c15c37ec5..e604466acb 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -24,7 +24,6 @@ */ #include "qemu/osdep.h" -#include "hw/ppc/mac.h" #include "hw/ppc/mac_dbdma.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" diff --git a/hw/ide/piix.c b/hw/ide/piix.c index de1f4f0efb..267dbf37db 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -36,6 +36,7 @@ #include "sysemu/blockdev.h" #include "sysemu/dma.h" +#include "hw/ide/piix.h" #include "hw/ide/pci.h" #include "trace.h" @@ -202,7 +203,7 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) } static const TypeInfo piix3_ide_info = { - .name = "piix3-ide", + .name = TYPE_PIIX3_IDE, .parent = TYPE_PCI_IDE, .class_init = piix3_ide_class_init, }; @@ -224,7 +225,7 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) } static const TypeInfo piix4_ide_info = { - .name = "piix4-ide", + .name = TYPE_PIIX4_IDE, .parent = TYPE_PCI_IDE, .class_init = piix4_ide_class_init, }; diff --git a/hw/ide/via.c b/hw/ide/via.c index 82def819c4..e1a429405d 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -230,7 +230,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_ide_info = { - .name = "via-ide", + .name = TYPE_VIA_IDE, .parent = TYPE_PCI_IDE, .class_init = via_ide_class_init, }; diff --git a/hw/intc/heathrow_pic.c b/hw/intc/heathrow_pic.c index cb97c315da..13048a2735 100644 --- a/hw/intc/heathrow_pic.c +++ b/hw/intc/heathrow_pic.c @@ -24,7 +24,6 @@ */ #include "qemu/osdep.h" -#include "hw/ppc/mac.h" #include "migration/vmstate.h" #include "qemu/module.h" #include "hw/intc/heathrow_pic.h" diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index b0787e8ee7..c757adbe53 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -32,7 +32,6 @@ #include "qemu/osdep.h" #include "hw/irq.h" -#include "hw/ppc/mac.h" #include "hw/pci/pci.h" #include "hw/ppc/openpic.h" #include "hw/ppc/ppc_e500.h" diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig index d42143a991..18b5c6bf3f 100644 --- a/hw/isa/Kconfig +++ b/hw/isa/Kconfig @@ -33,13 +33,20 @@ config PC87312 config PIIX3 bool + select I8257 select ISA_BUS config PIIX4 bool # For historical reasons, SuperIO devices are created in the board # for PIIX4. + select ACPI_PIIX4 + select I8254 + select I8257 + select I8259 + select IDE_PIIX select ISA_BUS + select MC146818RTC select USB_UHCI config VT82C686 @@ -53,6 +60,7 @@ config VT82C686 select I8254 select I8257 select I8259 + select IDE_VIA select MC146818RTC select PARALLEL @@ -67,6 +75,7 @@ config LPC_ICH9 bool # For historical reasons, SuperIO devices are created in the board # for ICH9. + select I8257 select ISA_BUS select ACPI_SMBUS select ACPI_X86_ICH diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 4553b5925b..8694e58b21 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -34,6 +34,7 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "qemu/range.h" +#include "hw/dma/i8257.h" #include "hw/isa/isa.h" #include "migration/vmstate.h" #include "hw/irq.h" @@ -722,6 +723,8 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp) qdev_init_gpio_out_named(dev, lpc->gsi, ICH9_GPIO_GSI, GSI_NUM_PINS); isa_bus_irqs(isa_bus, lpc->gsi); + + i8257_dma_init(isa_bus, 0); } static bool ich9_rst_cnt_needed(void *opaque) diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index 48f9ab1096..808fd4eadf 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -25,12 +25,11 @@ #include "qemu/osdep.h" #include "qemu/range.h" #include "qapi/error.h" +#include "hw/dma/i8257.h" #include "hw/southbridge/piix.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/xen/xen.h" -#include "sysemu/xen.h" -#include "sysemu/reset.h" #include "sysemu/runstate.h" #include "migration/vmstate.h" #include "hw/acpi/acpi_aml_interface.h" @@ -155,9 +154,9 @@ static void piix3_write_config_xen(PCIDevice *dev, piix3_write_config(dev, address, val, len); } -static void piix3_reset(void *opaque) +static void piix3_reset(DeviceState *dev) { - PIIX3State *d = opaque; + PIIX3State *d = PIIX3_PCI_DEVICE(dev); uint8_t *pci_conf = d->dev.config; pci_conf[0x04] = 0x07; /* master, memory and I/O */ @@ -289,15 +288,21 @@ static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len) static const MemoryRegionOps rcr_ops = { .read = rcr_read, .write = rcr_write, - .endianness = DEVICE_LITTLE_ENDIAN + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, }; static void pci_piix3_realize(PCIDevice *dev, Error **errp) { PIIX3State *d = PIIX3_PCI_DEVICE(dev); + ISABus *isa_bus; - if (!isa_bus_new(DEVICE(d), get_system_memory(), - pci_address_space_io(dev), errp)) { + isa_bus = isa_bus_new(DEVICE(d), pci_address_space(dev), + pci_address_space_io(dev), errp); + if (!isa_bus) { return; } @@ -306,7 +311,7 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp) memory_region_add_subregion_overlap(pci_address_space_io(dev), PIIX_RCR_IOPORT, &d->rcr_mem, 1); - qemu_register_reset(piix3_reset, d); + i8257_dma_init(isa_bus, 0); } static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope) @@ -328,6 +333,7 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); + dc->reset = piix3_reset; dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; dc->hotpluggable = false; @@ -370,7 +376,7 @@ static void piix3_realize(PCIDevice *dev, Error **errp) pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq, piix3, PIIX_NUM_PIRQS); pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq); -}; +} static void piix3_class_init(ObjectClass *klass, void *data) { @@ -405,7 +411,7 @@ static void piix3_xen_realize(PCIDevice *dev, Error **errp) */ pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq, piix3, XEN_PIIX_NUM_PIRQS); -}; +} static void piix3_xen_class_init(ObjectClass *klass, void *data) { @@ -413,7 +419,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) k->config_write = piix3_write_config_xen; k->realize = piix3_xen_realize; -}; +} static const TypeInfo piix3_xen_info = { .name = TYPE_PIIX3_XEN_DEVICE, diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 15f344dbb7..8fc1db6dc9 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -28,6 +28,7 @@ #include "hw/irq.h" #include "hw/southbridge/piix.h" #include "hw/pci/pci.h" +#include "hw/ide/piix.h" #include "hw/isa/isa.h" #include "hw/intc/i8259.h" #include "hw/dma/i8257.h" @@ -139,9 +140,11 @@ static void piix4_isa_reset(DeviceState *dev) pci_conf[0xab] = 0x00; pci_conf[0xac] = 0x00; pci_conf[0xae] = 0x00; + + d->rcr = 0; } -static int piix4_ide_post_load(void *opaque, int version_id) +static int piix4_post_load(void *opaque, int version_id) { PIIX4State *s = opaque; @@ -156,7 +159,7 @@ static const VMStateDescription vmstate_piix4 = { .name = "PIIX4", .version_id = 3, .minimum_version_id = 2, - .post_load = piix4_ide_post_load, + .post_load = piix4_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(dev, PIIX4State), VMSTATE_UINT8_V(rcr, PIIX4State, 3), @@ -254,7 +257,6 @@ static void piix4_realize(PCIDevice *dev, Error **errp) if (!qdev_realize(DEVICE(&s->ide), BUS(pci_bus), errp)) { return; } - pci_ide_create_devs(PCI_DEVICE(&s->ide)); /* USB */ qdev_prop_set_int32(DEVICE(&s->uhci), "addr", dev->devfn + 2); @@ -277,7 +279,7 @@ static void piix4_init(Object *obj) PIIX4State *s = PIIX4_PCI_DEVICE(obj); object_initialize_child(obj, "rtc", &s->rtc, TYPE_MC146818_RTC); - object_initialize_child(obj, "ide", &s->ide, "piix4-ide"); + object_initialize_child(obj, "ide", &s->ide, TYPE_PIIX4_IDE); object_initialize_child(obj, "uhci", &s->uhci, "piix4-usb-uhci"); object_initialize_child(obj, "pm", &s->pm, TYPE_PIIX4_PM); diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 8f656251b8..3f9bd0c04d 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -17,11 +17,13 @@ #include "hw/isa/vt82c686.h" #include "hw/pci/pci.h" #include "hw/qdev-properties.h" +#include "hw/ide/pci.h" #include "hw/isa/isa.h" #include "hw/isa/superio.h" #include "hw/intc/i8259.h" #include "hw/irq.h" #include "hw/dma/i8257.h" +#include "hw/usb/hcd-uhci.h" #include "hw/timer/i8254.h" #include "hw/rtc/mc146818rtc.h" #include "migration/vmstate.h" @@ -248,6 +250,8 @@ static const ViaPMInitInfo vt82c686b_pm_init_info = { .device_id = PCI_DEVICE_ID_VIA_82C686B_PM, }; +#define TYPE_VT82C686B_PM "vt82c686b-pm" + static const TypeInfo vt82c686b_pm_info = { .name = TYPE_VT82C686B_PM, .parent = TYPE_VIA_PM, @@ -259,6 +263,8 @@ static const ViaPMInitInfo vt8231_pm_init_info = { .device_id = PCI_DEVICE_ID_VIA_8231_PM, }; +#define TYPE_VT8231_PM "vt8231-pm" + static const TypeInfo vt8231_pm_info = { .name = TYPE_VT8231_PM, .parent = TYPE_VIA_PM, @@ -543,8 +549,13 @@ struct ViaISAState { PCIDevice dev; qemu_irq cpu_intr; qemu_irq *isa_irqs; - ISABus *isa_bus; - ViaSuperIOState *via_sio; + ViaSuperIOState via_sio; + RTCState rtc; + PCIIDEState ide; + UHCIState uhci[2]; + ViaPMState pm; + PCIDevice ac97; + PCIDevice mc97; }; static const VMStateDescription vmstate_via = { @@ -557,10 +568,23 @@ static const VMStateDescription vmstate_via = { } }; +static void via_isa_init(Object *obj) +{ + ViaISAState *s = VIA_ISA(obj); + + object_initialize_child(obj, "rtc", &s->rtc, TYPE_MC146818_RTC); + object_initialize_child(obj, "ide", &s->ide, TYPE_VIA_IDE); + object_initialize_child(obj, "uhci1", &s->uhci[0], TYPE_VT82C686B_USB_UHCI); + object_initialize_child(obj, "uhci2", &s->uhci[1], TYPE_VT82C686B_USB_UHCI); + object_initialize_child(obj, "ac97", &s->ac97, TYPE_VIA_AC97); + object_initialize_child(obj, "mc97", &s->mc97, TYPE_VIA_MC97); +} + static const TypeInfo via_isa_info = { .name = TYPE_VIA_ISA, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(ViaISAState), + .instance_init = via_isa_init, .abstract = true, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, @@ -584,24 +608,74 @@ static void via_isa_realize(PCIDevice *d, Error **errp) { ViaISAState *s = VIA_ISA(d); DeviceState *dev = DEVICE(d); + PCIBus *pci_bus = pci_get_bus(d); qemu_irq *isa_irq; + ISABus *isa_bus; int i; qdev_init_gpio_out(dev, &s->cpu_intr, 1); isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1); - s->isa_bus = isa_bus_new(dev, get_system_memory(), pci_address_space_io(d), - &error_fatal); - s->isa_irqs = i8259_init(s->isa_bus, *isa_irq); - isa_bus_irqs(s->isa_bus, s->isa_irqs); - i8254_pit_init(s->isa_bus, 0x40, 0, NULL); - i8257_dma_init(s->isa_bus, 0); - mc146818_rtc_init(s->isa_bus, 2000, NULL); + isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d), + errp); + + if (!isa_bus) { + return; + } + + s->isa_irqs = i8259_init(isa_bus, *isa_irq); + isa_bus_irqs(isa_bus, s->isa_irqs); + i8254_pit_init(isa_bus, 0x40, 0, NULL); + i8257_dma_init(isa_bus, 0); + + /* RTC */ + qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000); + if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) { + return; + } + isa_connect_gpio_out(ISA_DEVICE(&s->rtc), 0, s->rtc.isairq); for (i = 0; i < PCI_CONFIG_HEADER_SIZE; i++) { if (i < PCI_COMMAND || i >= PCI_REVISION_ID) { d->wmask[i] = 0; } } + + /* Super I/O */ + if (!qdev_realize(DEVICE(&s->via_sio), BUS(isa_bus), errp)) { + return; + } + + /* Function 1: IDE */ + qdev_prop_set_int32(DEVICE(&s->ide), "addr", d->devfn + 1); + if (!qdev_realize(DEVICE(&s->ide), BUS(pci_bus), errp)) { + return; + } + + /* Functions 2-3: USB Ports */ + for (i = 0; i < ARRAY_SIZE(s->uhci); i++) { + qdev_prop_set_int32(DEVICE(&s->uhci[i]), "addr", d->devfn + 2 + i); + if (!qdev_realize(DEVICE(&s->uhci[i]), BUS(pci_bus), errp)) { + return; + } + } + + /* Function 4: Power Management */ + qdev_prop_set_int32(DEVICE(&s->pm), "addr", d->devfn + 4); + if (!qdev_realize(DEVICE(&s->pm), BUS(pci_bus), errp)) { + return; + } + + /* Function 5: AC97 Audio */ + qdev_prop_set_int32(DEVICE(&s->ac97), "addr", d->devfn + 5); + if (!qdev_realize(DEVICE(&s->ac97), BUS(pci_bus), errp)) { + return; + } + + /* Function 6: MC97 Modem */ + qdev_prop_set_int32(DEVICE(&s->mc97), "addr", d->devfn + 6); + if (!qdev_realize(DEVICE(&s->mc97), BUS(pci_bus), errp)) { + return; + } } /* TYPE_VT82C686B_ISA */ @@ -615,7 +689,7 @@ static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, pci_default_write_config(d, addr, val, len); if (addr == 0x85) { /* BIT(1): enable or disable superio config io ports */ - via_superio_io_enable(s->via_sio, val & BIT(1)); + via_superio_io_enable(&s->via_sio, val & BIT(1)); } } @@ -639,13 +713,12 @@ static void vt82c686b_isa_reset(DeviceState *dev) pci_conf[0x77] = 0x10; /* GPIO Control 1/2/3/4 */ } -static void vt82c686b_realize(PCIDevice *d, Error **errp) +static void vt82c686b_init(Object *obj) { - ViaISAState *s = VIA_ISA(d); + ViaISAState *s = VIA_ISA(obj); - via_isa_realize(d, errp); - s->via_sio = VIA_SUPERIO(isa_create_simple(s->isa_bus, - TYPE_VT82C686B_SUPERIO)); + object_initialize_child(obj, "sio", &s->via_sio, TYPE_VT82C686B_SUPERIO); + object_initialize_child(obj, "pm", &s->pm, TYPE_VT82C686B_PM); } static void vt82c686b_class_init(ObjectClass *klass, void *data) @@ -653,7 +726,7 @@ static void vt82c686b_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->realize = vt82c686b_realize; + k->realize = via_isa_realize; k->config_write = vt82c686b_write_config; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_82C686B_ISA; @@ -670,6 +743,7 @@ static const TypeInfo vt82c686b_isa_info = { .name = TYPE_VT82C686B_ISA, .parent = TYPE_VIA_ISA, .instance_size = sizeof(ViaISAState), + .instance_init = vt82c686b_init, .class_init = vt82c686b_class_init, }; @@ -684,7 +758,7 @@ static void vt8231_write_config(PCIDevice *d, uint32_t addr, pci_default_write_config(d, addr, val, len); if (addr == 0x50) { /* BIT(2): enable or disable superio config io ports */ - via_superio_io_enable(s->via_sio, val & BIT(2)); + via_superio_io_enable(&s->via_sio, val & BIT(2)); } } @@ -703,13 +777,12 @@ static void vt8231_isa_reset(DeviceState *dev) pci_conf[0x6b] = 0x01; /* Fast IR I/O Base */ } -static void vt8231_realize(PCIDevice *d, Error **errp) +static void vt8231_init(Object *obj) { - ViaISAState *s = VIA_ISA(d); + ViaISAState *s = VIA_ISA(obj); - via_isa_realize(d, errp); - s->via_sio = VIA_SUPERIO(isa_create_simple(s->isa_bus, - TYPE_VT8231_SUPERIO)); + object_initialize_child(obj, "sio", &s->via_sio, TYPE_VT8231_SUPERIO); + object_initialize_child(obj, "pm", &s->pm, TYPE_VT8231_PM); } static void vt8231_class_init(ObjectClass *klass, void *data) @@ -717,7 +790,7 @@ static void vt8231_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->realize = vt8231_realize; + k->realize = via_isa_realize; k->config_write = vt8231_write_config; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_8231_ISA; @@ -734,6 +807,7 @@ static const TypeInfo vt8231_isa_info = { .name = TYPE_VT8231_ISA, .parent = TYPE_VIA_ISA, .instance_size = sizeof(ViaISAState), + .instance_init = vt8231_init, .class_init = vt8231_class_init, }; diff --git a/hw/mips/bootloader.c b/hw/mips/bootloader.c index 99991f8b2b..f5f42f2bf2 100644 --- a/hw/mips/bootloader.c +++ b/hw/mips/bootloader.c @@ -165,15 +165,29 @@ void bl_gen_jump_to(uint32_t **p, target_ulong jump_addr) bl_gen_nop(p); /* delay slot */ } -void bl_gen_jump_kernel(uint32_t **p, target_ulong sp, target_ulong a0, - target_ulong a1, target_ulong a2, target_ulong a3, +void bl_gen_jump_kernel(uint32_t **p, + bool set_sp, target_ulong sp, + bool set_a0, target_ulong a0, + bool set_a1, target_ulong a1, + bool set_a2, target_ulong a2, + bool set_a3, target_ulong a3, target_ulong kernel_addr) { - bl_gen_load_ulong(p, BL_REG_SP, sp); - bl_gen_load_ulong(p, BL_REG_A0, a0); - bl_gen_load_ulong(p, BL_REG_A1, a1); - bl_gen_load_ulong(p, BL_REG_A2, a2); - bl_gen_load_ulong(p, BL_REG_A3, a3); + if (set_sp) { + bl_gen_load_ulong(p, BL_REG_SP, sp); + } + if (set_a0) { + bl_gen_load_ulong(p, BL_REG_A0, a0); + } + if (set_a1) { + bl_gen_load_ulong(p, BL_REG_A1, a1); + } + if (set_a2) { + bl_gen_load_ulong(p, BL_REG_A2, a2); + } + if (set_a3) { + bl_gen_load_ulong(p, BL_REG_A3, a3); + } bl_gen_jump_to(p, kernel_addr); } diff --git a/hw/mips/boston.c b/hw/mips/boston.c index cab63f43bf..edda87e23c 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -352,7 +352,10 @@ static void gen_firmware(uint32_t *p, hwaddr kernel_entry, hwaddr fdt_addr) * a2/$6 = 0 * a3/$7 = 0 */ - bl_gen_jump_kernel(&p, 0, (int32_t)-2, fdt_addr, 0, 0, kernel_entry); + bl_gen_jump_kernel(&p, + true, 0, true, (int32_t)-2, + true, fdt_addr, true, 0, true, 0, + kernel_entry); } static const void *boston_fdt_filter(void *opaque, const void *fdt_orig, @@ -425,7 +428,7 @@ static inline XilinxPCIEHost * xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr, hwaddr cfg_base, uint64_t cfg_size, hwaddr mmio_base, uint64_t mmio_size, - qemu_irq irq, bool link_up) + qemu_irq irq) { DeviceState *dev; MemoryRegion *cfg, *mmio; @@ -437,7 +440,6 @@ xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr, qdev_prop_set_uint64(dev, "cfg_size", cfg_size); qdev_prop_set_uint64(dev, "mmio_base", mmio_base); qdev_prop_set_uint64(dev, "mmio_size", mmio_size); - qdev_prop_set_bit(dev, "link_up", link_up); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -730,21 +732,21 @@ static void boston_mach_init(MachineState *machine) boston_memmap[BOSTON_PCIE0].size, boston_memmap[BOSTON_PCIE0_MMIO].base, boston_memmap[BOSTON_PCIE0_MMIO].size, - get_cps_irq(&s->cps, 2), false); + get_cps_irq(&s->cps, 2)); xilinx_pcie_init(sys_mem, 1, boston_memmap[BOSTON_PCIE1].base, boston_memmap[BOSTON_PCIE1].size, boston_memmap[BOSTON_PCIE1_MMIO].base, boston_memmap[BOSTON_PCIE1_MMIO].size, - get_cps_irq(&s->cps, 1), false); + get_cps_irq(&s->cps, 1)); pcie2 = xilinx_pcie_init(sys_mem, 2, boston_memmap[BOSTON_PCIE2].base, boston_memmap[BOSTON_PCIE2].size, boston_memmap[BOSTON_PCIE2_MMIO].base, boston_memmap[BOSTON_PCIE2_MMIO].size, - get_cps_irq(&s->cps, 0), true); + get_cps_irq(&s->cps, 0)); platreg = g_new(MemoryRegion, 1); memory_region_init_io(platreg, NULL, &boston_platreg_ops, s, diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 5ee546f5f6..34befa5dd5 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -49,7 +49,6 @@ /* Fuloong 2e has a 512k flash: Winbond W39L040AP70Z */ #define BIOS_SIZE (512 * KiB) -#define MAX_IDE_BUS 2 /* * PMON is not part of qemu and released with BSD license, anyone @@ -180,8 +179,12 @@ static void write_bootloader(CPUMIPSState *env, uint8_t *base, /* Second part of the bootloader */ p = (uint32_t *)(base + 0x040); - bl_gen_jump_kernel(&p, ENVP_VADDR - 64, 2, ENVP_VADDR, ENVP_VADDR + 8, - loaderparams.ram_size, kernel_addr); + bl_gen_jump_kernel(&p, + true, ENVP_VADDR - 64, + true, 2, true, ENVP_VADDR, + true, ENVP_VADDR + 8, + true, loaderparams.ram_size, + kernel_addr); } static void main_cpu_reset(void *opaque) @@ -196,29 +199,6 @@ static void main_cpu_reset(void *opaque) } } -static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, - I2CBus **i2c_bus) -{ - PCIDevice *dev; - - dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(slot, 0), true, - TYPE_VT82C686B_ISA); - qdev_connect_gpio_out(DEVICE(dev), 0, intc); - - dev = pci_create_simple(pci_bus, PCI_DEVFN(slot, 1), "via-ide"); - pci_ide_create_devs(dev); - - pci_create_simple(pci_bus, PCI_DEVFN(slot, 2), "vt82c686b-usb-uhci"); - pci_create_simple(pci_bus, PCI_DEVFN(slot, 3), "vt82c686b-usb-uhci"); - - dev = pci_create_simple(pci_bus, PCI_DEVFN(slot, 4), TYPE_VT82C686B_PM); - *i2c_bus = I2C_BUS(qdev_get_child_bus(DEVICE(dev), "i2c")); - - /* Audio support */ - pci_create_simple(pci_bus, PCI_DEVFN(slot, 5), TYPE_VIA_AC97); - pci_create_simple(pci_bus, PCI_DEVFN(slot, 6), TYPE_VIA_MC97); -} - /* Network support */ static void network_init(PCIBus *pci_bus) { @@ -315,8 +295,20 @@ static void mips_fuloong2e_init(MachineState *machine) pci_bus = bonito_init((qemu_irq *)&(env->irq[2])); /* South bridge -> IP5 */ - vt82c686b_southbridge_init(pci_bus, FULOONG2E_VIA_SLOT, env->irq[5], - &smbus); + pci_dev = pci_create_simple_multifunction(pci_bus, + PCI_DEVFN(FULOONG2E_VIA_SLOT, 0), + true, TYPE_VT82C686B_ISA); + object_property_add_alias(OBJECT(machine), "rtc-time", + object_resolve_path_component(OBJECT(pci_dev), + "rtc"), + "date"); + qdev_connect_gpio_out(DEVICE(pci_dev), 0, env->irq[5]); + + dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide")); + pci_ide_create_devs(PCI_DEVICE(dev)); + + dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "pm")); + smbus = I2C_BUS(qdev_get_child_bus(dev, "i2c")); /* GPU */ if (vga_interface_type != VGA_NONE) { diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 7c3ad0974b..c0a2e0ab04 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -36,11 +36,12 @@ #include "hw/i2c/smbus_eeprom.h" #include "hw/block/flash.h" #include "hw/mips/mips.h" +#include "hw/mips/bootloader.h" #include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" #include "qemu/log.h" #include "hw/mips/bios.h" -#include "hw/ide.h" +#include "hw/ide/pci.h" #include "hw/irq.h" #include "hw/loader.h" #include "elf.h" @@ -70,8 +71,6 @@ #define FLASH_SIZE 0x400000 -#define MAX_IDE_BUS 2 - typedef struct { MemoryRegion iomem; MemoryRegion iomem_lo; /* 0 - 0x900 */ @@ -867,88 +866,63 @@ static void write_bootloader(uint8_t *base, uint64_t run_addr, /* Second part of the bootloader */ p = (uint32_t *) (base + 0x580); - if (semihosting_get_argc()) { - /* Preserve a0 content as arguments have been passed */ - stl_p(p++, 0x00000000); /* nop */ - } else { - stl_p(p++, 0x24040002); /* addiu a0, zero, 2 */ - } - - /* lui sp, high(ENVP_VADDR) */ - stl_p(p++, 0x3c1d0000 | (((ENVP_VADDR - 64) >> 16) & 0xffff)); - /* ori sp, sp, low(ENVP_VADDR) */ - stl_p(p++, 0x37bd0000 | ((ENVP_VADDR - 64) & 0xffff)); - /* lui a1, high(ENVP_VADDR) */ - stl_p(p++, 0x3c050000 | ((ENVP_VADDR >> 16) & 0xffff)); - /* ori a1, a1, low(ENVP_VADDR) */ - stl_p(p++, 0x34a50000 | (ENVP_VADDR & 0xffff)); - /* lui a2, high(ENVP_VADDR + 8) */ - stl_p(p++, 0x3c060000 | (((ENVP_VADDR + 8) >> 16) & 0xffff)); - /* ori a2, a2, low(ENVP_VADDR + 8) */ - stl_p(p++, 0x34c60000 | ((ENVP_VADDR + 8) & 0xffff)); - /* lui a3, high(ram_low_size) */ - stl_p(p++, 0x3c070000 | (loaderparams.ram_low_size >> 16)); - /* ori a3, a3, low(ram_low_size) */ - stl_p(p++, 0x34e70000 | (loaderparams.ram_low_size & 0xffff)); - - /* Load BAR registers as done by YAMON */ - stl_p(p++, 0x3c09b400); /* lui t1, 0xb400 */ - -#if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c08df00); /* lui t0, 0xdf00 */ -#else - stl_p(p++, 0x340800df); /* ori t0, r0, 0x00df */ -#endif - stl_p(p++, 0xad280068); /* sw t0, 0x0068(t1) */ - - stl_p(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */ - -#if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c08c000); /* lui t0, 0xc000 */ -#else - stl_p(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */ -#endif - stl_p(p++, 0xad280048); /* sw t0, 0x0048(t1) */ -#if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c084000); /* lui t0, 0x4000 */ -#else - stl_p(p++, 0x34080040); /* ori t0, r0, 0x0040 */ -#endif - stl_p(p++, 0xad280050); /* sw t0, 0x0050(t1) */ - -#if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c088000); /* lui t0, 0x8000 */ -#else - stl_p(p++, 0x34080080); /* ori t0, r0, 0x0080 */ -#endif - stl_p(p++, 0xad280058); /* sw t0, 0x0058(t1) */ -#if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c083f00); /* lui t0, 0x3f00 */ -#else - stl_p(p++, 0x3408003f); /* ori t0, r0, 0x003f */ -#endif - stl_p(p++, 0xad280060); /* sw t0, 0x0060(t1) */ + /* + * Load BAR registers as done by YAMON: + * + * - set up PCI0 I/O BARs from 0x18000000 to 0x181fffff + * - set up PCI0 MEM0 at 0x10000000, size 0x7e00000 + * - set up PCI0 MEM1 at 0x18200000, size 0xbc00000 + * + */ + /* Bus endianess is always reversed */ #if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c08c100); /* lui t0, 0xc100 */ +#define cpu_to_gt32 cpu_to_le32 #else - stl_p(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */ +#define cpu_to_gt32 cpu_to_be32 #endif - stl_p(p++, 0xad280080); /* sw t0, 0x0080(t1) */ -#if TARGET_BIG_ENDIAN - stl_p(p++, 0x3c085e00); /* lui t0, 0x5e00 */ -#else - stl_p(p++, 0x3408005e); /* ori t0, r0, 0x005e */ -#endif - stl_p(p++, 0xad280088); /* sw t0, 0x0088(t1) */ - /* Jump to kernel code */ - stl_p(p++, 0x3c1f0000 | - ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */ - stl_p(p++, 0x37ff0000 | - (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */ - stl_p(p++, 0x03e00009); /* jalr ra */ - stl_p(p++, 0x00000000); /* nop */ + /* move GT64120 registers from 0x14000000 to 0x1be00000 */ + bl_gen_write_u32(&p, /* GT_ISD */ + cpu_mips_phys_to_kseg1(NULL, 0x14000000 + 0x68), + cpu_to_gt32(0x1be00000 << 3)); + + /* setup MEM-to-PCI0 mapping */ + /* setup PCI0 io window to 0x18000000-0x181fffff */ + bl_gen_write_u32(&p, /* GT_PCI0IOLD */ + cpu_mips_phys_to_kseg1(NULL, 0x1be00000 + 0x48), + cpu_to_gt32(0x18000000 << 3)); + bl_gen_write_u32(&p, /* GT_PCI0IOHD */ + cpu_mips_phys_to_kseg1(NULL, 0x1be00000 + 0x50), + cpu_to_gt32(0x08000000 << 3)); + /* setup PCI0 mem windows */ + bl_gen_write_u32(&p, /* GT_PCI0M0LD */ + cpu_mips_phys_to_kseg1(NULL, 0x1be00000 + 0x58), + cpu_to_gt32(0x10000000 << 3)); + bl_gen_write_u32(&p, /* GT_PCI0M0HD */ + cpu_mips_phys_to_kseg1(NULL, 0x1be00000 + 0x60), + cpu_to_gt32(0x07e00000 << 3)); + + bl_gen_write_u32(&p, /* GT_PCI0M1LD */ + cpu_mips_phys_to_kseg1(NULL, 0x1be00000 + 0x80), + cpu_to_gt32(0x18200000 << 3)); + bl_gen_write_u32(&p, /* GT_PCI0M1HD */ + cpu_mips_phys_to_kseg1(NULL, 0x1be00000 + 0x88), + cpu_to_gt32(0x0bc00000 << 3)); + +#undef cpu_to_gt32 + + bl_gen_jump_kernel(&p, + true, ENVP_VADDR - 64, + /* + * If semihosting is used, arguments have already been + * passed, so we preserve $a0. + */ + !semihosting_get_argc(), 2, + true, ENVP_VADDR, + true, ENVP_VADDR + 8, + true, loaderparams.ram_low_size, + kernel_entry); /* YAMON subroutines */ p = (uint32_t *) (base + 0x800); @@ -1266,7 +1240,6 @@ void mips_malta_init(MachineState *machine) MaltaState *s; PCIDevice *piix4; DeviceState *dev; - DeviceState *pm_dev; s = MIPS_MALTA(qdev_new(TYPE_MIPS_MALTA)); sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal); @@ -1430,15 +1403,17 @@ void mips_malta_init(MachineState *machine) /* Southbridge */ piix4 = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(10, 0), true, TYPE_PIIX4_PCI_DEVICE); - dev = DEVICE(piix4); - isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); - pm_dev = DEVICE(object_resolve_path_component(OBJECT(dev), "pm")); - smbus = I2C_BUS(qdev_get_child_bus(pm_dev, "i2c")); + isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix4), "isa.0")); + + dev = DEVICE(object_resolve_path_component(OBJECT(piix4), "ide")); + pci_ide_create_devs(PCI_DEVICE(dev)); /* Interrupt controller */ - qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq); + qdev_connect_gpio_out_named(DEVICE(piix4), "intr", 0, i8259_irq); /* generate SPD EEPROM data */ + dev = DEVICE(object_resolve_path_component(OBJECT(piix4), "pm")); + smbus = I2C_BUS(qdev_get_child_bus(dev, "i2c")); generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size); generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]); smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size); diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 1498113cfc..0d4c13319a 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -25,7 +25,6 @@ #include "qemu/osdep.h" #include "hw/irq.h" -#include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "hw/input/adb.h" diff --git a/hw/misc/macio/gpio.c b/hw/misc/macio/gpio.c index b1bcf830c3..c8ac5633b2 100644 --- a/hw/misc/macio/gpio.c +++ b/hw/misc/macio/gpio.c @@ -24,7 +24,6 @@ */ #include "qemu/osdep.h" -#include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "hw/misc/macio/macio.h" diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index c1fad43f6c..08dbdd7fc0 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -26,7 +26,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" -#include "hw/ppc/mac.h" #include "hw/misc/macio/cuda.h" #include "hw/pci/pci.h" #include "hw/ppc/mac_dbdma.h" @@ -37,8 +36,9 @@ #include "hw/intc/heathrow_pic.h" #include "trace.h" -/* Note: this code is strongly inspirated from the corresponding code - * in PearPC */ +#define ESCC_CLOCK 3686400 + +/* Note: this code is strongly inspired by the corresponding code in PearPC */ /* * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", @@ -226,7 +226,7 @@ static void macio_oldworld_init(Object *obj) object_initialize_child(OBJECT(s), "nvram", &os->nvram, TYPE_MACIO_NVRAM); dev = DEVICE(&os->nvram); - qdev_prop_set_uint32(dev, "size", 0x2000); + qdev_prop_set_uint32(dev, "size", MACIO_NVRAM_SIZE); qdev_prop_set_uint32(dev, "it_shift", 4); for (i = 0; i < 2; i++) { diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c index 336502a84b..70562ed8d0 100644 --- a/hw/misc/macio/pmu.c +++ b/hw/misc/macio/pmu.c @@ -29,7 +29,6 @@ */ #include "qemu/osdep.h" -#include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "hw/input/adb.h" diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h index ae99f58bab..9d423f6c09 100644 --- a/hw/net/e1000_regs.h +++ b/hw/net/e1000_regs.h @@ -793,6 +793,7 @@ #define E1000_CTRL_EXT_ASDCHK 0x00001000 /* auto speed detection check */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* EEPROM reset */ #define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ +#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ #define E1000_CTRL_EXT_EIAME 0x01000000 #define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c index 11f2d31cdb..3d9ddda217 100644 --- a/hw/nvram/mac_nvram.c +++ b/hw/nvram/mac_nvram.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "hw/nvram/chrp_nvram.h" -#include "hw/ppc/mac.h" +#include "hw/nvram/mac_nvram.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/cutils.h" diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index b05facf463..95945ac0f4 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -24,8 +24,6 @@ */ #include "qemu/osdep.h" -#include "hw/pci/pci_host.h" -#include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "hw/pci/pci.h" #include "hw/irq.h" @@ -33,18 +31,7 @@ #include "qemu/module.h" #include "trace.h" #include "qom/object.h" - -OBJECT_DECLARE_SIMPLE_TYPE(GrackleState, GRACKLE_PCI_HOST_BRIDGE) - -struct GrackleState { - PCIHostState parent_obj; - - uint32_t ofw_addr; - qemu_irq irqs[4]; - MemoryRegion pci_mmio; - MemoryRegion pci_hole; - MemoryRegion pci_io; -}; +#include "hw/pci-host/grackle.h" /* Don't know if this matches real hardware, but it agrees with OHW. */ static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num) diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index d25b62d6a5..aebd44d265 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -24,7 +24,6 @@ #include "qemu/osdep.h" #include "hw/irq.h" -#include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "qemu/module.h" #include "hw/pci/pci.h" diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 791fe78a50..b8d2522f45 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -74,7 +74,6 @@ config PEGASOS2 imply ATI_VGA select MV64361 select VT82C686 - select IDE_VIA select SMBUS_EEPROM select VOF # This should come with VT82C686 @@ -126,6 +125,7 @@ config E500 select ETSEC select GPIO_MPC8XXX select OPENPIC + select PFLASH_CFI01 select PLATFORM_BUS select PPCE500_PCI select SERIAL diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 3e950ea3ba..2fe496677c 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -23,8 +23,10 @@ #include "e500-ccsr.h" #include "net/net.h" #include "qemu/config-file.h" +#include "hw/block/flash.h" #include "hw/char/serial.h" #include "hw/pci/pci.h" +#include "sysemu/block-backend-io.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "sysemu/reset.h" @@ -267,6 +269,31 @@ static void sysbus_device_create_devtree(SysBusDevice *sbdev, void *opaque) } } +static void create_devtree_flash(SysBusDevice *sbdev, + PlatformDevtreeData *data) +{ + g_autofree char *name = NULL; + uint64_t num_blocks = object_property_get_uint(OBJECT(sbdev), + "num-blocks", + &error_fatal); + uint64_t sector_length = object_property_get_uint(OBJECT(sbdev), + "sector-length", + &error_fatal); + uint64_t bank_width = object_property_get_uint(OBJECT(sbdev), + "width", + &error_fatal); + hwaddr flashbase = 0; + hwaddr flashsize = num_blocks * sector_length; + void *fdt = data->fdt; + + name = g_strdup_printf("%s/nor@%" PRIx64, data->node, flashbase); + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 1, flashbase, 1, flashsize); + qemu_fdt_setprop_cell(fdt, name, "bank-width", bank_width); +} + static void platform_bus_create_devtree(PPCE500MachineState *pms, void *fdt, const char *mpic) { @@ -276,6 +303,8 @@ static void platform_bus_create_devtree(PPCE500MachineState *pms, uint64_t addr = pmc->platform_bus_base; uint64_t size = pmc->platform_bus_size; int irq_start = pmc->platform_bus_first_irq; + SysBusDevice *sbdev; + bool ambiguous; /* Create a /platform node that we can put all devices into */ @@ -302,6 +331,13 @@ static void platform_bus_create_devtree(PPCE500MachineState *pms, /* Loop through all dynamic sysbus devices and create nodes for them */ foreach_dynamic_sysbus_device(sysbus_device_create_devtree, &data); + sbdev = SYS_BUS_DEVICE(object_resolve_path_type("", TYPE_PFLASH_CFI01, + &ambiguous)); + if (sbdev) { + assert(!ambiguous); + create_devtree_flash(sbdev, &data); + } + g_free(node); } @@ -856,6 +892,7 @@ void ppce500_init(MachineState *machine) unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4}; IrqLines *irqs; DeviceState *dev, *mpicdev; + DriveInfo *dinfo; CPUPPCState *firstenv = NULL; MemoryRegion *ccsr_addr_space; SysBusDevice *s; @@ -1024,6 +1061,48 @@ void ppce500_init(MachineState *machine) pmc->platform_bus_base, &pms->pbus_dev->mmio); + dinfo = drive_get(IF_PFLASH, 0, 0); + if (dinfo) { + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + BlockDriverState *bs = blk_bs(blk); + uint64_t mmio_size = memory_region_size(&pms->pbus_dev->mmio); + uint64_t size = bdrv_getlength(bs); + uint32_t sector_len = 64 * KiB; + + if (!is_power_of_2(size)) { + error_report("Size of pflash file must be a power of two."); + exit(1); + } + + if (size > mmio_size) { + error_report("Size of pflash file must not be bigger than %" PRIu64 + " bytes.", mmio_size); + exit(1); + } + + if (!QEMU_IS_ALIGNED(size, sector_len)) { + error_report("Size of pflash file must be a multiple of %" PRIu32 + ".", sector_len); + exit(1); + } + + dev = qdev_new(TYPE_PFLASH_CFI01); + qdev_prop_set_drive(dev, "drive", blk); + qdev_prop_set_uint32(dev, "num-blocks", size / sector_len); + qdev_prop_set_uint64(dev, "sector-length", sector_len); + qdev_prop_set_uint8(dev, "width", 2); + qdev_prop_set_bit(dev, "big-endian", true); + qdev_prop_set_uint16(dev, "id0", 0x89); + qdev_prop_set_uint16(dev, "id1", 0x18); + qdev_prop_set_uint16(dev, "id2", 0x0000); + qdev_prop_set_uint16(dev, "id3", 0x0); + qdev_prop_set_string(dev, "name", "e500.flash"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + memory_region_add_subregion(&pms->pbus_dev->mmio, 0, + pflash_cfi01_get_memory(PFLASH_CFI01(dev))); + } + /* * Smart firmware defaults ahead! * diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h deleted file mode 100644 index a1fa8f8e41..0000000000 --- a/hw/ppc/mac.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * QEMU PowerMac emulation shared definitions and prototypes - * - * Copyright (c) 2004-2007 Fabrice Bellard - * Copyright (c) 2007 Jocelyn Mayer - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef PPC_MAC_H -#define PPC_MAC_H - -#include "qemu/units.h" -#include "exec/memory.h" -#include "hw/boards.h" -#include "hw/sysbus.h" -#include "hw/input/adb.h" -#include "hw/misc/mos6522.h" -#include "hw/pci/pci_host.h" -#include "hw/pci-host/uninorth.h" -#include "qom/object.h" - -#define NVRAM_SIZE 0x2000 -#define PROM_FILENAME "openbios-ppc" - -#define KERNEL_LOAD_ADDR 0x01000000 -#define KERNEL_GAP 0x00100000 - -#define ESCC_CLOCK 3686400 - -/* Old World IRQs */ -#define OLDWORLD_CUDA_IRQ 0x12 -#define OLDWORLD_ESCCB_IRQ 0x10 -#define OLDWORLD_ESCCA_IRQ 0xf -#define OLDWORLD_IDE0_IRQ 0xd -#define OLDWORLD_IDE0_DMA_IRQ 0x2 -#define OLDWORLD_IDE1_IRQ 0xe -#define OLDWORLD_IDE1_DMA_IRQ 0x3 - -/* New World IRQs */ -#define NEWWORLD_CUDA_IRQ 0x19 -#define NEWWORLD_PMU_IRQ 0x19 -#define NEWWORLD_ESCCB_IRQ 0x24 -#define NEWWORLD_ESCCA_IRQ 0x25 -#define NEWWORLD_IDE0_IRQ 0xd -#define NEWWORLD_IDE0_DMA_IRQ 0x2 -#define NEWWORLD_IDE1_IRQ 0xe -#define NEWWORLD_IDE1_DMA_IRQ 0x3 -#define NEWWORLD_EXTING_GPIO1 0x2f -#define NEWWORLD_EXTING_GPIO9 0x37 - -/* Core99 machine */ -#define TYPE_CORE99_MACHINE MACHINE_TYPE_NAME("mac99") -typedef struct Core99MachineState Core99MachineState; -DECLARE_INSTANCE_CHECKER(Core99MachineState, CORE99_MACHINE, - TYPE_CORE99_MACHINE) - -#define CORE99_VIA_CONFIG_CUDA 0x0 -#define CORE99_VIA_CONFIG_PMU 0x1 -#define CORE99_VIA_CONFIG_PMU_ADB 0x2 - -struct Core99MachineState { - /*< private >*/ - MachineState parent; - - uint8_t via_config; -}; - -/* Grackle PCI */ -#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost" - -/* Mac NVRAM */ -#define TYPE_MACIO_NVRAM "macio-nvram" -OBJECT_DECLARE_SIMPLE_TYPE(MacIONVRAMState, MACIO_NVRAM) - -struct MacIONVRAMState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t size; - uint32_t it_shift; - - MemoryRegion mem; - uint8_t *data; -}; - -void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); -#endif /* PPC_MAC_H */ diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index cf7eb72391..601ea518f8 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -48,10 +48,13 @@ #include "qemu/osdep.h" #include "qemu/datadir.h" +#include "qemu/units.h" #include "qapi/error.h" #include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" -#include "hw/ppc/mac.h" +#include "hw/nvram/mac_nvram.h" +#include "hw/boards.h" +#include "hw/pci-host/uninorth.h" #include "hw/input/adb.h" #include "hw/ppc/mac_dbdma.h" #include "hw/pci/pci.h" @@ -80,9 +83,31 @@ #define NDRV_VGA_FILENAME "qemu_vga.ndrv" +#define PROM_FILENAME "openbios-ppc" #define PROM_BASE 0xfff00000 #define PROM_SIZE (1 * MiB) +#define KERNEL_LOAD_ADDR 0x01000000 +#define KERNEL_GAP 0x00100000 + +#define TYPE_CORE99_MACHINE MACHINE_TYPE_NAME("mac99") +typedef struct Core99MachineState Core99MachineState; +DECLARE_INSTANCE_CHECKER(Core99MachineState, CORE99_MACHINE, + TYPE_CORE99_MACHINE) + +typedef enum { + CORE99_VIA_CONFIG_CUDA = 0, + CORE99_VIA_CONFIG_PMU, + CORE99_VIA_CONFIG_PMU_ADB +} Core99ViaConfig; + +struct Core99MachineState { + /*< private >*/ + MachineState parent; + + Core99ViaConfig via_config; +}; + static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) { @@ -106,45 +131,32 @@ static void ppc_core99_reset(void *opaque) /* PowerPC Mac99 hardware initialisation */ static void ppc_core99_init(MachineState *machine) { - ram_addr_t ram_size = machine->ram_size; - const char *bios_name = machine->firmware ?: PROM_FILENAME; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - const char *boot_device = machine->boot_config.order; Core99MachineState *core99_machine = CORE99_MACHINE(machine); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; IrqLines *openpic_irqs; - int linux_boot, i, j, k; + int i, j, k, ppc_boot_device, machine_arch, bios_size = -1; + const char *bios_name = machine->firmware ?: PROM_FILENAME; MemoryRegion *bios = g_new(MemoryRegion, 1); - hwaddr kernel_base, initrd_base, cmdline_base = 0; - long kernel_size, initrd_size; - UNINHostState *uninorth_pci; + hwaddr kernel_base = 0, initrd_base = 0, cmdline_base = 0; + long kernel_size = 0, initrd_size = 0; PCIBus *pci_bus; - PCIDevice *macio; - ESCCState *escc; bool has_pmu, has_adb; + Object *macio; MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; - int bios_size; - int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; - int machine_arch; SysBusDevice *s; - DeviceState *dev, *pic_dev; + DeviceState *dev, *pic_dev, *uninorth_pci_dev; DeviceState *uninorth_internal_dev = NULL, *uninorth_agp_dev = NULL; hwaddr nvram_addr = 0xFFF04000; - uint64_t tbfreq; - unsigned int smp_cpus = machine->smp.cpus; - - linux_boot = (kernel_filename != NULL); + uint64_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TBFREQ; /* init CPUs */ - for (i = 0; i < smp_cpus; i++) { + for (i = 0; i < machine->smp.cpus; i++) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; @@ -176,68 +188,62 @@ static void ppc_core99_init(MachineState *machine) bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE); } g_free(filename); - } else { - bios_size = -1; } if (bios_size < 0 || bios_size > PROM_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); exit(1); } - if (linux_boot) { - int bswap_needed; + if (machine->kernel_filename) { + int bswap_needed = 0; #ifdef BSWAP_NEEDED bswap_needed = 1; -#else - bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; - - kernel_size = load_elf(kernel_filename, NULL, + kernel_size = load_elf(machine->kernel_filename, NULL, translate_kernel_address, NULL, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); - if (kernel_size < 0) - kernel_size = load_aout(kernel_filename, kernel_base, - ram_size - kernel_base, bswap_needed, - TARGET_PAGE_SIZE); - if (kernel_size < 0) - kernel_size = load_image_targphys(kernel_filename, + if (kernel_size < 0) { + kernel_size = load_aout(machine->kernel_filename, kernel_base, + machine->ram_size - kernel_base, + bswap_needed, TARGET_PAGE_SIZE); + } + if (kernel_size < 0) { + kernel_size = load_image_targphys(machine->kernel_filename, kernel_base, - ram_size - kernel_base); + machine->ram_size - kernel_base); + } if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); + error_report("could not load kernel '%s'", + machine->kernel_filename); exit(1); } /* load initrd */ - if (initrd_filename) { + if (machine->initrd_filename) { initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); - initrd_size = load_image_targphys(initrd_filename, initrd_base, - ram_size - initrd_base); + initrd_size = load_image_targphys(machine->initrd_filename, + initrd_base, + machine->ram_size - initrd_base); if (initrd_size < 0) { error_report("could not load initial ram disk '%s'", - initrd_filename); + machine->initrd_filename); exit(1); } cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size); } else { - initrd_base = 0; - initrd_size = 0; cmdline_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { - kernel_base = 0; - kernel_size = 0; - initrd_base = 0; - initrd_size = 0; ppc_boot_device = '\0'; /* We consider that NewWorld PowerMac never have any floppy drive * For now, OHW cannot boot from the network. */ - for (i = 0; boot_device[i] != '\0'; i++) { - if (boot_device[i] >= 'c' && boot_device[i] <= 'f') { - ppc_boot_device = boot_device[i]; + for (i = 0; machine->boot_config.order[i] != '\0'; i++) { + if (machine->boot_config.order[i] >= 'c' && + machine->boot_config.order[i] <= 'f') { + ppc_boot_device = machine->boot_config.order[i]; break; } } @@ -247,45 +253,39 @@ static void ppc_core99_init(MachineState *machine) } } - /* UniN init */ - dev = qdev_new(TYPE_UNI_NORTH); - s = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(s, &error_fatal); - memory_region_add_subregion(get_system_memory(), 0xf8000000, - sysbus_mmio_get_region(s, 0)); - - openpic_irqs = g_new0(IrqLines, smp_cpus); - for (i = 0; i < smp_cpus; i++) { + openpic_irqs = g_new0(IrqLines, machine->smp.cpus); + dev = DEVICE(cpu); + for (i = 0; i < machine->smp.cpus; i++) { /* Mac99 IRQ connection between OpenPIC outputs pins * and PowerPC input pins */ switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: openpic_irqs[i].irq[OPENPIC_OUTPUT_INT] = - qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT); + qdev_get_gpio_in(dev, PPC6xx_INPUT_INT); openpic_irqs[i].irq[OPENPIC_OUTPUT_CINT] = - qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT); + qdev_get_gpio_in(dev, PPC6xx_INPUT_INT); openpic_irqs[i].irq[OPENPIC_OUTPUT_MCK] = - qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_MCP); + qdev_get_gpio_in(dev, PPC6xx_INPUT_MCP); /* Not connected ? */ openpic_irqs[i].irq[OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i].irq[OPENPIC_OUTPUT_RESET] = - qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_HRESET); + qdev_get_gpio_in(dev, PPC6xx_INPUT_HRESET); break; #if defined(TARGET_PPC64) case PPC_FLAGS_INPUT_970: openpic_irqs[i].irq[OPENPIC_OUTPUT_INT] = - qdev_get_gpio_in(DEVICE(cpu), PPC970_INPUT_INT); + qdev_get_gpio_in(dev, PPC970_INPUT_INT); openpic_irqs[i].irq[OPENPIC_OUTPUT_CINT] = - qdev_get_gpio_in(DEVICE(cpu), PPC970_INPUT_INT); + qdev_get_gpio_in(dev, PPC970_INPUT_INT); openpic_irqs[i].irq[OPENPIC_OUTPUT_MCK] = - qdev_get_gpio_in(DEVICE(cpu), PPC970_INPUT_MCP); + qdev_get_gpio_in(dev, PPC970_INPUT_MCP); /* Not connected ? */ openpic_irqs[i].irq[OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i].irq[OPENPIC_OUTPUT_RESET] = - qdev_get_gpio_in(DEVICE(cpu), PPC970_INPUT_HRESET); + qdev_get_gpio_in(dev, PPC970_INPUT_HRESET); break; #endif /* defined(TARGET_PPC64) */ default: @@ -294,24 +294,29 @@ static void ppc_core99_init(MachineState *machine) } } + /* UniN init */ + s = SYS_BUS_DEVICE(qdev_new(TYPE_UNI_NORTH)); + sysbus_realize_and_unref(s, &error_fatal); + memory_region_add_subregion(get_system_memory(), 0xf8000000, + sysbus_mmio_get_region(s, 0)); + if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { + machine_arch = ARCH_MAC99_U3; /* 970 gets a U3 bus */ /* Uninorth AGP bus */ - dev = qdev_new(TYPE_U3_AGP_HOST_BRIDGE); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - uninorth_pci = U3_AGP_HOST_BRIDGE(dev); - s = SYS_BUS_DEVICE(dev); + uninorth_pci_dev = qdev_new(TYPE_U3_AGP_HOST_BRIDGE); + s = SYS_BUS_DEVICE(uninorth_pci_dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0xf0800000); + sysbus_mmio_map(s, 1, 0xf0c00000); /* PCI hole */ - memory_region_add_subregion(get_system_memory(), 0x80000000ULL, + memory_region_add_subregion(get_system_memory(), 0x80000000, sysbus_mmio_get_region(s, 2)); /* Register 8 MB of ISA IO space */ memory_region_add_subregion(get_system_memory(), 0xf2000000, sysbus_mmio_get_region(s, 3)); - sysbus_mmio_map(s, 0, 0xf0800000); - sysbus_mmio_map(s, 1, 0xf0c00000); - - machine_arch = ARCH_MAC99_U3; } else { + machine_arch = ARCH_MAC99; /* Use values found on a real PowerMac */ /* Uninorth AGP bus */ uninorth_agp_dev = qdev_new(TYPE_UNI_NORTH_AGP_HOST_BRIDGE); @@ -328,22 +333,19 @@ static void ppc_core99_init(MachineState *machine) sysbus_mmio_map(s, 0, 0xf4800000); sysbus_mmio_map(s, 1, 0xf4c00000); - /* Uninorth main bus */ - dev = qdev_new(TYPE_UNI_NORTH_PCI_HOST_BRIDGE); - qdev_prop_set_uint32(dev, "ofw-addr", 0xf2000000); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - uninorth_pci = UNI_NORTH_PCI_HOST_BRIDGE(dev); - s = SYS_BUS_DEVICE(dev); + /* Uninorth main bus - this must be last to make it the default */ + uninorth_pci_dev = qdev_new(TYPE_UNI_NORTH_PCI_HOST_BRIDGE); + qdev_prop_set_uint32(uninorth_pci_dev, "ofw-addr", 0xf2000000); + s = SYS_BUS_DEVICE(uninorth_pci_dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0xf2800000); + sysbus_mmio_map(s, 1, 0xf2c00000); /* PCI hole */ - memory_region_add_subregion(get_system_memory(), 0x80000000ULL, + memory_region_add_subregion(get_system_memory(), 0x80000000, sysbus_mmio_get_region(s, 2)); /* Register 8 MB of ISA IO space */ memory_region_add_subregion(get_system_memory(), 0xf2000000, sysbus_mmio_get_region(s, 3)); - sysbus_mmio_map(s, 0, 0xf2800000); - sysbus_mmio_map(s, 1, 0xf2c00000); - - machine_arch = ARCH_MAC99; } machine->usb |= defaults_enabled() && !machine->usb_disabled; @@ -351,32 +353,25 @@ static void ppc_core99_init(MachineState *machine) has_adb = (core99_machine->via_config == CORE99_VIA_CONFIG_CUDA || core99_machine->via_config == CORE99_VIA_CONFIG_PMU_ADB); - /* Timebase Frequency */ - if (kvm_enabled()) { - tbfreq = kvmppc_get_tbfreq(); - } else { - tbfreq = TBFREQ; - } - /* init basic PC hardware */ - pci_bus = PCI_HOST_BRIDGE(uninorth_pci)->bus; + pci_bus = PCI_HOST_BRIDGE(uninorth_pci_dev)->bus; /* MacIO */ - macio = pci_new(-1, TYPE_NEWWORLD_MACIO); + macio = OBJECT(pci_new(-1, TYPE_NEWWORLD_MACIO)); dev = DEVICE(macio); qdev_prop_set_uint64(dev, "frequency", tbfreq); qdev_prop_set_bit(dev, "has-pmu", has_pmu); qdev_prop_set_bit(dev, "has-adb", has_adb); - escc = ESCC(object_resolve_path_component(OBJECT(macio), "escc")); - qdev_prop_set_chr(DEVICE(escc), "chrA", serial_hd(0)); - qdev_prop_set_chr(DEVICE(escc), "chrB", serial_hd(1)); + dev = DEVICE(object_resolve_path_component(macio, "escc")); + qdev_prop_set_chr(dev, "chrA", serial_hd(0)); + qdev_prop_set_chr(dev, "chrB", serial_hd(1)); - pci_realize_and_unref(macio, pci_bus, &error_fatal); + pci_realize_and_unref(PCI_DEVICE(macio), pci_bus, &error_fatal); - pic_dev = DEVICE(object_resolve_path_component(OBJECT(macio), "pic")); + pic_dev = DEVICE(object_resolve_path_component(macio, "pic")); for (i = 0; i < 4; i++) { - qdev_connect_gpio_out(DEVICE(uninorth_pci), i, + qdev_connect_gpio_out(uninorth_pci_dev, i, qdev_get_gpio_in(pic_dev, 0x1b + i)); } @@ -398,7 +393,7 @@ static void ppc_core99_init(MachineState *machine) /* OpenPIC */ s = SYS_BUS_DEVICE(pic_dev); k = 0; - for (i = 0; i < smp_cpus; i++) { + for (i = 0; i < machine->smp.cpus; i++) { for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { sysbus_connect_irq(s, k++, openpic_irqs[i].irq[j]); } @@ -408,19 +403,17 @@ static void ppc_core99_init(MachineState *machine) /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); - macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), - "ide[0]")); + macio_ide = MACIO_IDE(object_resolve_path_component(macio, "ide[0]")); macio_ide_init_drives(macio_ide, hd); - macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), - "ide[1]")); + macio_ide = MACIO_IDE(object_resolve_path_component(macio, "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); if (has_adb) { if (has_pmu) { - dev = DEVICE(object_resolve_path_component(OBJECT(macio), "pmu")); + dev = DEVICE(object_resolve_path_component(macio, "pmu")); } else { - dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); + dev = DEVICE(object_resolve_path_component(macio, "cuda")); } adb_bus = qdev_get_child_bus(dev, "adb.0"); @@ -461,12 +454,12 @@ static void ppc_core99_init(MachineState *machine) nvram_addr = 0xFFE00000; } dev = qdev_new(TYPE_MACIO_NVRAM); - qdev_prop_set_uint32(dev, "size", 0x2000); + qdev_prop_set_uint32(dev, "size", MACIO_NVRAM_SIZE); qdev_prop_set_uint32(dev, "it_shift", 1); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, nvram_addr); nvr = MACIO_NVRAM(dev); - pmac_format_nvram_partition(nvr, 0x2000); + pmac_format_nvram_partition(nvr, MACIO_NVRAM_SIZE); /* No PCI init: the BIOS will do it */ dev = qdev_new(TYPE_FW_CFG_MEM); @@ -480,15 +473,16 @@ static void ppc_core99_init(MachineState *machine) sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); - fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); + fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)machine->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - if (kernel_cmdline) { + if (machine->kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); - pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); + pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, + machine->kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 03732ca7ed..558c639202 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -30,13 +30,14 @@ #include "qapi/error.h" #include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" -#include "mac.h" +#include "hw/boards.h" #include "hw/input/adb.h" #include "sysemu/sysemu.h" #include "net/net.h" #include "hw/isa/isa.h" #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" +#include "hw/pci-host/grackle.h" #include "hw/nvram/fw_cfg.h" #include "hw/char/escc.h" #include "hw/misc/macio/macio.h" @@ -56,10 +57,15 @@ #define NDRV_VGA_FILENAME "qemu_vga.ndrv" -#define GRACKLE_BASE 0xfec00000 +#define PROM_FILENAME "openbios-ppc" #define PROM_BASE 0xffc00000 #define PROM_SIZE (4 * MiB) +#define KERNEL_LOAD_ADDR 0x01000000 +#define KERNEL_GAP 0x00100000 + +#define GRACKLE_BASE 0xfec00000 + static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) { @@ -80,33 +86,28 @@ static void ppc_heathrow_reset(void *opaque) static void ppc_heathrow_init(MachineState *machine) { - ram_addr_t ram_size = machine->ram_size; const char *bios_name = machine->firmware ?: PROM_FILENAME; - const char *boot_device = machine->boot_config.order; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; - int i; + int i, bios_size = -1; MemoryRegion *bios = g_new(MemoryRegion, 1); - uint32_t kernel_base, initrd_base, cmdline_base = 0; - int32_t kernel_size, initrd_size; + uint64_t bios_addr; + uint32_t kernel_base = 0, initrd_base = 0, cmdline_base = 0; + int32_t kernel_size = 0, initrd_size = 0; PCIBus *pci_bus; - PCIDevice *macio; + Object *macio; MACIOIDEState *macio_ide; - ESCCState *escc; SysBusDevice *s; DeviceState *dev, *pic_dev, *grackle_dev; BusState *adb_bus; - uint64_t bios_addr; - int bios_size; - unsigned int smp_cpus = machine->smp.cpus; uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; - uint64_t tbfreq; + uint64_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TBFREQ; /* init CPUs */ - for (i = 0; i < smp_cpus; i++) { + for (i = 0; i < machine->smp.cpus; i++) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; @@ -116,9 +117,9 @@ static void ppc_heathrow_init(MachineState *machine) } /* allocate RAM */ - if (ram_size > 2047 * MiB) { + if (machine->ram_size > 2047 * MiB) { error_report("Too much memory for this machine: %" PRId64 " MB, " - "maximum 2047 MB", ram_size / MiB); + "maximum 2047 MB", machine->ram_size / MiB); exit(1); } @@ -143,8 +144,6 @@ static void ppc_heathrow_init(MachineState *machine) bios_addr = PROM_BASE; } g_free(filename); - } else { - bios_size = -1; } if (bios_size < 0 || bios_addr - PROM_BASE + bios_size > PROM_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); @@ -152,25 +151,25 @@ static void ppc_heathrow_init(MachineState *machine) } if (machine->kernel_filename) { - int bswap_needed; + int bswap_needed = 0; #ifdef BSWAP_NEEDED bswap_needed = 1; -#else - bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(machine->kernel_filename, NULL, translate_kernel_address, NULL, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); - if (kernel_size < 0) + if (kernel_size < 0) { kernel_size = load_aout(machine->kernel_filename, kernel_base, - ram_size - kernel_base, bswap_needed, - TARGET_PAGE_SIZE); - if (kernel_size < 0) + machine->ram_size - kernel_base, + bswap_needed, TARGET_PAGE_SIZE); + } + if (kernel_size < 0) { kernel_size = load_image_targphys(machine->kernel_filename, kernel_base, - ram_size - kernel_base); + machine->ram_size - kernel_base); + } if (kernel_size < 0) { error_report("could not load kernel '%s'", machine->kernel_filename); @@ -182,7 +181,7 @@ static void ppc_heathrow_init(MachineState *machine) KERNEL_GAP); initrd_size = load_image_targphys(machine->initrd_filename, initrd_base, - ram_size - initrd_base); + machine->ram_size - initrd_base); if (initrd_size < 0) { error_report("could not load initial ram disk '%s'", machine->initrd_filename); @@ -190,30 +189,27 @@ static void ppc_heathrow_init(MachineState *machine) } cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size); } else { - initrd_base = 0; - initrd_size = 0; cmdline_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { - kernel_base = 0; - kernel_size = 0; - initrd_base = 0; - initrd_size = 0; ppc_boot_device = '\0'; - for (i = 0; boot_device[i] != '\0'; i++) { - /* TOFIX: for now, the second IDE channel is not properly + for (i = 0; machine->boot_config.order[i] != '\0'; i++) { + /* + * TOFIX: for now, the second IDE channel is not properly * used by OHW. The Mac floppy disk are not emulated. * For now, OHW cannot boot from the network. */ #if 0 - if (boot_device[i] >= 'a' && boot_device[i] <= 'f') { - ppc_boot_device = boot_device[i]; + if (machine->boot_config.order[i] >= 'a' && + machine->boot_config.order[i] <= 'f') { + ppc_boot_device = machine->boot_config.order[i]; break; } #else - if (boot_device[i] >= 'c' && boot_device[i] <= 'd') { - ppc_boot_device = boot_device[i]; + if (machine->boot_config.order[i] >= 'c' && + machine->boot_config.order[i] <= 'd') { + ppc_boot_device = machine->boot_config.order[i]; break; } #endif @@ -224,13 +220,6 @@ static void ppc_heathrow_init(MachineState *machine) } } - /* Timebase Frequency */ - if (kvm_enabled()) { - tbfreq = kvmppc_get_tbfreq(); - } else { - tbfreq = TBFREQ; - } - /* Grackle PCI host bridge */ grackle_dev = qdev_new(TYPE_GRACKLE_PCI_HOST_BRIDGE); qdev_prop_set_uint32(grackle_dev, "ofw-addr", 0x80000000); @@ -249,24 +238,23 @@ static void ppc_heathrow_init(MachineState *machine) pci_bus = PCI_HOST_BRIDGE(grackle_dev)->bus; /* MacIO */ - macio = pci_new(PCI_DEVFN(16, 0), TYPE_OLDWORLD_MACIO); - dev = DEVICE(macio); - qdev_prop_set_uint64(dev, "frequency", tbfreq); + macio = OBJECT(pci_new(PCI_DEVFN(16, 0), TYPE_OLDWORLD_MACIO)); + qdev_prop_set_uint64(DEVICE(macio), "frequency", tbfreq); - escc = ESCC(object_resolve_path_component(OBJECT(macio), "escc")); - qdev_prop_set_chr(DEVICE(escc), "chrA", serial_hd(0)); - qdev_prop_set_chr(DEVICE(escc), "chrB", serial_hd(1)); + dev = DEVICE(object_resolve_path_component(macio, "escc")); + qdev_prop_set_chr(dev, "chrA", serial_hd(0)); + qdev_prop_set_chr(dev, "chrB", serial_hd(1)); - pci_realize_and_unref(macio, pci_bus, &error_fatal); + pci_realize_and_unref(PCI_DEVICE(macio), pci_bus, &error_fatal); - pic_dev = DEVICE(object_resolve_path_component(OBJECT(macio), "pic")); + pic_dev = DEVICE(object_resolve_path_component(macio, "pic")); for (i = 0; i < 4; i++) { qdev_connect_gpio_out(grackle_dev, i, qdev_get_gpio_in(pic_dev, 0x15 + i)); } /* Connect the heathrow PIC outputs to the 6xx bus */ - for (i = 0; i < smp_cpus; i++) { + for (i = 0; i < machine->smp.cpus; i++) { switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: /* XXX: we register only 1 output pin for heathrow PIC */ @@ -287,16 +275,14 @@ static void ppc_heathrow_init(MachineState *machine) /* MacIO IDE */ ide_drive_get(hd, ARRAY_SIZE(hd)); - macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), - "ide[0]")); + macio_ide = MACIO_IDE(object_resolve_path_component(macio, "ide[0]")); macio_ide_init_drives(macio_ide, hd); - macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), - "ide[1]")); + macio_ide = MACIO_IDE(object_resolve_path_component(macio, "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); /* MacIO CUDA/ADB */ - dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); + dev = DEVICE(object_resolve_path_component(macio, "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); dev = qdev_new(TYPE_ADB_KEYBOARD); qdev_realize_and_unref(dev, adb_bus, &error_fatal); @@ -307,8 +293,9 @@ static void ppc_heathrow_init(MachineState *machine) pci_create_simple(pci_bus, -1, "pci-ohci"); } - if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) + if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) { graphic_depth = 15; + } /* No PCI init: the BIOS will do it */ @@ -323,9 +310,9 @@ static void ppc_heathrow_init(MachineState *machine) sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); - fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); + fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)machine->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index 32babc9b48..c927337da0 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -59,8 +59,9 @@ ppc_ss.add(when: 'CONFIG_PPC440', if_true: files( 'ppc440_bamboo.c', 'ppc440_pcix.c', 'ppc440_uc.c')) ppc_ss.add(when: 'CONFIG_PPC4XX', if_true: files( + 'ppc4xx_devs.c', 'ppc4xx_pci.c', - 'ppc4xx_devs.c')) + 'ppc4xx_sdram.c')) ppc_ss.add(when: 'CONFIG_SAM460EX', if_true: files('sam460ex.c')) # PReP ppc_ss.add(when: 'CONFIG_PREP', if_true: files('prep.c')) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index bb4d008ba9..f46d4bf51d 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -102,7 +102,7 @@ static void pegasos2_init(MachineState *machine) CPUPPCState *env; MemoryRegion *rom = g_new(MemoryRegion, 1); PCIBus *pci_bus; - PCIDevice *dev; + PCIDevice *dev, *via; I2CBus *i2c_bus; const char *fwname = machine->firmware ?: PROM_FILENAME; char *filename; @@ -159,30 +159,23 @@ static void pegasos2_init(MachineState *machine) pci_bus = mv64361_get_pci_bus(pm->mv, 1); /* VIA VT8231 South Bridge (multifunction PCI device) */ - /* VT8231 function 0: PCI-to-ISA Bridge */ - dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0), true, + via = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0), true, TYPE_VT8231_ISA); - qdev_connect_gpio_out(DEVICE(dev), 0, + object_property_add_alias(OBJECT(machine), "rtc-time", + object_resolve_path_component(OBJECT(via), + "rtc"), + "date"); + qdev_connect_gpio_out(DEVICE(via), 0, qdev_get_gpio_in_named(pm->mv, "gpp", 31)); - /* VT8231 function 1: IDE Controller */ - dev = pci_create_simple(pci_bus, PCI_DEVFN(12, 1), "via-ide"); + dev = PCI_DEVICE(object_resolve_path_component(OBJECT(via), "ide")); pci_ide_create_devs(dev); - /* VT8231 function 2-3: USB Ports */ - pci_create_simple(pci_bus, PCI_DEVFN(12, 2), "vt82c686b-usb-uhci"); - pci_create_simple(pci_bus, PCI_DEVFN(12, 3), "vt82c686b-usb-uhci"); - - /* VT8231 function 4: Power Management Controller */ - dev = pci_create_simple(pci_bus, PCI_DEVFN(12, 4), TYPE_VT8231_PM); + dev = PCI_DEVICE(object_resolve_path_component(OBJECT(via), "pm")); i2c_bus = I2C_BUS(qdev_get_child_bus(DEVICE(dev), "i2c")); spd_data = spd_data_generate(DDR, machine->ram_size); smbus_eeprom_init_one(i2c_bus, 0x57, spd_data); - /* VT8231 function 5-6: AC97 Audio & Modem */ - pci_create_simple(pci_bus, PCI_DEVFN(12, 5), TYPE_VIA_AC97); - pci_create_simple(pci_bus, PCI_DEVFN(12, 6), TYPE_VIA_MC97); - /* other PC hardware */ pci_vga_init(pci_bus); diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 19e8eb885f..9ee79192dd 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -58,6 +58,7 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu) env->msr |= MSR_HVB; /* Hypervisor mode */ env->spr[SPR_HRMOR] = pc->hrmor; hreg_compute_hflags(env); + ppc_maybe_interrupt(env); pcc->intc_reset(pc->chip, cpu); } diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 690f448cb9..dc86c1c7db 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -40,9 +40,8 @@ static void cpu_ppc_tb_stop (CPUPPCState *env); static void cpu_ppc_tb_start (CPUPPCState *env); -void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level) +void ppc_set_irq(PowerPCCPU *cpu, int irq, int level) { - CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; unsigned int old_pending; bool locked = false; @@ -56,21 +55,17 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level) old_pending = env->pending_interrupts; if (level) { - env->pending_interrupts |= 1 << n_IRQ; - cpu_interrupt(cs, CPU_INTERRUPT_HARD); + env->pending_interrupts |= irq; } else { - env->pending_interrupts &= ~(1 << n_IRQ); - if (env->pending_interrupts == 0) { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } + env->pending_interrupts &= ~irq; } if (old_pending != env->pending_interrupts) { - kvmppc_set_interrupt(cpu, n_IRQ, level); + ppc_maybe_interrupt(env); + kvmppc_set_interrupt(cpu, irq, level); } - - trace_ppc_irq_set_exit(env, n_IRQ, level, env->pending_interrupts, + trace_ppc_irq_set_exit(env, irq, level, env->pending_interrupts, CPU(cpu)->interrupt_request); if (locked) { diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 5fbf44009e..651263926e 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -10,21 +10,14 @@ #include "qemu/osdep.h" #include "qemu/units.h" -#include "qemu/error-report.h" #include "qapi/error.h" #include "qemu/log.h" -#include "qemu/module.h" #include "hw/irq.h" -#include "exec/memory.h" -#include "cpu.h" #include "hw/ppc/ppc4xx.h" #include "hw/qdev-properties.h" #include "hw/pci/pci.h" -#include "sysemu/block-backend.h" #include "sysemu/reset.h" #include "ppc440.h" -#include "qom/object.h" -#include "trace.h" /*****************************************************************************/ /* L2 Cache as SRAM */ @@ -479,331 +472,6 @@ void ppc4xx_sdr_init(CPUPPCState *env) } /*****************************************************************************/ -/* SDRAM controller */ -enum { - SDRAM0_CFGADDR = 0x10, - SDRAM0_CFGDATA, - SDRAM_R0BAS = 0x40, - SDRAM_R1BAS, - SDRAM_R2BAS, - SDRAM_R3BAS, - SDRAM_CONF1HB = 0x45, - SDRAM_PLBADDULL = 0x4a, - SDRAM_CONF1LL = 0x4b, - SDRAM_CONFPATHB = 0x4f, - SDRAM_PLBADDUHB = 0x50, -}; - -static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size) -{ - uint32_t bcr; - - switch (ram_size) { - case 8 * MiB: - bcr = 0xffc0; - break; - case 16 * MiB: - bcr = 0xff80; - break; - case 32 * MiB: - bcr = 0xff00; - break; - case 64 * MiB: - bcr = 0xfe00; - break; - case 128 * MiB: - bcr = 0xfc00; - break; - case 256 * MiB: - bcr = 0xf800; - break; - case 512 * MiB: - bcr = 0xf000; - break; - case 1 * GiB: - bcr = 0xe000; - break; - case 2 * GiB: - bcr = 0xc000; - break; - case 4 * GiB: - bcr = 0x8000; - break; - default: - error_report("invalid RAM size " TARGET_FMT_plx, ram_size); - return 0; - } - bcr |= ram_base >> 2 & 0xffe00000; - bcr |= 1; - - return bcr; -} - -static inline hwaddr sdram_ddr2_base(uint32_t bcr) -{ - return (bcr & 0xffe00000) << 2; -} - -static uint64_t sdram_ddr2_size(uint32_t bcr) -{ - uint64_t size; - int sh; - - sh = 1024 - ((bcr >> 6) & 0x3ff); - size = 8 * MiB * sh; - - return size; -} - -static void sdram_bank_map(Ppc4xxSdramBank *bank) -{ - memory_region_init(&bank->container, NULL, "sdram-container", bank->size); - memory_region_add_subregion(&bank->container, 0, &bank->ram); - memory_region_add_subregion(get_system_memory(), bank->base, - &bank->container); -} - -static void sdram_bank_unmap(Ppc4xxSdramBank *bank) -{ - memory_region_del_subregion(get_system_memory(), &bank->container); - memory_region_del_subregion(&bank->container, &bank->ram); - object_unparent(OBJECT(&bank->container)); -} - -static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i, - uint32_t bcr, int enabled) -{ - if (sdram->bank[i].bcr & 1) { - /* First unmap RAM if enabled */ - trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr), - sdram_ddr2_size(sdram->bank[i].bcr)); - sdram_bank_unmap(&sdram->bank[i]); - } - sdram->bank[i].bcr = bcr & 0xffe0ffc1; - if (enabled && (bcr & 1)) { - trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr)); - sdram_bank_map(&sdram->bank[i]); - } -} - -static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram) -{ - int i; - - for (i = 0; i < sdram->nbanks; i++) { - if (sdram->bank[i].size) { - sdram_ddr2_set_bcr(sdram, i, - sdram_ddr2_bcr(sdram->bank[i].base, - sdram->bank[i].size), 1); - } else { - sdram_ddr2_set_bcr(sdram, i, 0, 0); - } - } -} - -static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram) -{ - int i; - - for (i = 0; i < sdram->nbanks; i++) { - if (sdram->bank[i].size) { - sdram_ddr2_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0); - } - } -} - -static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn) -{ - Ppc4xxSdramDdr2State *sdram = opaque; - uint32_t ret = 0; - - switch (dcrn) { - case SDRAM_R0BAS: - case SDRAM_R1BAS: - case SDRAM_R2BAS: - case SDRAM_R3BAS: - if (sdram->bank[dcrn - SDRAM_R0BAS].size) { - ret = sdram_ddr2_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base, - sdram->bank[dcrn - SDRAM_R0BAS].size); - } - break; - case SDRAM_CONF1HB: - case SDRAM_CONF1LL: - case SDRAM_CONFPATHB: - case SDRAM_PLBADDULL: - case SDRAM_PLBADDUHB: - break; - case SDRAM0_CFGADDR: - ret = sdram->addr; - break; - case SDRAM0_CFGDATA: - switch (sdram->addr) { - case 0x14: /* SDRAM_MCSTAT (405EX) */ - case 0x1F: - ret = 0x80000000; - break; - case 0x21: /* SDRAM_MCOPT2 */ - ret = sdram->mcopt2; - break; - case 0x40: /* SDRAM_MB0CF */ - ret = 0x00008001; - break; - case 0x7A: /* SDRAM_DLCR */ - ret = 0x02000000; - break; - case 0xE1: /* SDR0_DDR0 */ - ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1; - break; - default: - break; - } - break; - default: - break; - } - - return ret; -} - -#define SDRAM_DDR2_MCOPT2_DCEN BIT(27) - -static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val) -{ - Ppc4xxSdramDdr2State *sdram = opaque; - - switch (dcrn) { - case SDRAM_R0BAS: - case SDRAM_R1BAS: - case SDRAM_R2BAS: - case SDRAM_R3BAS: - case SDRAM_CONF1HB: - case SDRAM_CONF1LL: - case SDRAM_CONFPATHB: - case SDRAM_PLBADDULL: - case SDRAM_PLBADDUHB: - break; - case SDRAM0_CFGADDR: - sdram->addr = val; - break; - case SDRAM0_CFGDATA: - switch (sdram->addr) { - case 0x00: /* B0CR */ - break; - case 0x21: /* SDRAM_MCOPT2 */ - if (!(sdram->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) && - (val & SDRAM_DDR2_MCOPT2_DCEN)) { - trace_ppc4xx_sdram_enable("enable"); - /* validate all RAM mappings */ - sdram_ddr2_map_bcr(sdram); - sdram->mcopt2 |= SDRAM_DDR2_MCOPT2_DCEN; - } else if ((sdram->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) && - !(val & SDRAM_DDR2_MCOPT2_DCEN)) { - trace_ppc4xx_sdram_enable("disable"); - /* invalidate all RAM mappings */ - sdram_ddr2_unmap_bcr(sdram); - sdram->mcopt2 &= ~SDRAM_DDR2_MCOPT2_DCEN; - } - break; - default: - break; - } - break; - default: - break; - } -} - -static void ppc4xx_sdram_ddr2_reset(DeviceState *dev) -{ - Ppc4xxSdramDdr2State *sdram = PPC4xx_SDRAM_DDR2(dev); - - sdram->addr = 0; - sdram->mcopt2 = 0; -} - -static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp) -{ - Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev); - Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - /* - * SoC also has 4 GiB but that causes problem with 32 bit - * builds (4*GiB overflows the 32 bit ram_addr_t). - */ - const ram_addr_t valid_bank_sizes[] = { - 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, - 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0 - }; - - 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); - - ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - - ppc4xx_dcr_register(dcr, SDRAM_R0BAS, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_R1BAS, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_R2BAS, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_R3BAS, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_CONF1HB, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_PLBADDULL, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_CONF1LL, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_CONFPATHB, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); - ppc4xx_dcr_register(dcr, SDRAM_PLBADDUHB, - s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); -} - -static Property ppc4xx_sdram_ddr2_props[] = { - DEFINE_PROP_LINK("dram", Ppc4xxSdramDdr2State, dram_mr, TYPE_MEMORY_REGION, - MemoryRegion *), - DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdr2State, nbanks, 4), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ppc4xx_sdram_ddr2_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = ppc4xx_sdram_ddr2_realize; - dc->reset = ppc4xx_sdram_ddr2_reset; - /* Reason: only works as function of a ppc4xx SoC */ - dc->user_creatable = false; - device_class_set_props(dc, ppc4xx_sdram_ddr2_props); -} - -void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s) -{ - sdram_ddr2_dcr_write(s, SDRAM0_CFGADDR, 0x21); - sdram_ddr2_dcr_write(s, SDRAM0_CFGDATA, 0x08000000); -} - -static const TypeInfo ppc4xx_types[] = { - { - .name = TYPE_PPC4xx_SDRAM_DDR2, - .parent = TYPE_PPC4xx_DCR_DEVICE, - .instance_size = sizeof(Ppc4xxSdramDdr2State), - .class_init = ppc4xx_sdram_ddr2_class_init, - } -}; -DEFINE_TYPES(ppc4xx_types) - -/*****************************************************************************/ /* PLB to AHB bridge */ enum { AHB_TOP = 0xA4, diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 12af90f244..c1d111465d 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -23,419 +23,10 @@ */ #include "qemu/osdep.h" -#include "qemu/units.h" -#include "sysemu/reset.h" #include "cpu.h" -#include "hw/irq.h" -#include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" #include "hw/qdev-properties.h" -#include "qemu/log.h" -#include "exec/address-spaces.h" -#include "qemu/error-report.h" #include "qapi/error.h" -#include "trace.h" - -/*****************************************************************************/ -/* SDRAM controller */ -enum { - SDRAM0_CFGADDR = 0x010, - SDRAM0_CFGDATA = 0x011, -}; - -/* - * XXX: TOFIX: some patches have made this code become inconsistent: - * there are type inconsistencies, mixing hwaddr, target_ulong - * and uint32_t - */ -static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size) -{ - uint32_t bcr; - - switch (ram_size) { - case 4 * MiB: - bcr = 0; - break; - case 8 * MiB: - bcr = 0x20000; - break; - case 16 * MiB: - bcr = 0x40000; - break; - case 32 * MiB: - bcr = 0x60000; - break; - case 64 * MiB: - bcr = 0x80000; - break; - case 128 * MiB: - bcr = 0xA0000; - break; - case 256 * MiB: - bcr = 0xC0000; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__, - ram_size); - return 0; - } - bcr |= ram_base & 0xFF800000; - bcr |= 1; - - return bcr; -} - -static inline hwaddr sdram_ddr_base(uint32_t bcr) -{ - return bcr & 0xFF800000; -} - -static target_ulong sdram_ddr_size(uint32_t bcr) -{ - target_ulong size; - int sh; - - sh = (bcr >> 17) & 0x7; - if (sh == 7) { - size = -1; - } else { - size = (4 * MiB) << sh; - } - - return size; -} - -static void sdram_ddr_set_bcr(Ppc4xxSdramDdrState *sdram, int i, - uint32_t bcr, int enabled) -{ - if (sdram->bank[i].bcr & 1) { - /* Unmap RAM */ - trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr), - sdram_ddr_size(sdram->bank[i].bcr)); - memory_region_del_subregion(get_system_memory(), - &sdram->bank[i].container); - memory_region_del_subregion(&sdram->bank[i].container, - &sdram->bank[i].ram); - object_unparent(OBJECT(&sdram->bank[i].container)); - } - sdram->bank[i].bcr = bcr & 0xFFDEE001; - if (enabled && (bcr & 1)) { - trace_ppc4xx_sdram_map(sdram_ddr_base(bcr), sdram_ddr_size(bcr)); - memory_region_init(&sdram->bank[i].container, NULL, "sdram-container", - sdram_ddr_size(bcr)); - memory_region_add_subregion(&sdram->bank[i].container, 0, - &sdram->bank[i].ram); - memory_region_add_subregion(get_system_memory(), - sdram_ddr_base(bcr), - &sdram->bank[i].container); - } -} - -static void sdram_ddr_map_bcr(Ppc4xxSdramDdrState *sdram) -{ - int i; - - for (i = 0; i < sdram->nbanks; i++) { - if (sdram->bank[i].size != 0) { - sdram_ddr_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base, - sdram->bank[i].size), 1); - } else { - sdram_ddr_set_bcr(sdram, i, 0, 0); - } - } -} - -static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState *sdram) -{ - int i; - - for (i = 0; i < sdram->nbanks; i++) { - trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr), - sdram_ddr_size(sdram->bank[i].bcr)); - memory_region_del_subregion(get_system_memory(), - &sdram->bank[i].ram); - } -} - -static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn) -{ - Ppc4xxSdramDdrState *sdram = opaque; - uint32_t ret; - - switch (dcrn) { - case SDRAM0_CFGADDR: - ret = sdram->addr; - break; - case SDRAM0_CFGDATA: - switch (sdram->addr) { - case 0x00: /* SDRAM_BESR0 */ - ret = sdram->besr0; - break; - case 0x08: /* SDRAM_BESR1 */ - ret = sdram->besr1; - break; - case 0x10: /* SDRAM_BEAR */ - ret = sdram->bear; - break; - case 0x20: /* SDRAM_CFG */ - ret = sdram->cfg; - break; - case 0x24: /* SDRAM_STATUS */ - ret = sdram->status; - break; - case 0x30: /* SDRAM_RTR */ - ret = sdram->rtr; - break; - case 0x34: /* SDRAM_PMIT */ - ret = sdram->pmit; - break; - case 0x40: /* SDRAM_B0CR */ - ret = sdram->bank[0].bcr; - break; - case 0x44: /* SDRAM_B1CR */ - ret = sdram->bank[1].bcr; - break; - case 0x48: /* SDRAM_B2CR */ - ret = sdram->bank[2].bcr; - break; - case 0x4C: /* SDRAM_B3CR */ - ret = sdram->bank[3].bcr; - break; - case 0x80: /* SDRAM_TR */ - ret = -1; /* ? */ - break; - case 0x94: /* SDRAM_ECCCFG */ - ret = sdram->ecccfg; - break; - case 0x98: /* SDRAM_ECCESR */ - ret = sdram->eccesr; - break; - default: /* Error */ - ret = -1; - break; - } - break; - default: - /* Avoid gcc warning */ - ret = 0; - break; - } - - return ret; -} - -static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val) -{ - Ppc4xxSdramDdrState *sdram = opaque; - - switch (dcrn) { - case SDRAM0_CFGADDR: - sdram->addr = val; - break; - case SDRAM0_CFGDATA: - switch (sdram->addr) { - case 0x00: /* SDRAM_BESR0 */ - sdram->besr0 &= ~val; - break; - case 0x08: /* SDRAM_BESR1 */ - sdram->besr1 &= ~val; - break; - case 0x10: /* SDRAM_BEAR */ - sdram->bear = val; - break; - case 0x20: /* SDRAM_CFG */ - val &= 0xFFE00000; - if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) { - trace_ppc4xx_sdram_enable("enable"); - /* validate all RAM mappings */ - sdram_ddr_map_bcr(sdram); - sdram->status &= ~0x80000000; - } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) { - trace_ppc4xx_sdram_enable("disable"); - /* invalidate all RAM mappings */ - sdram_ddr_unmap_bcr(sdram); - sdram->status |= 0x80000000; - } - if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) { - sdram->status |= 0x40000000; - } else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) { - sdram->status &= ~0x40000000; - } - sdram->cfg = val; - break; - case 0x24: /* SDRAM_STATUS */ - /* Read-only register */ - break; - case 0x30: /* SDRAM_RTR */ - sdram->rtr = val & 0x3FF80000; - break; - case 0x34: /* SDRAM_PMIT */ - sdram->pmit = (val & 0xF8000000) | 0x07C00000; - break; - case 0x40: /* SDRAM_B0CR */ - sdram_ddr_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000); - break; - case 0x44: /* SDRAM_B1CR */ - sdram_ddr_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000); - break; - case 0x48: /* SDRAM_B2CR */ - sdram_ddr_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000); - break; - case 0x4C: /* SDRAM_B3CR */ - sdram_ddr_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000); - break; - case 0x80: /* SDRAM_TR */ - sdram->tr = val & 0x018FC01F; - break; - case 0x94: /* SDRAM_ECCCFG */ - sdram->ecccfg = val & 0x00F00000; - break; - case 0x98: /* SDRAM_ECCESR */ - val &= 0xFFF0F000; - if (sdram->eccesr == 0 && val != 0) { - qemu_irq_raise(sdram->irq); - } else if (sdram->eccesr != 0 && val == 0) { - qemu_irq_lower(sdram->irq); - } - sdram->eccesr = val; - break; - default: /* Error */ - break; - } - break; - } -} - -static void ppc4xx_sdram_ddr_reset(DeviceState *dev) -{ - Ppc4xxSdramDdrState *sdram = PPC4xx_SDRAM_DDR(dev); - - sdram->addr = 0; - sdram->bear = 0; - sdram->besr0 = 0; /* No error */ - sdram->besr1 = 0; /* No error */ - sdram->cfg = 0; - sdram->ecccfg = 0; /* No ECC */ - sdram->eccesr = 0; /* No error */ - sdram->pmit = 0x07C00000; - sdram->rtr = 0x05F00000; - sdram->tr = 0x00854009; - /* We pre-initialize RAM banks */ - sdram->status = 0; - sdram->cfg = 0x00800000; -} - -static void ppc4xx_sdram_ddr_realize(DeviceState *dev, Error **errp) -{ - 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 - }; - - 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); -} - -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_ddr_enable(Ppc4xxSdramDdrState *s) -{ - sdram_ddr_dcr_write(s, SDRAM0_CFGADDR, 0x20); - sdram_ddr_dcr_write(s, SDRAM0_CFGDATA, 0x80000000); -} - -/* - * Split RAM between SDRAM banks. - * - * sdram_bank_sizes[] must be in descending order, that is sizes[i] > sizes[i+1] - * and must be 0-terminated. - * - * The 4xx SDRAM controller supports a small number of banks, and each bank - * must be one of a small set of sizes. The number of banks and the supported - * sizes varies by SoC. - */ -void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, - Ppc4xxSdramBank ram_banks[], - const ram_addr_t sdram_bank_sizes[]) -{ - ram_addr_t size_left = memory_region_size(ram); - ram_addr_t base = 0; - ram_addr_t bank_size; - int i; - int j; - - for (i = 0; i < nr_banks; i++) { - for (j = 0; sdram_bank_sizes[j] != 0; j++) { - bank_size = sdram_bank_sizes[j]; - if (bank_size <= size_left) { - char name[32]; - - ram_banks[i].base = base; - ram_banks[i].size = bank_size; - base += bank_size; - size_left -= bank_size; - snprintf(name, sizeof(name), "ppc4xx.sdram%d", i); - memory_region_init_alias(&ram_banks[i].ram, NULL, name, ram, - ram_banks[i].base, ram_banks[i].size); - break; - } - } - if (!size_left) { - /* No need to use the remaining banks. */ - break; - } - } - - if (size_left) { - ram_addr_t used_size = memory_region_size(ram) - size_left; - GString *s = g_string_new(NULL); - - for (i = 0; sdram_bank_sizes[i]; i++) { - g_string_append_printf(s, "%" PRIi64 "%s", - sdram_bank_sizes[i] / MiB, - sdram_bank_sizes[i + 1] ? ", " : ""); - } - error_report("at most %d bank%s of %s MiB each supported", - nr_banks, nr_banks == 1 ? "" : "s", s->str); - error_printf("Possible valid RAM size: %" PRIi64 " MiB\n", - used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB); - - g_string_free(s, true); - exit(EXIT_FAILURE); - } -} /*****************************************************************************/ /* MAL */ @@ -963,11 +554,6 @@ static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data) 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), diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c new file mode 100644 index 0000000000..8d7137faf3 --- /dev/null +++ b/hw/ppc/ppc4xx_sdram.c @@ -0,0 +1,757 @@ +/* + * QEMU PowerPC 4xx embedded processors SDRAM controller emulation + * + * DDR SDRAM controller: + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * DDR2 SDRAM controller: + * Copyright (c) 2012 François Revol + * Copyright (c) 2016-2019 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "exec/address-spaces.h" /* get_system_memory() */ +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/ppc/ppc4xx.h" +#include "trace.h" + +/*****************************************************************************/ +/* Shared functions */ + +/* + * Split RAM between SDRAM banks. + * + * sdram_bank_sizes[] must be in descending order, that is sizes[i] > sizes[i+1] + * and must be 0-terminated. + * + * The 4xx SDRAM controller supports a small number of banks, and each bank + * must be one of a small set of sizes. The number of banks and the supported + * sizes varies by SoC. + */ +static bool ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, + Ppc4xxSdramBank ram_banks[], + const ram_addr_t sdram_bank_sizes[], + Error **errp) +{ + ERRP_GUARD(); + ram_addr_t size_left = memory_region_size(ram); + ram_addr_t base = 0; + ram_addr_t bank_size; + int i; + int j; + + for (i = 0; i < nr_banks; i++) { + for (j = 0; sdram_bank_sizes[j] != 0; j++) { + bank_size = sdram_bank_sizes[j]; + if (bank_size <= size_left) { + char name[32]; + + ram_banks[i].base = base; + ram_banks[i].size = bank_size; + base += bank_size; + size_left -= bank_size; + snprintf(name, sizeof(name), "ppc4xx.sdram%d", i); + memory_region_init_alias(&ram_banks[i].ram, NULL, name, ram, + ram_banks[i].base, ram_banks[i].size); + break; + } + } + if (!size_left) { + /* No need to use the remaining banks. */ + break; + } + } + + if (size_left) { + ram_addr_t used_size = memory_region_size(ram) - size_left; + GString *s = g_string_new(NULL); + + for (i = 0; sdram_bank_sizes[i]; i++) { + g_string_append_printf(s, "%" PRIi64 "%s", + sdram_bank_sizes[i] / MiB, + sdram_bank_sizes[i + 1] ? ", " : ""); + } + error_setg(errp, "Invalid SDRAM banks"); + error_append_hint(errp, "at most %d bank%s of %s MiB each supported\n", + nr_banks, nr_banks == 1 ? "" : "s", s->str); + error_append_hint(errp, "Possible valid RAM size: %" PRIi64 " MiB\n", + used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB); + + g_string_free(s, true); + return false; + } + return true; +} + +static void sdram_bank_map(Ppc4xxSdramBank *bank) +{ + trace_ppc4xx_sdram_map(bank->base, bank->size); + memory_region_init(&bank->container, NULL, "sdram-container", bank->size); + memory_region_add_subregion(&bank->container, 0, &bank->ram); + memory_region_add_subregion(get_system_memory(), bank->base, + &bank->container); +} + +static void sdram_bank_unmap(Ppc4xxSdramBank *bank) +{ + trace_ppc4xx_sdram_unmap(bank->base, bank->size); + memory_region_del_subregion(get_system_memory(), &bank->container); + memory_region_del_subregion(&bank->container, &bank->ram); + object_unparent(OBJECT(&bank->container)); +} + +static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, uint32_t bcr, + hwaddr base, hwaddr size, int enabled) +{ + if (memory_region_is_mapped(&bank->container)) { + sdram_bank_unmap(bank); + } + bank->bcr = bcr; + bank->base = base; + bank->size = size; + if (enabled && (bcr & 1)) { + sdram_bank_map(bank); + } +} + +enum { + SDRAM0_CFGADDR = 0x010, + SDRAM0_CFGDATA = 0x011, +}; + +/*****************************************************************************/ +/* DDR SDRAM controller */ +#define SDRAM_DDR_BCR_MASK 0xFFDEE001 + +static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size) +{ + uint32_t bcr; + + switch (ram_size) { + case 4 * MiB: + bcr = 0; + break; + case 8 * MiB: + bcr = 0x20000; + break; + case 16 * MiB: + bcr = 0x40000; + break; + case 32 * MiB: + bcr = 0x60000; + break; + case 64 * MiB: + bcr = 0x80000; + break; + case 128 * MiB: + bcr = 0xA0000; + break; + case 256 * MiB: + bcr = 0xC0000; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__, + ram_size); + return 0; + } + bcr |= ram_base & 0xFF800000; + bcr |= 1; + + return bcr; +} + +static inline hwaddr sdram_ddr_base(uint32_t bcr) +{ + return bcr & 0xFF800000; +} + +static hwaddr sdram_ddr_size(uint32_t bcr) +{ + hwaddr size; + int sh; + + sh = (bcr >> 17) & 0x7; + if (sh == 7) { + size = -1; + } else { + size = (4 * MiB) << sh; + } + + return size; +} + +static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn) +{ + Ppc4xxSdramDdrState *s = opaque; + uint32_t ret; + + switch (dcrn) { + case SDRAM0_CFGADDR: + ret = s->addr; + break; + case SDRAM0_CFGDATA: + switch (s->addr) { + case 0x00: /* SDRAM_BESR0 */ + ret = s->besr0; + break; + case 0x08: /* SDRAM_BESR1 */ + ret = s->besr1; + break; + case 0x10: /* SDRAM_BEAR */ + ret = s->bear; + break; + case 0x20: /* SDRAM_CFG */ + ret = s->cfg; + break; + case 0x24: /* SDRAM_STATUS */ + ret = s->status; + break; + case 0x30: /* SDRAM_RTR */ + ret = s->rtr; + break; + case 0x34: /* SDRAM_PMIT */ + ret = s->pmit; + break; + case 0x40: /* SDRAM_B0CR */ + ret = s->bank[0].bcr; + break; + case 0x44: /* SDRAM_B1CR */ + ret = s->bank[1].bcr; + break; + case 0x48: /* SDRAM_B2CR */ + ret = s->bank[2].bcr; + break; + case 0x4C: /* SDRAM_B3CR */ + ret = s->bank[3].bcr; + break; + case 0x80: /* SDRAM_TR */ + ret = -1; /* ? */ + break; + case 0x94: /* SDRAM_ECCCFG */ + ret = s->ecccfg; + break; + case 0x98: /* SDRAM_ECCESR */ + ret = s->eccesr; + break; + default: /* Error */ + ret = -1; + break; + } + break; + default: + /* Avoid gcc warning */ + ret = 0; + break; + } + + return ret; +} + +static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val) +{ + Ppc4xxSdramDdrState *s = opaque; + int i; + + switch (dcrn) { + case SDRAM0_CFGADDR: + s->addr = val; + break; + case SDRAM0_CFGDATA: + switch (s->addr) { + case 0x00: /* SDRAM_BESR0 */ + s->besr0 &= ~val; + break; + case 0x08: /* SDRAM_BESR1 */ + s->besr1 &= ~val; + break; + case 0x10: /* SDRAM_BEAR */ + s->bear = val; + break; + case 0x20: /* SDRAM_CFG */ + val &= 0xFFE00000; + if (!(s->cfg & 0x80000000) && (val & 0x80000000)) { + trace_ppc4xx_sdram_enable("enable"); + /* validate all RAM mappings */ + for (i = 0; i < s->nbanks; i++) { + if (s->bank[i].size) { + sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr, + s->bank[i].base, s->bank[i].size, + 1); + } + } + s->status &= ~0x80000000; + } else if ((s->cfg & 0x80000000) && !(val & 0x80000000)) { + trace_ppc4xx_sdram_enable("disable"); + /* invalidate all RAM mappings */ + for (i = 0; i < s->nbanks; i++) { + if (s->bank[i].size) { + sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr, + s->bank[i].base, s->bank[i].size, + 0); + } + } + s->status |= 0x80000000; + } + if (!(s->cfg & 0x40000000) && (val & 0x40000000)) { + s->status |= 0x40000000; + } else if ((s->cfg & 0x40000000) && !(val & 0x40000000)) { + s->status &= ~0x40000000; + } + s->cfg = val; + break; + case 0x24: /* SDRAM_STATUS */ + /* Read-only register */ + break; + case 0x30: /* SDRAM_RTR */ + s->rtr = val & 0x3FF80000; + break; + case 0x34: /* SDRAM_PMIT */ + s->pmit = (val & 0xF8000000) | 0x07C00000; + break; + case 0x40: /* SDRAM_B0CR */ + case 0x44: /* SDRAM_B1CR */ + case 0x48: /* SDRAM_B2CR */ + case 0x4C: /* SDRAM_B3CR */ + i = (s->addr - 0x40) / 4; + val &= SDRAM_DDR_BCR_MASK; + if (s->bank[i].size) { + sdram_bank_set_bcr(&s->bank[i], val, + sdram_ddr_base(val), sdram_ddr_size(val), + s->cfg & 0x80000000); + } + break; + case 0x80: /* SDRAM_TR */ + s->tr = val & 0x018FC01F; + break; + case 0x94: /* SDRAM_ECCCFG */ + s->ecccfg = val & 0x00F00000; + break; + case 0x98: /* SDRAM_ECCESR */ + val &= 0xFFF0F000; + if (s->eccesr == 0 && val != 0) { + qemu_irq_raise(s->irq); + } else if (s->eccesr != 0 && val == 0) { + qemu_irq_lower(s->irq); + } + s->eccesr = val; + break; + default: /* Error */ + break; + } + break; + } +} + +static void ppc4xx_sdram_ddr_reset(DeviceState *dev) +{ + Ppc4xxSdramDdrState *s = PPC4xx_SDRAM_DDR(dev); + + s->addr = 0; + s->bear = 0; + s->besr0 = 0; /* No error */ + s->besr1 = 0; /* No error */ + s->cfg = 0; + s->ecccfg = 0; /* No ECC */ + s->eccesr = 0; /* No error */ + s->pmit = 0x07C00000; + s->rtr = 0x05F00000; + s->tr = 0x00854009; + /* We pre-initialize RAM banks */ + s->status = 0; + s->cfg = 0x00800000; +} + +static void ppc4xx_sdram_ddr_realize(DeviceState *dev, Error **errp) +{ + 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 + }; + int i; + + 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; + } + if (!ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, + valid_bank_sizes, errp)) { + return; + } + for (i = 0; i < s->nbanks; i++) { + if (s->bank[i].size) { + s->bank[i].bcr = sdram_ddr_bcr(s->bank[i].base, s->bank[i].size); + sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr, + s->bank[i].base, s->bank[i].size, 0); + } else { + sdram_bank_set_bcr(&s->bank[i], 0, 0, 0, 0); + } + trace_ppc4xx_sdram_init(sdram_ddr_base(s->bank[i].bcr), + sdram_ddr_size(s->bank[i].bcr), + s->bank[i].bcr); + } + + 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); +} + +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_ddr_enable(Ppc4xxSdramDdrState *s) +{ + sdram_ddr_dcr_write(s, SDRAM0_CFGADDR, 0x20); + sdram_ddr_dcr_write(s, SDRAM0_CFGDATA, 0x80000000); +} + +/*****************************************************************************/ +/* DDR2 SDRAM controller */ +#define SDRAM_DDR2_BCR_MASK 0xffe0ffc1 + +enum { + SDRAM_R0BAS = 0x40, + SDRAM_R1BAS, + SDRAM_R2BAS, + SDRAM_R3BAS, + SDRAM_CONF1HB = 0x45, + SDRAM_PLBADDULL = 0x4a, + SDRAM_CONF1LL = 0x4b, + SDRAM_CONFPATHB = 0x4f, + SDRAM_PLBADDUHB = 0x50, +}; + +static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size) +{ + uint32_t bcr; + + switch (ram_size) { + case 8 * MiB: + bcr = 0xffc0; + break; + case 16 * MiB: + bcr = 0xff80; + break; + case 32 * MiB: + bcr = 0xff00; + break; + case 64 * MiB: + bcr = 0xfe00; + break; + case 128 * MiB: + bcr = 0xfc00; + break; + case 256 * MiB: + bcr = 0xf800; + break; + case 512 * MiB: + bcr = 0xf000; + break; + case 1 * GiB: + bcr = 0xe000; + break; + case 2 * GiB: + bcr = 0xc000; + break; + case 4 * GiB: + bcr = 0x8000; + break; + default: + error_report("invalid RAM size " TARGET_FMT_plx, ram_size); + return 0; + } + bcr |= ram_base >> 2 & 0xffe00000; + bcr |= 1; + + return bcr; +} + +static inline hwaddr sdram_ddr2_base(uint32_t bcr) +{ + return (bcr & 0xffe00000) << 2; +} + +static hwaddr sdram_ddr2_size(uint32_t bcr) +{ + hwaddr size; + int sh; + + sh = 1024 - ((bcr >> 6) & 0x3ff); + size = 8 * MiB * sh; + + return size; +} + +static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn) +{ + Ppc4xxSdramDdr2State *s = opaque; + uint32_t ret = 0; + + switch (dcrn) { + case SDRAM_R0BAS: + case SDRAM_R1BAS: + case SDRAM_R2BAS: + case SDRAM_R3BAS: + if (s->bank[dcrn - SDRAM_R0BAS].size) { + ret = sdram_ddr2_bcr(s->bank[dcrn - SDRAM_R0BAS].base, + s->bank[dcrn - SDRAM_R0BAS].size); + } + break; + case SDRAM_CONF1HB: + case SDRAM_CONF1LL: + case SDRAM_CONFPATHB: + case SDRAM_PLBADDULL: + case SDRAM_PLBADDUHB: + break; + case SDRAM0_CFGADDR: + ret = s->addr; + break; + case SDRAM0_CFGDATA: + switch (s->addr) { + case 0x14: /* SDRAM_MCSTAT (405EX) */ + case 0x1F: + ret = 0x80000000; + break; + case 0x21: /* SDRAM_MCOPT2 */ + ret = s->mcopt2; + break; + case 0x40: /* SDRAM_MB0CF */ + ret = 0x00008001; + break; + case 0x7A: /* SDRAM_DLCR */ + ret = 0x02000000; + break; + case 0xE1: /* SDR0_DDR0 */ + ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1; + break; + default: + break; + } + break; + default: + break; + } + + return ret; +} + +#define SDRAM_DDR2_MCOPT2_DCEN BIT(27) + +static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val) +{ + Ppc4xxSdramDdr2State *s = opaque; + int i; + + switch (dcrn) { + case SDRAM_R0BAS: + case SDRAM_R1BAS: + case SDRAM_R2BAS: + case SDRAM_R3BAS: + case SDRAM_CONF1HB: + case SDRAM_CONF1LL: + case SDRAM_CONFPATHB: + case SDRAM_PLBADDULL: + case SDRAM_PLBADDUHB: + break; + case SDRAM0_CFGADDR: + s->addr = val; + break; + case SDRAM0_CFGDATA: + switch (s->addr) { + case 0x00: /* B0CR */ + break; + case 0x21: /* SDRAM_MCOPT2 */ + if (!(s->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) && + (val & SDRAM_DDR2_MCOPT2_DCEN)) { + trace_ppc4xx_sdram_enable("enable"); + /* validate all RAM mappings */ + for (i = 0; i < s->nbanks; i++) { + if (s->bank[i].size) { + sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr, + s->bank[i].base, s->bank[i].size, + 1); + } + } + s->mcopt2 |= SDRAM_DDR2_MCOPT2_DCEN; + } else if ((s->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) && + !(val & SDRAM_DDR2_MCOPT2_DCEN)) { + trace_ppc4xx_sdram_enable("disable"); + /* invalidate all RAM mappings */ + for (i = 0; i < s->nbanks; i++) { + if (s->bank[i].size) { + sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr, + s->bank[i].base, s->bank[i].size, + 0); + } + } + s->mcopt2 &= ~SDRAM_DDR2_MCOPT2_DCEN; + } + break; + default: + break; + } + break; + default: + break; + } +} + +static void ppc4xx_sdram_ddr2_reset(DeviceState *dev) +{ + Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev); + + s->addr = 0; + s->mcopt2 = 0; +} + +static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp) +{ + Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + /* + * SoC also has 4 GiB but that causes problem with 32 bit + * builds (4*GiB overflows the 32 bit ram_addr_t). + */ + const ram_addr_t valid_bank_sizes[] = { + 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, + 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0 + }; + int i; + + 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; + } + if (!ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, + valid_bank_sizes, errp)) { + return; + } + for (i = 0; i < s->nbanks; i++) { + if (s->bank[i].size) { + s->bank[i].bcr = sdram_ddr2_bcr(s->bank[i].base, s->bank[i].size); + s->bank[i].bcr &= SDRAM_DDR2_BCR_MASK; + sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr, + s->bank[i].base, s->bank[i].size, 0); + } else { + sdram_bank_set_bcr(&s->bank[i], 0, 0, 0, 0); + } + trace_ppc4xx_sdram_init(sdram_ddr2_base(s->bank[i].bcr), + sdram_ddr2_size(s->bank[i].bcr), + s->bank[i].bcr); + } + + ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + + ppc4xx_dcr_register(dcr, SDRAM_R0BAS, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_R1BAS, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_R2BAS, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_R3BAS, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_CONF1HB, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_PLBADDULL, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_CONF1LL, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_CONFPATHB, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); + ppc4xx_dcr_register(dcr, SDRAM_PLBADDUHB, + s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write); +} + +static Property ppc4xx_sdram_ddr2_props[] = { + DEFINE_PROP_LINK("dram", Ppc4xxSdramDdr2State, dram_mr, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdr2State, nbanks, 4), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc4xx_sdram_ddr2_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc4xx_sdram_ddr2_realize; + dc->reset = ppc4xx_sdram_ddr2_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; + device_class_set_props(dc, ppc4xx_sdram_ddr2_props); +} + +void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s) +{ + sdram_ddr2_dcr_write(s, SDRAM0_CFGADDR, 0x21); + sdram_ddr2_dcr_write(s, SDRAM0_CFGDATA, 0x08000000); +} + +static const TypeInfo ppc4xx_sdram_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_SDRAM_DDR2, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc4xxSdramDdr2State), + .class_init = ppc4xx_sdram_ddr2_class_init, + } +}; + +DEFINE_TYPES(ppc4xx_sdram_types) diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index f08714f2ec..fcbe4c5837 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -50,8 +50,6 @@ /* SMP is not enabled, for now */ #define MAX_CPUS 1 -#define MAX_IDE_BUS 2 - #define CFG_ADDR 0xf0000510 #define KERNEL_LOAD_ADDR 0x01000000 diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 891206e893..925ff523cc 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -490,6 +490,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr, env->msr |= (1ULL << MSR_EE); hreg_compute_hflags(env); + ppc_maybe_interrupt(env); if (spapr_cpu->prod) { spapr_cpu->prod = false; @@ -500,6 +501,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr, cs->halted = 1; cs->exception_index = EXCP_HLT; cs->exit_request = 1; + ppc_maybe_interrupt(env); } return H_SUCCESS; @@ -521,6 +523,7 @@ static target_ulong h_confer_self(PowerPCCPU *cpu) cs->halted = 1; cs->exception_index = EXCP_HALTED; cs->exit_request = 1; + ppc_maybe_interrupt(&cpu->env); return H_SUCCESS; } @@ -633,6 +636,7 @@ static target_ulong h_prod(PowerPCCPU *cpu, SpaprMachineState *spapr, spapr_cpu = spapr_cpu_state(tcpu); spapr_cpu->prod = true; cs->halted = 0; + ppc_maybe_interrupt(&cpu->env); qemu_cpu_kick(cs); return H_SUCCESS; @@ -1669,6 +1673,7 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, spapr_cpu->in_nested = true; hreg_compute_hflags(env); + ppc_maybe_interrupt(env); tlb_flush(cs); env->reserve_addr = -1; /* Reset the reservation */ @@ -1810,6 +1815,7 @@ out_restore_l1: spapr_cpu->in_nested = false; hreg_compute_hflags(env); + ppc_maybe_interrupt(env); tlb_flush(cs); env->reserve_addr = -1; /* Reset the reservation */ diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index d58b65e88f..3f664ea02c 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -214,9 +214,9 @@ static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr, * guest. * For the same reason, set PSSCR_EC. */ - ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm); env->spr[SPR_PSSCR] |= PSSCR_EC; cs->halted = 1; + ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm); kvmppc_set_reg_ppc_online(cpu, 0); qemu_cpu_kick(cs); } diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index a07d5aca0f..f670e8906c 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -127,7 +127,7 @@ ppc40x_set_tb_clk(uint32_t value) "new frequency %" PRIu32 ppc40x_timers_init(uint32_t value) "frequency %" PRIu32 ppc_irq_set(void *env, uint32_t pin, uint32_t level) "env [%p] pin %d level %d" -ppc_irq_set_exit(void *env, uint32_t n_IRQ, uint32_t level, uint32_t pending, uint32_t request) "env [%p] n_IRQ %d level %d => pending 0x%08" PRIx32 " req 0x%08" PRIx32 +ppc_irq_set_exit(void *env, uint32_t irq, uint32_t level, uint32_t pending, uint32_t request) "env [%p] irq 0x%05" PRIx32 " level %d => pending 0x%08" PRIx32 " req 0x%08" PRIx32 ppc_irq_set_state(const char *name, uint32_t level) "\"%s\" level %d" ppc_irq_reset(const char *name) "%s" ppc_irq_cpu(const char *action) "%s" @@ -179,3 +179,4 @@ ppc405ep_clocks_setup(const char *trace) "%s" ppc4xx_sdram_enable(const char *trace) "%s SDRAM controller" ppc4xx_sdram_unmap(uint64_t addr, uint64_t size) "Unmap RAM area 0x%" PRIx64 " size 0x%" PRIx64 ppc4xx_sdram_map(uint64_t addr, uint64_t size) "Map RAM area 0x%" PRIx64 " size 0x%" PRIx64 +ppc4xx_sdram_init(uint64_t base, uint64_t size, uint32_t bcr) "Init RAM area 0x%" PRIx64 " size 0x%" PRIx64 " bcr 0x%x" diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c index 728ba24547..8dfe92d8df 100644 --- a/hw/s390x/pv.c +++ b/hw/s390x/pv.c @@ -50,7 +50,7 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) * This macro lets us pass the command as a string to the function so * we can print it on an error. */ -#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data); +#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data) #define s390_pv_cmd_exit(cmd, data) \ { \ int rc; \ diff --git a/hw/s390x/tod-kvm.c b/hw/s390x/tod-kvm.c index 9d0cbfbce2..e2202dae2d 100644 --- a/hw/s390x/tod-kvm.c +++ b/hw/s390x/tod-kvm.c @@ -13,6 +13,7 @@ #include "qemu/module.h" #include "sysemu/runstate.h" #include "hw/s390x/tod.h" +#include "hw/s390x/pv.h" #include "kvm/kvm_s390x.h" static void kvm_s390_get_tod_raw(S390TOD *tod, Error **errp) @@ -84,6 +85,14 @@ static void kvm_s390_tod_vm_state_change(void *opaque, bool running, S390TODState *td = opaque; Error *local_err = NULL; + /* + * Under PV, the clock is under ultravisor control, hence we cannot restore + * it on resume. + */ + if (s390_is_pv()) { + return; + } + if (running && td->stopped) { /* Set the old TOD when running the VM - start the TOD clock. */ kvm_s390_set_tod_raw(&td->base, &local_err); diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h index e8c753d6d1..964570f8e8 100644 --- a/hw/sd/sdhci-internal.h +++ b/hw/sd/sdhci-internal.h @@ -288,26 +288,6 @@ enum { extern const VMStateDescription sdhci_vmstate; - -#define ESDHC_MIX_CTRL 0x48 - -#define ESDHC_VENDOR_SPEC 0xc0 -#define ESDHC_IMX_FRC_SDCLK_ON (1 << 8) - -#define ESDHC_DLL_CTRL 0x60 - -#define ESDHC_TUNING_CTRL 0xcc -#define ESDHC_TUNE_CTRL_STATUS 0x68 -#define ESDHC_WTMK_LVL 0x44 - -/* Undocumented register used by guests working around erratum ERR004536 */ -#define ESDHC_UNDOCUMENTED_REG27 0x6c - -#define ESDHC_CTRL_4BITBUS (0x1 << 1) -#define ESDHC_CTRL_8BITBUS (0x2 << 1) - -#define ESDHC_PRNSTS_SDSTB (1 << 3) - /* * Default SD/MMC host controller features information, which will be * presented in CAPABILITIES register of generic SD host controller at reset. diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 0e5e988927..306070c872 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1577,6 +1577,25 @@ static const TypeInfo sdhci_bus_info = { /* --- qdev i.MX eSDHC --- */ +#define USDHC_MIX_CTRL 0x48 + +#define USDHC_VENDOR_SPEC 0xc0 +#define USDHC_IMX_FRC_SDCLK_ON (1 << 8) + +#define USDHC_DLL_CTRL 0x60 + +#define USDHC_TUNING_CTRL 0xcc +#define USDHC_TUNE_CTRL_STATUS 0x68 +#define USDHC_WTMK_LVL 0x44 + +/* Undocumented register used by guests working around erratum ERR004536 */ +#define USDHC_UNDOCUMENTED_REG27 0x6c + +#define USDHC_CTRL_4BITBUS (0x1 << 1) +#define USDHC_CTRL_8BITBUS (0x2 << 1) + +#define USDHC_PRNSTS_SDSTB (1 << 3) + static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size) { SDHCIState *s = SYSBUS_SDHCI(opaque); @@ -1596,11 +1615,11 @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size) hostctl1 = SDHC_DMA_TYPE(s->hostctl1) << (8 - 3); if (s->hostctl1 & SDHC_CTRL_8BITBUS) { - hostctl1 |= ESDHC_CTRL_8BITBUS; + hostctl1 |= USDHC_CTRL_8BITBUS; } if (s->hostctl1 & SDHC_CTRL_4BITBUS) { - hostctl1 |= ESDHC_CTRL_4BITBUS; + hostctl1 |= USDHC_CTRL_4BITBUS; } ret = hostctl1; @@ -1611,21 +1630,21 @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size) case SDHC_PRNSTS: /* Add SDSTB (SD Clock Stable) bit to PRNSTS */ - ret = sdhci_read(opaque, offset, size) & ~ESDHC_PRNSTS_SDSTB; + ret = sdhci_read(opaque, offset, size) & ~USDHC_PRNSTS_SDSTB; if (s->clkcon & SDHC_CLOCK_INT_STABLE) { - ret |= ESDHC_PRNSTS_SDSTB; + ret |= USDHC_PRNSTS_SDSTB; } break; - case ESDHC_VENDOR_SPEC: + case USDHC_VENDOR_SPEC: ret = s->vendor_spec; break; - case ESDHC_DLL_CTRL: - case ESDHC_TUNE_CTRL_STATUS: - case ESDHC_UNDOCUMENTED_REG27: - case ESDHC_TUNING_CTRL: - case ESDHC_MIX_CTRL: - case ESDHC_WTMK_LVL: + case USDHC_DLL_CTRL: + case USDHC_TUNE_CTRL_STATUS: + case USDHC_UNDOCUMENTED_REG27: + case USDHC_TUNING_CTRL: + case USDHC_MIX_CTRL: + case USDHC_WTMK_LVL: ret = 0; break; } @@ -1641,18 +1660,18 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) uint32_t value = (uint32_t)val; switch (offset) { - case ESDHC_DLL_CTRL: - case ESDHC_TUNE_CTRL_STATUS: - case ESDHC_UNDOCUMENTED_REG27: - case ESDHC_TUNING_CTRL: - case ESDHC_WTMK_LVL: + case USDHC_DLL_CTRL: + case USDHC_TUNE_CTRL_STATUS: + case USDHC_UNDOCUMENTED_REG27: + case USDHC_TUNING_CTRL: + case USDHC_WTMK_LVL: break; - case ESDHC_VENDOR_SPEC: + case USDHC_VENDOR_SPEC: s->vendor_spec = value; switch (s->vendor) { case SDHCI_VENDOR_IMX: - if (value & ESDHC_IMX_FRC_SDCLK_ON) { + if (value & USDHC_IMX_FRC_SDCLK_ON) { s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF; } else { s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF; @@ -1721,12 +1740,12 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) * Second, split "Data Transfer Width" from bits 2 and 1 in to * bits 5 and 1 */ - if (value & ESDHC_CTRL_8BITBUS) { + if (value & USDHC_CTRL_8BITBUS) { hostctl1 |= SDHC_CTRL_8BITBUS; } - if (value & ESDHC_CTRL_4BITBUS) { - hostctl1 |= ESDHC_CTRL_4BITBUS; + if (value & USDHC_CTRL_4BITBUS) { + hostctl1 |= USDHC_CTRL_4BITBUS; } /* @@ -1749,7 +1768,7 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) sdhci_write(opaque, offset, value, size); break; - case ESDHC_MIX_CTRL: + case USDHC_MIX_CTRL: /* * So, when SD/MMC stack in Linux tries to write to "Transfer * Mode Register", ESDHC i.MX quirk code will translate it diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 0e27715ac4..387181ff77 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -66,7 +66,6 @@ #define PBM_PCI_IO_BASE (PBM_SPECIAL_BASE + 0x02000000ULL) #define PROM_FILENAME "openbios-sparc64" #define NVRAM_SIZE 0x2000 -#define MAX_IDE_BUS 2 #define BIOS_CFG_IOPORT 0x510 #define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) #define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 5831395cef..1cac1cd435 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -14,7 +14,7 @@ #include "qemu/error-report.h" #include <wchar.h> #include <dirent.h> - +#include <glib/gstdio.h> #include <sys/statvfs.h> @@ -1622,7 +1622,7 @@ static void usb_mtp_write_data(MTPState *s, uint32_t handle) if (s->dataset.filename) { path = g_strdup_printf("%s/%s", parent->path, s->dataset.filename); if (s->dataset.format == FMT_ASSOCIATION) { - ret = mkdir(path, mask); + ret = g_mkdir(path, mask); if (!ret) { usb_mtp_queue_result(s, RES_OK, d->trans, 3, QEMU_STORAGE_ID, diff --git a/hw/usb/vt82c686-uhci-pci.c b/hw/usb/vt82c686-uhci-pci.c index 0bf2b72ff0..46a901f56f 100644 --- a/hw/usb/vt82c686-uhci-pci.c +++ b/hw/usb/vt82c686-uhci-pci.c @@ -31,7 +31,7 @@ static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) static UHCIInfo uhci_info[] = { { - .name = "vt82c686b-usb-uhci", + .name = TYPE_VT82C686B_USB_UHCI, .vendor_id = PCI_VENDOR_ID_VIA, .device_id = PCI_DEVICE_ID_VIA_UHCI, .revision = 0x01, @@ -45,7 +45,7 @@ static UHCIInfo uhci_info[] = { static const TypeInfo vt82c686b_usb_uhci_type_info = { .parent = TYPE_UHCI, - .name = "vt82c686b-usb-uhci", + .name = TYPE_VT82C686B_USB_UHCI, .class_init = uhci_data_class_init, .class_data = uhci_info, }; |