mirror of https://github.com/xemu-project/xemu.git
ppc patch queue for 2022-10-18:
This queue contains improvements in the e500 and ppc4xx boards, changes in the maintainership of the project, a new QMP/HMP command and bug fixes: - Cedric is stepping back from qemu-ppc maintainership; - ppc4xx_sdram: QOMification and clean ups; - e500: add new types of flash and clean ups; - QMP/HMP: introduce dumpdtb command; - spapr_pci, booke doorbell interrupt and xvcmp* bit fixes; The 'dumpdtb' implementation is also making changes to RISC-V files that were acked by Alistair Francis and are being included in this queue. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCY02qEgAKCRA82cqW3gMx ZIadAQCYY9f+NFrSJBm3z4JjUaP+GmbgEjibjZW05diyKwbqzQEAjE1KXFCcd40D 3Brs2Dm4YruaJCwb68vswVQAYteXaQ8= =hl94 -----END PGP SIGNATURE----- Merge tag 'pull-ppc-20221017' of https://gitlab.com/danielhb/qemu into staging ppc patch queue for 2022-10-18: This queue contains improvements in the e500 and ppc4xx boards, changes in the maintainership of the project, a new QMP/HMP command and bug fixes: - Cedric is stepping back from qemu-ppc maintainership; - ppc4xx_sdram: QOMification and clean ups; - e500: add new types of flash and clean ups; - QMP/HMP: introduce dumpdtb command; - spapr_pci, booke doorbell interrupt and xvcmp* bit fixes; The 'dumpdtb' implementation is also making changes to RISC-V files that were acked by Alistair Francis and are being included in this queue. # -----BEGIN PGP SIGNATURE----- # # iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCY02qEgAKCRA82cqW3gMx # ZIadAQCYY9f+NFrSJBm3z4JjUaP+GmbgEjibjZW05diyKwbqzQEAjE1KXFCcd40D # 3Brs2Dm4YruaJCwb68vswVQAYteXaQ8= # =hl94 # -----END PGP SIGNATURE----- # gpg: Signature made Mon 17 Oct 2022 15:16:34 EDT # gpg: using EDDSA key 17EBFF9923D01800AF2838193CD9CA96DE033164 # gpg: Good signature from "Daniel Henrique Barboza <danielhb413@gmail.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 17EB FF99 23D0 1800 AF28 3819 3CD9 CA96 DE03 3164 * tag 'pull-ppc-20221017' of https://gitlab.com/danielhb/qemu: (38 commits) hw/riscv: set machine->fdt in spike_board_init() hw/riscv: set machine->fdt in sifive_u_machine_init() hw/ppc: set machine->fdt in spapr machine hw/ppc: set machine->fdt in pnv_reset() hw/ppc: set machine->fdt in pegasos2_machine_reset() hw/ppc: set machine->fdt in xilinx_load_device_tree() hw/ppc: set machine->fdt in sam460ex_load_device_tree() hw/ppc: set machine->fdt in bamboo_load_device_tree() hw/nios2: set machine->fdt in nios2_load_dtb() qmp/hmp, device_tree.c: introduce dumpdtb hw/ppc/spapr_pci.c: Use device_cold_reset() rather than device_legacy_reset() target/ppc: Fix xvcmp* clearing FI bit hw/ppc/e500: Remove if statement which is now always true hw/ppc/mpc8544ds: Add platform bus hw/ppc/mpc8544ds: Rename wrongly named method hw/ppc/e500: Reduce usage of sysbus API docs/system/ppc/ppce500: Add heading for networking chapter hw/gpio/meson: Introduce dedicated config switch for hw/gpio/mpc8xxx hw/ppc/meson: Allow e500 boards to be enabled separately ppc440_uc.c: Remove unneeded parenthesis ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
2c65091fd9
10
MAINTAINERS
10
MAINTAINERS
|
@ -267,8 +267,8 @@ F: hw/openrisc/
|
|||
F: tests/tcg/openrisc/
|
||||
|
||||
PowerPC TCG CPUs
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: Cédric Le Goater <clg@kaod.org>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
|
@ -392,8 +392,8 @@ F: target/mips/kvm*
|
|||
F: target/mips/sysemu/
|
||||
|
||||
PPC KVM CPUs
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: Cédric Le Goater <clg@kaod.org>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
S: Maintained
|
||||
|
@ -1365,8 +1365,8 @@ F: include/hw/rtc/m48t59.h
|
|||
F: tests/avocado/ppc_prep_40p.py
|
||||
|
||||
sPAPR (pseries)
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: Cédric Le Goater <clg@kaod.org>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
|
@ -1387,7 +1387,7 @@ F: tests/avocado/ppc_pseries.py
|
|||
PowerNV (Non-Virtualized)
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
S: Odd Fixes
|
||||
F: docs/system/ppc/powernv.rst
|
||||
F: hw/ppc/pnv*
|
||||
F: hw/intc/pnv*
|
||||
|
@ -2333,7 +2333,7 @@ T: git https://github.com/philmd/qemu.git fw_cfg-next
|
|||
XIVE
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: hw/*/*xive*
|
||||
F: include/hw/*/*xive*
|
||||
F: docs/*/*xive*
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# Default configuration for ppc-softmmu
|
||||
|
||||
# For embedded PPCs:
|
||||
CONFIG_E500=y
|
||||
CONFIG_E500PLAT=y
|
||||
CONFIG_MPC8544DS=y
|
||||
CONFIG_PPC405=y
|
||||
CONFIG_PPC440=y
|
||||
CONFIG_VIRTEX=y
|
||||
|
|
|
@ -146,6 +146,9 @@ You can specify a real world SoC device that QEMU has built-in support but all
|
|||
these SoCs are e500v2 based MPC85xx series, hence you cannot test anything
|
||||
built for P4080 (e500mc), P5020 (e5500) and T2080 (e6500).
|
||||
|
||||
Networking
|
||||
----------
|
||||
|
||||
By default a VirtIO standard PCI networking device is connected as an ethernet
|
||||
interface at PCI address 0.1.0, but we can switch that to an e1000 NIC by:
|
||||
|
||||
|
|
|
@ -1800,3 +1800,18 @@ ERST
|
|||
.sub_table = hmp_info_cmds,
|
||||
.flags = "p",
|
||||
},
|
||||
|
||||
#if defined(CONFIG_FDT)
|
||||
{
|
||||
.name = "dumpdtb",
|
||||
.args_type = "filename:F",
|
||||
.params = "filename",
|
||||
.help = "dump the FDT in dtb format to 'filename'",
|
||||
.cmd = hmp_dumpdtb,
|
||||
},
|
||||
|
||||
SRST
|
||||
``dumpdtb`` *filename*
|
||||
Dump the FDT in dtb format to *filename*.
|
||||
ERST
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,9 @@ config PL061
|
|||
config GPIO_KEY
|
||||
bool
|
||||
|
||||
config GPIO_MPC8XXX
|
||||
bool
|
||||
|
||||
config GPIO_PWR
|
||||
bool
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_GPIO_MPC8XXX', if_true: files('mpc8xxx.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
|
||||
#include "boot.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#define NIOS2_MAGIC 0x534f494e
|
||||
|
||||
static struct nios2_boot_info {
|
||||
|
@ -81,6 +83,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
|||
static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
|
||||
const char *kernel_cmdline, const char *dtb_filename)
|
||||
{
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
int fdt_size;
|
||||
void *fdt = NULL;
|
||||
int r;
|
||||
|
@ -113,7 +116,10 @@ static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
|
|||
}
|
||||
|
||||
cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
|
||||
g_free(fdt);
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
return fdt_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
nios2_ss = ss.source_set()
|
||||
nios2_ss.add(files('boot.c'))
|
||||
nios2_ss.add(files('boot.c'), fdt)
|
||||
nios2_ss.add(when: 'CONFIG_NIOS2_10M50', if_true: files('10m50_devboard.c'))
|
||||
nios2_ss.add(when: 'CONFIG_NIOS2_GENERIC_NOMMU', if_true: files('generic_nommu.c'))
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ config E500
|
|||
imply AT24C
|
||||
imply VIRTIO_PCI
|
||||
select ETSEC
|
||||
select GPIO_MPC8XXX
|
||||
select OPENPIC
|
||||
select PLATFORM_BUS
|
||||
select PPCE500_PCI
|
||||
|
@ -132,6 +133,14 @@ config E500
|
|||
select FDT_PPC
|
||||
select DS1338
|
||||
|
||||
config E500PLAT
|
||||
bool
|
||||
select E500
|
||||
|
||||
config MPC8544DS
|
||||
bool
|
||||
select E500
|
||||
|
||||
config VIRTEX
|
||||
bool
|
||||
select PPC4XX
|
||||
|
|
|
@ -1007,25 +1007,23 @@ void ppce500_init(MachineState *machine)
|
|||
}
|
||||
|
||||
/* Platform Bus Device */
|
||||
if (pmc->has_platform_bus) {
|
||||
dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
|
||||
dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
|
||||
qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
|
||||
qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
pms->pbus_dev = PLATFORM_BUS_DEVICE(dev);
|
||||
dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
|
||||
dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
|
||||
qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
|
||||
qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
pms->pbus_dev = PLATFORM_BUS_DEVICE(dev);
|
||||
|
||||
s = SYS_BUS_DEVICE(pms->pbus_dev);
|
||||
for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
|
||||
int irqn = pmc->platform_bus_first_irq + i;
|
||||
sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
|
||||
}
|
||||
|
||||
memory_region_add_subregion(address_space_mem,
|
||||
pmc->platform_bus_base,
|
||||
sysbus_mmio_get_region(s, 0));
|
||||
s = SYS_BUS_DEVICE(pms->pbus_dev);
|
||||
for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
|
||||
int irqn = pmc->platform_bus_first_irq + i;
|
||||
sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
|
||||
}
|
||||
|
||||
memory_region_add_subregion(address_space_mem,
|
||||
pmc->platform_bus_base,
|
||||
&pms->pbus_dev->mmio);
|
||||
|
||||
/*
|
||||
* Smart firmware defaults ahead!
|
||||
*
|
||||
|
|
|
@ -27,7 +27,6 @@ struct PPCE500MachineClass {
|
|||
|
||||
int mpic_version;
|
||||
bool has_mpc8xxx_gpio;
|
||||
bool has_platform_bus;
|
||||
hwaddr platform_bus_base;
|
||||
hwaddr platform_bus_size;
|
||||
int platform_bus_first_irq;
|
||||
|
|
|
@ -86,7 +86,6 @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
|
|||
pmc->fixup_devtree = e500plat_fixup_devtree;
|
||||
pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_42;
|
||||
pmc->has_mpc8xxx_gpio = true;
|
||||
pmc->has_platform_bus = true;
|
||||
pmc->platform_bus_base = 0xf00000000ULL;
|
||||
pmc->platform_bus_size = 128 * MiB;
|
||||
pmc->platform_bus_first_irq = 5;
|
||||
|
|
|
@ -71,12 +71,10 @@ ppc_ss.add(when: 'CONFIG_MAC_OLDWORLD', if_true: files('mac_oldworld.c'))
|
|||
# NewWorld PowerMac
|
||||
ppc_ss.add(when: 'CONFIG_MAC_NEWWORLD', if_true: files('mac_newworld.c'))
|
||||
# e500
|
||||
ppc_ss.add(when: 'CONFIG_E500PLAT', if_true: files('e500plat.c'))
|
||||
ppc_ss.add(when: 'CONFIG_MPC8544DS', if_true: files('mpc8544ds.c'))
|
||||
ppc_ss.add(when: 'CONFIG_E500', if_true: files(
|
||||
'e500.c',
|
||||
'mpc8544ds.c',
|
||||
'e500plat.c'
|
||||
))
|
||||
ppc_ss.add(when: 'CONFIG_E500', if_true: files(
|
||||
'mpc8544_guts.c',
|
||||
'ppce500_spin.c'
|
||||
))
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "sysemu/device_tree.h"
|
||||
#include "hw/ppc/openpic.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/units.h"
|
||||
#include "cpu.h"
|
||||
|
||||
static void mpc8544ds_fixup_devtree(void *fdt)
|
||||
|
@ -36,7 +37,7 @@ static void mpc8544ds_init(MachineState *machine)
|
|||
ppce500_init(machine);
|
||||
}
|
||||
|
||||
static void e500plat_machine_class_init(ObjectClass *oc, void *data)
|
||||
static void mpc8544ds_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
PPCE500MachineClass *pmc = PPCE500_MACHINE_CLASS(oc);
|
||||
|
@ -45,6 +46,10 @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
|
|||
pmc->pci_nr_slots = 2;
|
||||
pmc->fixup_devtree = mpc8544ds_fixup_devtree;
|
||||
pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
|
||||
pmc->platform_bus_base = 0xFF800000ULL;
|
||||
pmc->platform_bus_size = 8 * MiB;
|
||||
pmc->platform_bus_first_irq = 5;
|
||||
pmc->platform_bus_num_irqs = 10;
|
||||
pmc->ccsrbar_base = 0xE0000000ULL;
|
||||
pmc->pci_mmio_base = 0xC0000000ULL;
|
||||
pmc->pci_mmio_bus_base = 0xC0000000ULL;
|
||||
|
@ -63,7 +68,7 @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
|
|||
static const TypeInfo mpc8544ds_info = {
|
||||
.name = TYPE_MPC8544DS_MACHINE,
|
||||
.parent = TYPE_PPCE500_MACHINE,
|
||||
.class_init = e500plat_machine_class_init,
|
||||
.class_init = mpc8544ds_machine_class_init,
|
||||
};
|
||||
|
||||
static void mpc8544ds_register_types(void)
|
||||
|
|
|
@ -331,6 +331,10 @@ static void pegasos2_machine_reset(MachineState *machine)
|
|||
|
||||
vof_build_dt(fdt, pm->vof);
|
||||
vof_client_open_store(fdt, pm->vof, "/chosen", "stdout", "/failsafe");
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine);
|
||||
}
|
||||
|
||||
|
|
|
@ -678,7 +678,13 @@ static void pnv_reset(MachineState *machine)
|
|||
qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
|
||||
cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
|
||||
|
||||
g_free(fdt);
|
||||
/*
|
||||
* Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
|
||||
* the existing machine->fdt to avoid leaking it during
|
||||
* a reset.
|
||||
*/
|
||||
g_free(machine->fdt);
|
||||
machine->fdt = fdt;
|
||||
}
|
||||
|
||||
static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
|
||||
|
|
|
@ -167,13 +167,6 @@ struct Ppc405SoCState {
|
|||
DeviceState parent_obj;
|
||||
|
||||
/* Public */
|
||||
MemoryRegion ram_banks[2];
|
||||
hwaddr ram_bases[2], ram_sizes[2];
|
||||
bool do_dram_init;
|
||||
|
||||
MemoryRegion *dram_mr;
|
||||
hwaddr ram_size;
|
||||
|
||||
PowerPCCPU cpu;
|
||||
PPCUIC uic;
|
||||
Ppc405CpcState cpc;
|
||||
|
@ -187,6 +180,7 @@ struct Ppc405SoCState {
|
|||
Ppc405PobState pob;
|
||||
Ppc4xxPlbState plb;
|
||||
Ppc4xxMalState mal;
|
||||
Ppc4xxSdramDdrState sdram;
|
||||
};
|
||||
|
||||
#endif /* PPC405_H */
|
||||
|
|
|
@ -271,25 +271,13 @@ static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu)
|
|||
static void ppc405_init(MachineState *machine)
|
||||
{
|
||||
Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
|
||||
if (machine->ram_size != mc->default_ram_size) {
|
||||
char *sz = size_to_str(mc->default_ram_size);
|
||||
error_report("Invalid RAM size, should be %s", sz);
|
||||
g_free(sz);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
object_initialize_child(OBJECT(machine), "soc", &ppc405->soc,
|
||||
TYPE_PPC405_SOC);
|
||||
object_property_set_uint(OBJECT(&ppc405->soc), "ram-size",
|
||||
machine->ram_size, &error_fatal);
|
||||
object_property_set_link(OBJECT(&ppc405->soc), "dram",
|
||||
OBJECT(machine->ram), &error_abort);
|
||||
object_property_set_bool(OBJECT(&ppc405->soc), "dram-init",
|
||||
kernel_filename != NULL, &error_abort);
|
||||
object_property_set_uint(OBJECT(&ppc405->soc), "sys-clk", 33333333,
|
||||
&error_abort);
|
||||
qdev_realize(DEVICE(&ppc405->soc), NULL, &error_fatal);
|
||||
|
@ -349,6 +337,7 @@ static void ppc405_init(MachineState *machine)
|
|||
|
||||
/* Load ELF kernel and rootfs.cpio */
|
||||
} else if (kernel_filename && !machine->firmware) {
|
||||
ppc4xx_sdram_ddr_enable(&ppc405->soc.sdram);
|
||||
boot_from_kernel(machine, &ppc405->soc.cpu);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1016,6 +1016,9 @@ static void ppc405_soc_instance_init(Object *obj)
|
|||
object_initialize_child(obj, "plb", &s->plb, TYPE_PPC4xx_PLB);
|
||||
|
||||
object_initialize_child(obj, "mal", &s->mal, TYPE_PPC4xx_MAL);
|
||||
|
||||
object_initialize_child(obj, "sdram", &s->sdram, TYPE_PPC4xx_SDRAM_DDR);
|
||||
object_property_add_alias(obj, "dram", OBJECT(&s->sdram), "dram");
|
||||
}
|
||||
|
||||
static void ppc405_reset(void *opaque)
|
||||
|
@ -1073,16 +1076,17 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp)
|
|||
qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_CINT));
|
||||
|
||||
/* SDRAM controller */
|
||||
/* XXX 405EP has no ECC interrupt */
|
||||
s->ram_bases[0] = 0;
|
||||
s->ram_sizes[0] = s->ram_size;
|
||||
memory_region_init_alias(&s->ram_banks[0], OBJECT(s),
|
||||
"ppc405.sdram0", s->dram_mr,
|
||||
s->ram_bases[0], s->ram_sizes[0]);
|
||||
|
||||
ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(&s->uic), 17), 1,
|
||||
s->ram_banks, s->ram_bases, s->ram_sizes,
|
||||
s->do_dram_init);
|
||||
/*
|
||||
* We use the 440 DDR SDRAM controller which has more regs and features
|
||||
* but it's compatible enough for now
|
||||
*/
|
||||
object_property_set_int(OBJECT(&s->sdram), "nbanks", 2, &error_abort);
|
||||
if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->sdram), &s->cpu, errp)) {
|
||||
return;
|
||||
}
|
||||
/* XXX 405EP has no ECC interrupt */
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdram), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->uic), 17));
|
||||
|
||||
/* External bus controller */
|
||||
if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ebc), &s->cpu, errp)) {
|
||||
|
@ -1157,14 +1161,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp)
|
|||
/* Uses UIC IRQs 9, 15, 17 */
|
||||
}
|
||||
|
||||
static Property ppc405_soc_properties[] = {
|
||||
DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
|
||||
MemoryRegion *),
|
||||
DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0),
|
||||
DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void ppc405_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
@ -1172,7 +1168,6 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data)
|
|||
dc->realize = ppc405_soc_realize;
|
||||
/* Reason: only works as part of a ppc405 board/machine */
|
||||
dc->user_creatable = false;
|
||||
device_class_set_props(dc, ppc405_soc_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo ppc405_types[] = {
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
void ppc4xx_l2sram_init(CPUPPCState *env);
|
||||
void ppc4xx_cpr_init(CPUPPCState *env);
|
||||
void ppc4xx_sdr_init(CPUPPCState *env);
|
||||
void ppc440_sdram_init(CPUPPCState *env, int nbanks,
|
||||
MemoryRegion *ram_memories,
|
||||
hwaddr *ram_bases, hwaddr *ram_sizes,
|
||||
int do_init);
|
||||
void ppc4xx_ahb_init(CPUPPCState *env);
|
||||
void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
|
||||
void ppc460ex_pcie_init(CPUPPCState *env);
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
|
||||
|
||||
/* from u-boot */
|
||||
|
@ -48,22 +50,15 @@
|
|||
#define PPC440EP_PCI_IO 0xe8000000
|
||||
#define PPC440EP_PCI_IOLEN 0x00010000
|
||||
|
||||
#define PPC440EP_SDRAM_NR_BANKS 4
|
||||
|
||||
static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
|
||||
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
|
||||
};
|
||||
|
||||
static hwaddr entry;
|
||||
|
||||
static int bamboo_load_device_tree(hwaddr addr,
|
||||
uint32_t ramsize,
|
||||
hwaddr initrd_base,
|
||||
hwaddr initrd_size,
|
||||
const char *kernel_cmdline)
|
||||
static int bamboo_load_device_tree(MachineState *machine,
|
||||
hwaddr addr,
|
||||
hwaddr initrd_base,
|
||||
hwaddr initrd_size)
|
||||
{
|
||||
int ret = -1;
|
||||
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
|
||||
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(machine->ram_size) };
|
||||
char *filename;
|
||||
int fdt_size;
|
||||
void *fdt;
|
||||
|
@ -98,7 +93,7 @@ static int bamboo_load_device_tree(hwaddr addr,
|
|||
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
|
||||
}
|
||||
ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
|
||||
kernel_cmdline);
|
||||
machine->kernel_cmdline);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "couldn't set /chosen/bootargs\n");
|
||||
}
|
||||
|
@ -119,7 +114,10 @@ static int bamboo_load_device_tree(hwaddr addr,
|
|||
tb_freq);
|
||||
|
||||
rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
|
||||
g_free(fdt);
|
||||
|
||||
/* Set ms->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,14 +161,10 @@ static void main_cpu_reset(void *opaque)
|
|||
static void bamboo_init(MachineState *machine)
|
||||
{
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *isa = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
|
||||
hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
|
||||
hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
|
||||
PCIBus *pcibus;
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
|
@ -205,15 +199,15 @@ static void bamboo_init(MachineState *machine)
|
|||
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
|
||||
|
||||
/* SDRAM controller */
|
||||
memset(ram_bases, 0, sizeof(ram_bases));
|
||||
memset(ram_sizes, 0, sizeof(ram_sizes));
|
||||
ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
|
||||
ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
|
||||
dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
|
||||
object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
|
||||
&error_abort);
|
||||
ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
|
||||
object_unref(OBJECT(dev));
|
||||
/* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
|
||||
ppc4xx_sdram_init(env,
|
||||
qdev_get_gpio_in(uicdev, 14),
|
||||
PPC440EP_SDRAM_NR_BANKS, ram_memories,
|
||||
ram_bases, ram_sizes, 1);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
|
||||
/* Enable SDRAM memory regions, this should be done by the firmware */
|
||||
ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev));
|
||||
|
||||
/* PCI */
|
||||
dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
|
||||
|
@ -289,8 +283,8 @@ static void bamboo_init(MachineState *machine)
|
|||
|
||||
/* If we're loading a kernel directly, we must load the device tree too. */
|
||||
if (kernel_filename) {
|
||||
if (bamboo_load_device_tree(FDT_ADDR, machine->ram_size, RAMDISK_ADDR,
|
||||
initrd_size, kernel_cmdline) < 0) {
|
||||
if (bamboo_load_device_tree(machine, FDT_ADDR,
|
||||
RAMDISK_ADDR, initrd_size) < 0) {
|
||||
error_report("couldn't load device tree");
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -16,13 +16,15 @@
|
|||
#include "qemu/module.h"
|
||||
#include "hw/irq.h"
|
||||
#include "exec/memory.h"
|
||||
#include "hw/ppc/ppc.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 */
|
||||
|
@ -378,10 +380,6 @@ enum {
|
|||
PESDR1_RSTSTA = 0x365,
|
||||
};
|
||||
|
||||
#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29)
|
||||
#define SDR0_DDR0_DDRM_DDR1 0x20000000
|
||||
#define SDR0_DDR0_DDRM_DDR2 0x40000000
|
||||
|
||||
static uint32_t dcr_read_sdr(void *opaque, int dcrn)
|
||||
{
|
||||
ppc4xx_sdr_t *sdr = opaque;
|
||||
|
@ -482,16 +480,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* SDRAM controller */
|
||||
typedef struct ppc440_sdram_t {
|
||||
uint32_t addr;
|
||||
int nbanks;
|
||||
MemoryRegion containers[4]; /* used for clipping */
|
||||
MemoryRegion *ram_memories;
|
||||
hwaddr ram_bases[4];
|
||||
hwaddr ram_sizes[4];
|
||||
uint32_t bcr[4];
|
||||
} ppc440_sdram_t;
|
||||
|
||||
enum {
|
||||
SDRAM0_CFGADDR = 0x10,
|
||||
SDRAM0_CFGDATA,
|
||||
|
@ -506,39 +494,39 @@ enum {
|
|||
SDRAM_PLBADDUHB = 0x50,
|
||||
};
|
||||
|
||||
static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
{
|
||||
uint32_t bcr;
|
||||
|
||||
switch (ram_size) {
|
||||
case (8 * MiB):
|
||||
case 8 * MiB:
|
||||
bcr = 0xffc0;
|
||||
break;
|
||||
case (16 * MiB):
|
||||
case 16 * MiB:
|
||||
bcr = 0xff80;
|
||||
break;
|
||||
case (32 * MiB):
|
||||
case 32 * MiB:
|
||||
bcr = 0xff00;
|
||||
break;
|
||||
case (64 * MiB):
|
||||
case 64 * MiB:
|
||||
bcr = 0xfe00;
|
||||
break;
|
||||
case (128 * MiB):
|
||||
case 128 * MiB:
|
||||
bcr = 0xfc00;
|
||||
break;
|
||||
case (256 * MiB):
|
||||
case 256 * MiB:
|
||||
bcr = 0xf800;
|
||||
break;
|
||||
case (512 * MiB):
|
||||
case 512 * MiB:
|
||||
bcr = 0xf000;
|
||||
break;
|
||||
case (1 * GiB):
|
||||
case 1 * GiB:
|
||||
bcr = 0xe000;
|
||||
break;
|
||||
case (2 * GiB):
|
||||
case 2 * GiB:
|
||||
bcr = 0xc000;
|
||||
break;
|
||||
case (4 * GiB):
|
||||
case 4 * GiB:
|
||||
bcr = 0x8000;
|
||||
break;
|
||||
default:
|
||||
|
@ -551,12 +539,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
|||
return bcr;
|
||||
}
|
||||
|
||||
static inline hwaddr sdram_base(uint32_t bcr)
|
||||
static inline hwaddr sdram_ddr2_base(uint32_t bcr)
|
||||
{
|
||||
return (bcr & 0xffe00000) << 2;
|
||||
}
|
||||
|
||||
static uint64_t sdram_size(uint32_t bcr)
|
||||
static uint64_t sdram_ddr2_size(uint32_t bcr)
|
||||
{
|
||||
uint64_t size;
|
||||
int sh;
|
||||
|
@ -567,46 +555,66 @@ static uint64_t sdram_size(uint32_t bcr)
|
|||
return size;
|
||||
}
|
||||
|
||||
static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
|
||||
uint32_t bcr, int enabled)
|
||||
static void sdram_bank_map(Ppc4xxSdramBank *bank)
|
||||
{
|
||||
if (sdram->bcr[i] & 1) {
|
||||
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 */
|
||||
memory_region_del_subregion(get_system_memory(),
|
||||
&sdram->containers[i]);
|
||||
memory_region_del_subregion(&sdram->containers[i],
|
||||
&sdram->ram_memories[i]);
|
||||
object_unparent(OBJECT(&sdram->containers[i]));
|
||||
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->bcr[i] = bcr & 0xffe0ffc1;
|
||||
sdram->bank[i].bcr = bcr & 0xffe0ffc1;
|
||||
if (enabled && (bcr & 1)) {
|
||||
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
|
||||
sdram_size(bcr));
|
||||
memory_region_add_subregion(&sdram->containers[i], 0,
|
||||
&sdram->ram_memories[i]);
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sdram_base(bcr),
|
||||
&sdram->containers[i]);
|
||||
trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
|
||||
sdram_bank_map(&sdram->bank[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdram_map_bcr(ppc440_sdram_t *sdram)
|
||||
static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sdram->nbanks; i++) {
|
||||
if (sdram->ram_sizes[i] != 0) {
|
||||
sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
|
||||
sdram->ram_sizes[i]), 1);
|
||||
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_set_bcr(sdram, i, 0, 0);
|
||||
sdram_ddr2_set_bcr(sdram, i, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
||||
static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram)
|
||||
{
|
||||
ppc440_sdram_t *sdram = opaque;
|
||||
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) {
|
||||
|
@ -614,9 +622,9 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
|||
case SDRAM_R1BAS:
|
||||
case SDRAM_R2BAS:
|
||||
case SDRAM_R3BAS:
|
||||
if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
|
||||
ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
|
||||
sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
|
||||
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:
|
||||
|
@ -635,7 +643,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
|||
ret = 0x80000000;
|
||||
break;
|
||||
case 0x21: /* SDRAM_MCOPT2 */
|
||||
ret = 0x08000000;
|
||||
ret = sdram->mcopt2;
|
||||
break;
|
||||
case 0x40: /* SDRAM_MB0CF */
|
||||
ret = 0x00008001;
|
||||
|
@ -657,9 +665,11 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
||||
#define SDRAM_DDR2_MCOPT2_DCEN BIT(27)
|
||||
|
||||
static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
|
||||
{
|
||||
ppc440_sdram_t *sdram = opaque;
|
||||
Ppc4xxSdramDdr2State *sdram = opaque;
|
||||
|
||||
switch (dcrn) {
|
||||
case SDRAM_R0BAS:
|
||||
|
@ -679,6 +689,21 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
|||
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;
|
||||
}
|
||||
|
@ -688,54 +713,96 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
static void sdram_reset(void *opaque)
|
||||
static void ppc4xx_sdram_ddr2_reset(DeviceState *dev)
|
||||
{
|
||||
ppc440_sdram_t *sdram = opaque;
|
||||
Ppc4xxSdramDdr2State *sdram = PPC4xx_SDRAM_DDR2(dev);
|
||||
|
||||
sdram->addr = 0;
|
||||
sdram->mcopt2 = 0;
|
||||
}
|
||||
|
||||
void ppc440_sdram_init(CPUPPCState *env, int nbanks,
|
||||
MemoryRegion *ram_memories,
|
||||
hwaddr *ram_bases, hwaddr *ram_sizes,
|
||||
int do_init)
|
||||
static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ppc440_sdram_t *sdram;
|
||||
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
|
||||
};
|
||||
|
||||
sdram = g_malloc0(sizeof(*sdram));
|
||||
sdram->nbanks = nbanks;
|
||||
sdram->ram_memories = ram_memories;
|
||||
memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
|
||||
memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
|
||||
qemu_register_reset(&sdram_reset, sdram);
|
||||
ppc_dcr_register(env, SDRAM0_CFGADDR,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM0_CFGDATA,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
if (do_init) {
|
||||
sdram_map_bcr(sdram);
|
||||
if (s->nbanks < 1 || s->nbanks > 4) {
|
||||
error_setg(errp, "Invalid number of RAM banks");
|
||||
return;
|
||||
}
|
||||
if (!s->dram_mr) {
|
||||
error_setg(errp, "Missing dram memory region");
|
||||
return;
|
||||
}
|
||||
ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
|
||||
|
||||
ppc_dcr_register(env, SDRAM_R0BAS,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_R1BAS,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_R2BAS,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_R3BAS,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_CONF1HB,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_PLBADDULL,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_CONF1LL,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_CONFPATHB,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM_PLBADDUHB,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
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 {
|
||||
|
|
|
@ -38,28 +38,6 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
/* SDRAM controller */
|
||||
typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
|
||||
struct ppc4xx_sdram_t {
|
||||
uint32_t addr;
|
||||
int nbanks;
|
||||
MemoryRegion containers[4]; /* used for clipping */
|
||||
MemoryRegion *ram_memories;
|
||||
hwaddr ram_bases[4];
|
||||
hwaddr ram_sizes[4];
|
||||
uint32_t besr0;
|
||||
uint32_t besr1;
|
||||
uint32_t bear;
|
||||
uint32_t cfg;
|
||||
uint32_t status;
|
||||
uint32_t rtr;
|
||||
uint32_t pmit;
|
||||
uint32_t bcr[4];
|
||||
uint32_t tr;
|
||||
uint32_t ecccfg;
|
||||
uint32_t eccesr;
|
||||
qemu_irq irq;
|
||||
};
|
||||
|
||||
enum {
|
||||
SDRAM0_CFGADDR = 0x010,
|
||||
SDRAM0_CFGDATA = 0x011,
|
||||
|
@ -70,37 +48,37 @@ enum {
|
|||
* there are type inconsistencies, mixing hwaddr, target_ulong
|
||||
* and uint32_t
|
||||
*/
|
||||
static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
{
|
||||
uint32_t bcr;
|
||||
|
||||
switch (ram_size) {
|
||||
case 4 * MiB:
|
||||
bcr = 0x00000000;
|
||||
bcr = 0;
|
||||
break;
|
||||
case 8 * MiB:
|
||||
bcr = 0x00020000;
|
||||
bcr = 0x20000;
|
||||
break;
|
||||
case 16 * MiB:
|
||||
bcr = 0x00040000;
|
||||
bcr = 0x40000;
|
||||
break;
|
||||
case 32 * MiB:
|
||||
bcr = 0x00060000;
|
||||
bcr = 0x60000;
|
||||
break;
|
||||
case 64 * MiB:
|
||||
bcr = 0x00080000;
|
||||
bcr = 0x80000;
|
||||
break;
|
||||
case 128 * MiB:
|
||||
bcr = 0x000A0000;
|
||||
bcr = 0xA0000;
|
||||
break;
|
||||
case 256 * MiB:
|
||||
bcr = 0x000C0000;
|
||||
bcr = 0xC0000;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
|
||||
ram_size);
|
||||
return 0x00000000;
|
||||
return 0;
|
||||
}
|
||||
bcr |= ram_base & 0xFF800000;
|
||||
bcr |= 1;
|
||||
|
@ -108,12 +86,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
|||
return bcr;
|
||||
}
|
||||
|
||||
static inline hwaddr sdram_base(uint32_t bcr)
|
||||
static inline hwaddr sdram_ddr_base(uint32_t bcr)
|
||||
{
|
||||
return bcr & 0xFF800000;
|
||||
}
|
||||
|
||||
static target_ulong sdram_size(uint32_t bcr)
|
||||
static target_ulong sdram_ddr_size(uint32_t bcr)
|
||||
{
|
||||
target_ulong size;
|
||||
int sh;
|
||||
|
@ -128,64 +106,63 @@ static target_ulong sdram_size(uint32_t bcr)
|
|||
return size;
|
||||
}
|
||||
|
||||
static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
|
||||
uint32_t bcr, int enabled)
|
||||
static void sdram_ddr_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
|
||||
uint32_t bcr, int enabled)
|
||||
{
|
||||
if (sdram->bcr[i] & 0x00000001) {
|
||||
if (sdram->bank[i].bcr & 1) {
|
||||
/* Unmap RAM */
|
||||
trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
|
||||
sdram_size(sdram->bcr[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->containers[i]);
|
||||
memory_region_del_subregion(&sdram->containers[i],
|
||||
&sdram->ram_memories[i]);
|
||||
object_unparent(OBJECT(&sdram->containers[i]));
|
||||
&sdram->bank[i].container);
|
||||
memory_region_del_subregion(&sdram->bank[i].container,
|
||||
&sdram->bank[i].ram);
|
||||
object_unparent(OBJECT(&sdram->bank[i].container));
|
||||
}
|
||||
sdram->bcr[i] = bcr & 0xFFDEE001;
|
||||
if (enabled && (bcr & 0x00000001)) {
|
||||
trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
|
||||
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
|
||||
sdram_size(bcr));
|
||||
memory_region_add_subregion(&sdram->containers[i], 0,
|
||||
&sdram->ram_memories[i]);
|
||||
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_base(bcr),
|
||||
&sdram->containers[i]);
|
||||
sdram_ddr_base(bcr),
|
||||
&sdram->bank[i].container);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdram_map_bcr(ppc4xx_sdram_t *sdram)
|
||||
static void sdram_ddr_map_bcr(Ppc4xxSdramDdrState *sdram)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sdram->nbanks; i++) {
|
||||
if (sdram->ram_sizes[i] != 0) {
|
||||
sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
|
||||
sdram->ram_sizes[i]), 1);
|
||||
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_set_bcr(sdram, i, 0x00000000, 0);
|
||||
sdram_ddr_set_bcr(sdram, i, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sdram_unmap_bcr(ppc4xx_sdram_t *sdram)
|
||||
static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState *sdram)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sdram->nbanks; i++) {
|
||||
trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
|
||||
sdram_size(sdram->bcr[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->ram_memories[i]);
|
||||
&sdram->bank[i].ram);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
||||
static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram;
|
||||
Ppc4xxSdramDdrState *sdram = opaque;
|
||||
uint32_t ret;
|
||||
|
||||
sdram = opaque;
|
||||
switch (dcrn) {
|
||||
case SDRAM0_CFGADDR:
|
||||
ret = sdram->addr;
|
||||
|
@ -214,16 +191,16 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
|||
ret = sdram->pmit;
|
||||
break;
|
||||
case 0x40: /* SDRAM_B0CR */
|
||||
ret = sdram->bcr[0];
|
||||
ret = sdram->bank[0].bcr;
|
||||
break;
|
||||
case 0x44: /* SDRAM_B1CR */
|
||||
ret = sdram->bcr[1];
|
||||
ret = sdram->bank[1].bcr;
|
||||
break;
|
||||
case 0x48: /* SDRAM_B2CR */
|
||||
ret = sdram->bcr[2];
|
||||
ret = sdram->bank[2].bcr;
|
||||
break;
|
||||
case 0x4C: /* SDRAM_B3CR */
|
||||
ret = sdram->bcr[3];
|
||||
ret = sdram->bank[3].bcr;
|
||||
break;
|
||||
case 0x80: /* SDRAM_TR */
|
||||
ret = -1; /* ? */
|
||||
|
@ -241,18 +218,17 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
|||
break;
|
||||
default:
|
||||
/* Avoid gcc warning */
|
||||
ret = 0x00000000;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
||||
static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram;
|
||||
Ppc4xxSdramDdrState *sdram = opaque;
|
||||
|
||||
sdram = opaque;
|
||||
switch (dcrn) {
|
||||
case SDRAM0_CFGADDR:
|
||||
sdram->addr = val;
|
||||
|
@ -273,12 +249,12 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
|||
if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
|
||||
trace_ppc4xx_sdram_enable("enable");
|
||||
/* validate all RAM mappings */
|
||||
sdram_map_bcr(sdram);
|
||||
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_unmap_bcr(sdram);
|
||||
sdram_ddr_unmap_bcr(sdram);
|
||||
sdram->status |= 0x80000000;
|
||||
}
|
||||
if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) {
|
||||
|
@ -298,16 +274,16 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
|||
sdram->pmit = (val & 0xF8000000) | 0x07C00000;
|
||||
break;
|
||||
case 0x40: /* SDRAM_B0CR */
|
||||
sdram_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
|
||||
sdram_ddr_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x44: /* SDRAM_B1CR */
|
||||
sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
|
||||
sdram_ddr_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x48: /* SDRAM_B2CR */
|
||||
sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
|
||||
sdram_ddr_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x4C: /* SDRAM_B3CR */
|
||||
sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
|
||||
sdram_ddr_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x80: /* SDRAM_TR */
|
||||
sdram->tr = val & 0x018FC01F;
|
||||
|
@ -331,52 +307,73 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
static void sdram_reset(void *opaque)
|
||||
static void ppc4xx_sdram_ddr_reset(DeviceState *dev)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram;
|
||||
Ppc4xxSdramDdrState *sdram = PPC4xx_SDRAM_DDR(dev);
|
||||
|
||||
sdram = opaque;
|
||||
sdram->addr = 0x00000000;
|
||||
sdram->bear = 0x00000000;
|
||||
sdram->besr0 = 0x00000000; /* No error */
|
||||
sdram->besr1 = 0x00000000; /* No error */
|
||||
sdram->cfg = 0x00000000;
|
||||
sdram->ecccfg = 0x00000000; /* No ECC */
|
||||
sdram->eccesr = 0x00000000; /* No error */
|
||||
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 = 0x00000000;
|
||||
sdram->status = 0;
|
||||
sdram->cfg = 0x00800000;
|
||||
}
|
||||
|
||||
void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks,
|
||||
MemoryRegion *ram_memories,
|
||||
hwaddr *ram_bases,
|
||||
hwaddr *ram_sizes,
|
||||
int do_init)
|
||||
static void ppc4xx_sdram_ddr_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram;
|
||||
Ppc4xxSdramDdrState *s = PPC4xx_SDRAM_DDR(dev);
|
||||
Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
|
||||
const ram_addr_t valid_bank_sizes[] = {
|
||||
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
|
||||
};
|
||||
|
||||
sdram = g_new0(ppc4xx_sdram_t, 1);
|
||||
sdram->irq = irq;
|
||||
sdram->nbanks = nbanks;
|
||||
sdram->ram_memories = ram_memories;
|
||||
memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
|
||||
memcpy(sdram->ram_bases, ram_bases,
|
||||
nbanks * sizeof(hwaddr));
|
||||
memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
|
||||
memcpy(sdram->ram_sizes, ram_sizes,
|
||||
nbanks * sizeof(hwaddr));
|
||||
qemu_register_reset(&sdram_reset, sdram);
|
||||
ppc_dcr_register(env, SDRAM0_CFGADDR,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
ppc_dcr_register(env, SDRAM0_CFGDATA,
|
||||
sdram, &dcr_read_sdram, &dcr_write_sdram);
|
||||
if (do_init) {
|
||||
sdram_map_bcr(sdram);
|
||||
if (s->nbanks < 1 || s->nbanks > 4) {
|
||||
error_setg(errp, "Invalid number of RAM banks");
|
||||
return;
|
||||
}
|
||||
if (!s->dram_mr) {
|
||||
error_setg(errp, "Missing dram memory region");
|
||||
return;
|
||||
}
|
||||
ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
|
||||
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
|
||||
|
||||
ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR,
|
||||
s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
|
||||
ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA,
|
||||
s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -390,8 +387,7 @@ void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks,
|
|||
* sizes varies by SoC.
|
||||
*/
|
||||
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
|
||||
MemoryRegion ram_memories[],
|
||||
hwaddr ram_bases[], hwaddr ram_sizes[],
|
||||
Ppc4xxSdramBank ram_banks[],
|
||||
const ram_addr_t sdram_bank_sizes[])
|
||||
{
|
||||
ram_addr_t size_left = memory_region_size(ram);
|
||||
|
@ -406,13 +402,13 @@ void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
|
|||
if (bank_size <= size_left) {
|
||||
char name[32];
|
||||
|
||||
ram_bases[i] = base;
|
||||
ram_sizes[i] = bank_size;
|
||||
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_memories[i], NULL, name, ram,
|
||||
ram_bases[i], ram_sizes[i]);
|
||||
memory_region_init_alias(&ram_banks[i].ram, NULL, name, ram,
|
||||
ram_banks[i].base, ram_banks[i].size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -967,6 +963,11 @@ 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),
|
||||
|
|
|
@ -73,14 +73,6 @@
|
|||
#define OPB_FREQ 115000000
|
||||
#define EBC_FREQ 115000000
|
||||
#define UART_FREQ 11059200
|
||||
#define SDRAM_NR_BANKS 4
|
||||
|
||||
/* The SoC could also handle 4 GiB but firmware does not work with that. */
|
||||
/* Maybe it overflows a signed 32 bit number somewhere? */
|
||||
static const ram_addr_t ppc460ex_sdram_bank_sizes[] = {
|
||||
2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
|
||||
32 * MiB, 0
|
||||
};
|
||||
|
||||
struct boot_info {
|
||||
uint32_t dt_base;
|
||||
|
@ -131,13 +123,12 @@ static int sam460ex_load_uboot(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sam460ex_load_device_tree(hwaddr addr,
|
||||
uint32_t ramsize,
|
||||
static int sam460ex_load_device_tree(MachineState *machine,
|
||||
hwaddr addr,
|
||||
hwaddr initrd_base,
|
||||
hwaddr initrd_size,
|
||||
const char *kernel_cmdline)
|
||||
hwaddr initrd_size)
|
||||
{
|
||||
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
|
||||
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(machine->ram_size) };
|
||||
char *filename;
|
||||
int fdt_size;
|
||||
void *fdt;
|
||||
|
@ -171,7 +162,8 @@ static int sam460ex_load_device_tree(hwaddr addr,
|
|||
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
|
||||
(initrd_base + initrd_size));
|
||||
|
||||
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
|
||||
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
|
||||
machine->kernel_cmdline);
|
||||
|
||||
/* Copy data from the host device tree into the guest. Since the guest can
|
||||
* directly access the timebase without host involvement, we must expose
|
||||
|
@ -208,7 +200,9 @@ static int sam460ex_load_device_tree(hwaddr addr,
|
|||
EBC_FREQ);
|
||||
|
||||
rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
|
||||
g_free(fdt);
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
return fdt_size;
|
||||
}
|
||||
|
@ -274,9 +268,6 @@ static void sam460ex_init(MachineState *machine)
|
|||
{
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *isa = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
|
||||
hwaddr ram_bases[SDRAM_NR_BANKS] = {0};
|
||||
hwaddr ram_sizes[SDRAM_NR_BANKS] = {0};
|
||||
MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
|
||||
DeviceState *uic[4];
|
||||
int i;
|
||||
|
@ -343,22 +334,37 @@ static void sam460ex_init(MachineState *machine)
|
|||
}
|
||||
|
||||
/* SDRAM controller */
|
||||
/* put all RAM on first bank because board has one slot
|
||||
* and firmware only checks that */
|
||||
ppc4xx_sdram_banks(machine->ram, 1, ram_memories, ram_bases, ram_sizes,
|
||||
ppc460ex_sdram_bank_sizes);
|
||||
|
||||
/* The SoC could also handle 4 GiB but firmware does not work with that. */
|
||||
if (machine->ram_size > 2 * GiB) {
|
||||
error_report("Memory over 2 GiB is not supported");
|
||||
exit(1);
|
||||
}
|
||||
/* Firmware needs at least 64 MiB */
|
||||
if (machine->ram_size < 64 * MiB) {
|
||||
error_report("Memory below 64 MiB is not supported");
|
||||
exit(1);
|
||||
}
|
||||
dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR2);
|
||||
object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
|
||||
&error_abort);
|
||||
/*
|
||||
* Put all RAM on first bank because board has one slot
|
||||
* and firmware only checks that
|
||||
*/
|
||||
object_property_set_int(OBJECT(dev), "nbanks", 1, &error_abort);
|
||||
ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
|
||||
object_unref(OBJECT(dev));
|
||||
/* FIXME: does 460EX have ECC interrupts? */
|
||||
ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
|
||||
ram_bases, ram_sizes, 1);
|
||||
/* Enable SDRAM memory regions as we may boot without firmware */
|
||||
ppc4xx_sdram_ddr2_enable(PPC4xx_SDRAM_DDR2(dev));
|
||||
|
||||
/* IIC controllers and devices */
|
||||
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700,
|
||||
qdev_get_gpio_in(uic[0], 2));
|
||||
i2c = PPC4xx_I2C(dev)->bus;
|
||||
/* SPD EEPROM on RAM module */
|
||||
spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2,
|
||||
ram_sizes[0]);
|
||||
spd_data = spd_data_generate(machine->ram_size < 128 * MiB ? DDR : DDR2,
|
||||
machine->ram_size);
|
||||
spd_data[20] = 4; /* SO-DIMM module */
|
||||
smbus_eeprom_init_one(i2c, 0x50, spd_data);
|
||||
/* RTC */
|
||||
|
@ -496,9 +502,8 @@ static void sam460ex_init(MachineState *machine)
|
|||
if (machine->kernel_filename) {
|
||||
int dt_size;
|
||||
|
||||
dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
|
||||
RAMDISK_ADDR, initrd_size,
|
||||
machine->kernel_cmdline);
|
||||
dt_size = sam460ex_load_device_tree(machine, FDT_ADDR,
|
||||
RAMDISK_ADDR, initrd_size);
|
||||
|
||||
boot_info->dt_base = FDT_ADDR;
|
||||
boot_info->dt_size = dt_size;
|
||||
|
|
|
@ -1713,6 +1713,9 @@ static void spapr_machine_reset(MachineState *machine)
|
|||
spapr->fdt_initial_size = spapr->fdt_size;
|
||||
spapr->fdt_blob = fdt;
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
/* Set up the entry state */
|
||||
first_ppc_cpu->env.gpr[5] = 0;
|
||||
|
||||
|
|
|
@ -1256,6 +1256,14 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu,
|
|||
spapr->fdt_initial_size = spapr->fdt_size;
|
||||
spapr->fdt_blob = fdt;
|
||||
|
||||
/*
|
||||
* Set the machine->fdt pointer again since we just freed
|
||||
* it above (by freeing spapr->fdt_blob). We set this
|
||||
* pointer to enable support for the 'dumpdtb' QMP/HMP
|
||||
* command.
|
||||
*/
|
||||
MACHINE(spapr)->fdt = fdt;
|
||||
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -2045,7 +2045,7 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
|
|||
DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
|
||||
|
||||
if (dev) {
|
||||
device_legacy_reset(dev);
|
||||
device_cold_reset(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "hw/qdev-properties.h"
|
||||
#include "ppc405.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#define EPAPR_MAGIC (0x45504150)
|
||||
#define FLASH_SIZE (16 * MiB)
|
||||
|
||||
|
@ -144,11 +146,10 @@ static void main_cpu_reset(void *opaque)
|
|||
}
|
||||
|
||||
#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
|
||||
static int xilinx_load_device_tree(hwaddr addr,
|
||||
uint32_t ramsize,
|
||||
hwaddr initrd_base,
|
||||
hwaddr initrd_size,
|
||||
const char *kernel_cmdline)
|
||||
static int xilinx_load_device_tree(MachineState *machine,
|
||||
hwaddr addr,
|
||||
hwaddr initrd_base,
|
||||
hwaddr initrd_size)
|
||||
{
|
||||
char *path;
|
||||
int fdt_size;
|
||||
|
@ -190,18 +191,21 @@ static int xilinx_load_device_tree(hwaddr addr,
|
|||
error_report("couldn't set /chosen/linux,initrd-end");
|
||||
}
|
||||
|
||||
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
|
||||
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
|
||||
machine->kernel_cmdline);
|
||||
if (r < 0)
|
||||
fprintf(stderr, "couldn't set /chosen/bootargs\n");
|
||||
cpu_physical_memory_write(addr, fdt, fdt_size);
|
||||
g_free(fdt);
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
return fdt_size;
|
||||
}
|
||||
|
||||
static void virtex_init(MachineState *machine)
|
||||
{
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
hwaddr initrd_base = 0;
|
||||
int initrd_size = 0;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
|
@ -294,9 +298,8 @@ static void virtex_init(MachineState *machine)
|
|||
boot_info.fdt = high + (8192 * 2);
|
||||
boot_info.fdt &= ~8191;
|
||||
|
||||
xilinx_load_device_tree(boot_info.fdt, machine->ram_size,
|
||||
initrd_base, initrd_size,
|
||||
kernel_cmdline);
|
||||
xilinx_load_device_tree(machine, boot_info.fdt,
|
||||
initrd_base, initrd_size);
|
||||
}
|
||||
env->load_info = &boot_info;
|
||||
}
|
||||
|
|
|
@ -634,6 +634,9 @@ static void sifive_u_machine_init(MachineState *machine)
|
|||
start_addr_hi32 = (uint64_t)start_addr >> 32;
|
||||
}
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = s->fdt;
|
||||
|
||||
/* reset vector */
|
||||
uint32_t reset_vec[12] = {
|
||||
s->msel, /* MSEL pin state */
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
static const MemMapEntry spike_memmap[] = {
|
||||
[SPIKE_MROM] = { 0x1000, 0xf000 },
|
||||
[SPIKE_HTIF] = { 0x1000000, 0x1000 },
|
||||
|
@ -304,6 +306,10 @@ static void spike_board_init(MachineState *machine)
|
|||
/* Compute the fdt load address in dram */
|
||||
fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
|
||||
machine->ram_size, s->fdt);
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = s->fdt;
|
||||
|
||||
/* load the reset vector */
|
||||
riscv_setup_rom_reset_vec(machine, &s->soc[0], memmap[SPIKE_DRAM].base,
|
||||
memmap[SPIKE_MROM].base,
|
||||
|
|
|
@ -29,16 +29,17 @@
|
|||
#include "exec/memory.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
|
||||
MemoryRegion ram_memories[],
|
||||
hwaddr ram_bases[], hwaddr ram_sizes[],
|
||||
const ram_addr_t sdram_bank_sizes[]);
|
||||
typedef struct {
|
||||
MemoryRegion ram;
|
||||
MemoryRegion container; /* used for clipping */
|
||||
hwaddr base;
|
||||
hwaddr size;
|
||||
uint32_t bcr;
|
||||
} Ppc4xxSdramBank;
|
||||
|
||||
void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
|
||||
MemoryRegion ram_memories[],
|
||||
hwaddr *ram_bases,
|
||||
hwaddr *ram_sizes,
|
||||
int do_init);
|
||||
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
|
||||
Ppc4xxSdramBank ram_banks[],
|
||||
const ram_addr_t sdram_bank_sizes[]);
|
||||
|
||||
#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
|
||||
|
||||
|
@ -109,4 +110,50 @@ struct Ppc4xxEbcState {
|
|||
uint32_t cfg;
|
||||
};
|
||||
|
||||
/* SDRAM DDR controller */
|
||||
#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29)
|
||||
#define SDR0_DDR0_DDRM_DDR1 0x20000000
|
||||
#define SDR0_DDR0_DDRM_DDR2 0x40000000
|
||||
|
||||
#define TYPE_PPC4xx_SDRAM_DDR "ppc4xx-sdram-ddr"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramDdrState, PPC4xx_SDRAM_DDR);
|
||||
struct Ppc4xxSdramDdrState {
|
||||
Ppc4xxDcrDeviceState parent_obj;
|
||||
|
||||
MemoryRegion *dram_mr;
|
||||
uint32_t nbanks; /* Banks to use from 4, e.g. when board has less slots */
|
||||
Ppc4xxSdramBank bank[4];
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t addr;
|
||||
uint32_t besr0;
|
||||
uint32_t besr1;
|
||||
uint32_t bear;
|
||||
uint32_t cfg;
|
||||
uint32_t status;
|
||||
uint32_t rtr;
|
||||
uint32_t pmit;
|
||||
uint32_t tr;
|
||||
uint32_t ecccfg;
|
||||
uint32_t eccesr;
|
||||
};
|
||||
|
||||
void ppc4xx_sdram_ddr_enable(Ppc4xxSdramDdrState *s);
|
||||
|
||||
/* SDRAM DDR2 controller */
|
||||
#define TYPE_PPC4xx_SDRAM_DDR2 "ppc4xx-sdram-ddr2"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramDdr2State, PPC4xx_SDRAM_DDR2);
|
||||
struct Ppc4xxSdramDdr2State {
|
||||
Ppc4xxDcrDeviceState parent_obj;
|
||||
|
||||
MemoryRegion *dram_mr;
|
||||
uint32_t nbanks; /* Banks to use from 4, e.g. when board has less slots */
|
||||
Ppc4xxSdramBank bank[4];
|
||||
|
||||
uint32_t addr;
|
||||
uint32_t mcopt2;
|
||||
};
|
||||
|
||||
void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s);
|
||||
|
||||
#endif /* PPC4XX_H */
|
||||
|
|
|
@ -136,6 +136,7 @@ int qemu_fdt_add_path(void *fdt, const char *path);
|
|||
} while (0)
|
||||
|
||||
void qemu_fdt_dumpdtb(void *fdt, int size);
|
||||
void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
|
||||
|
||||
/**
|
||||
* qemu_fdt_setprop_sized_cells_from_array:
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tpm.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
|
|
@ -1664,3 +1664,21 @@
|
|||
'*size': 'size',
|
||||
'*max-size': 'size',
|
||||
'*slots': 'uint64' } }
|
||||
|
||||
##
|
||||
# @dumpdtb:
|
||||
#
|
||||
# Save the FDT in dtb format.
|
||||
#
|
||||
# @filename: name of the dtb file to be created
|
||||
#
|
||||
# Since: 7.2
|
||||
#
|
||||
# Example:
|
||||
# {"execute": "dumpdtb"}
|
||||
# "arguments": { "filename": "fdt.dtb" } }
|
||||
#
|
||||
##
|
||||
{ 'command': 'dumpdtb',
|
||||
'data': { 'filename': 'str' },
|
||||
'if': 'CONFIG_FDT' }
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include "hw/loader.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qapi/qapi-commands-machine.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "monitor/hmp.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
|
@ -643,3 +646,37 @@ out:
|
|||
g_free(propcells);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qmp_dumpdtb(const char *filename, Error **errp)
|
||||
{
|
||||
g_autoptr(GError) err = NULL;
|
||||
uint32_t size;
|
||||
|
||||
if (!current_machine->fdt) {
|
||||
error_setg(errp, "This machine doesn't have a FDT");
|
||||
return;
|
||||
}
|
||||
|
||||
size = fdt_totalsize(current_machine->fdt);
|
||||
|
||||
g_assert(size > 0);
|
||||
|
||||
if (!g_file_set_contents(filename, current_machine->fdt, size, &err)) {
|
||||
error_setg(errp, "Error saving FDT to file %s: %s",
|
||||
filename, err->message);
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *filename = qdict_get_str(qdict, "filename");
|
||||
Error *local_err = NULL;
|
||||
|
||||
qmp_dumpdtb(filename, &local_err);
|
||||
|
||||
if (hmp_handle_error(mon, local_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
info_report("dtb dumped to %s", filename);
|
||||
}
|
||||
|
|
|
@ -1247,6 +1247,12 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
|
|||
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
|
||||
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
|
||||
break;
|
||||
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
|
||||
break;
|
||||
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
|
||||
srr0 = SPR_BOOKE_CSRR0;
|
||||
srr1 = SPR_BOOKE_CSRR1;
|
||||
break;
|
||||
case POWERPC_EXCP_RESET: /* System reset exception */
|
||||
if (FIELD_EX64(env->msr, MSR, POW)) {
|
||||
cpu_abort(cs, "Trying to deliver power-saving system reset "
|
||||
|
|
|
@ -810,7 +810,6 @@ static void gen_##name(DisasContext *ctx) \
|
|||
gen_helper_##name(ignored, cpu_env, xt, xa, xb); \
|
||||
tcg_temp_free_i32(ignored); \
|
||||
} \
|
||||
gen_helper_float_check_status(cpu_env); \
|
||||
tcg_temp_free_ptr(xt); \
|
||||
tcg_temp_free_ptr(xa); \
|
||||
tcg_temp_free_ptr(xb); \
|
||||
|
|
Loading…
Reference in New Issue