diff options
Diffstat (limited to 'hw/ppc/ppc405_boards.c')
-rw-r--r-- | hw/ppc/ppc405_boards.c | 743 |
1 files changed, 349 insertions, 394 deletions
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 972a7a4a3e..4092ebc1ab 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -25,7 +25,6 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" -#include "qemu-common.h" #include "qemu/datadir.h" #include "cpu.h" #include "hw/ppc/ppc.h" @@ -41,327 +40,364 @@ #include "qemu/error-report.h" #include "hw/loader.h" #include "qemu/cutils.h" +#include "elf.h" #define BIOS_FILENAME "ppc405_rom.bin" #define BIOS_SIZE (2 * MiB) -#define KERNEL_LOAD_ADDR 0x00000000 +#define KERNEL_LOAD_ADDR 0x01000000 #define INITRD_LOAD_ADDR 0x01800000 +#define PPC405EP_SDRAM_BASE 0x00000000 +#define PPC405EP_SRAM_BASE 0xFFF00000 +#define PPC405EP_SRAM_SIZE (512 * KiB) + #define USE_FLASH_BIOS -/*****************************************************************************/ -/* PPC405EP reference board (IBM) */ -/* Standalone board with: - * - PowerPC 405EP CPU - * - SDRAM (0x00000000) - * - Flash (0xFFF80000) - * - SRAM (0xFFF00000) - * - NVRAM (0xF0000000) - * - FPGA (0xF0300000) - */ -typedef struct ref405ep_fpga_t ref405ep_fpga_t; -struct ref405ep_fpga_t { - uint8_t reg0; - uint8_t reg1; +#define TYPE_PPC405_MACHINE MACHINE_TYPE_NAME("ppc405") +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405MachineState, PPC405_MACHINE); + +struct Ppc405MachineState { + /* Private */ + MachineState parent_obj; + /* Public */ + + Ppc405SoCState soc; }; -static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) +/* CPU reset handler when booting directly from a loaded kernel */ +static struct boot_info { + uint32_t entry; + uint32_t bdloc; + uint32_t initrd_base; + uint32_t initrd_size; + uint32_t cmdline_base; + uint32_t cmdline_size; +} boot_info; + +static void main_cpu_reset(void *opaque) { - ref405ep_fpga_t *fpga; - uint32_t ret; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; + struct boot_info *bi = env->load_info; - fpga = opaque; - switch (addr) { - case 0x0: - ret = fpga->reg0; - break; - case 0x1: - ret = fpga->reg1; - break; - default: - ret = 0; - break; - } + cpu_reset(CPU(cpu)); - return ret; + /* stack: top of sram */ + env->gpr[1] = PPC405EP_SRAM_BASE + PPC405EP_SRAM_SIZE - 8; + + /* Tune our boot state */ + env->gpr[3] = bi->bdloc; + env->gpr[4] = bi->initrd_base; + env->gpr[5] = bi->initrd_base + bi->initrd_size; + env->gpr[6] = bi->cmdline_base; + env->gpr[7] = bi->cmdline_size; + + env->nip = bi->entry; } -static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, - unsigned size) +/* Bootinfo as set-up by u-boot */ +typedef struct { + uint32_t bi_memstart; + uint32_t bi_memsize; + uint32_t bi_flashstart; + uint32_t bi_flashsize; + uint32_t bi_flashoffset; /* 0x10 */ + uint32_t bi_sramstart; + uint32_t bi_sramsize; + uint32_t bi_bootflags; + uint32_t bi_ipaddr; /* 0x20 */ + uint8_t bi_enetaddr[6]; + uint16_t bi_ethspeed; + uint32_t bi_intfreq; + uint32_t bi_busfreq; /* 0x30 */ + uint32_t bi_baudrate; + uint8_t bi_s_version[4]; + uint8_t bi_r_version[32]; + uint32_t bi_procfreq; + uint32_t bi_plb_busfreq; + uint32_t bi_pci_busfreq; + uint8_t bi_pci_enetaddr[6]; + uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */ + uint32_t bi_opbfreq; + uint32_t bi_iic_fast[2]; +} ppc4xx_bd_info_t; + +static void ppc405_set_default_bootinfo(ppc4xx_bd_info_t *bd, + ram_addr_t ram_size) { - ref405ep_fpga_t *fpga; + memset(bd, 0, sizeof(*bd)); + + bd->bi_memstart = PPC405EP_SDRAM_BASE; + bd->bi_memsize = ram_size; + bd->bi_sramstart = PPC405EP_SRAM_BASE; + bd->bi_sramsize = PPC405EP_SRAM_SIZE; + bd->bi_bootflags = 0; + bd->bi_intfreq = 133333333; + bd->bi_busfreq = 33333333; + bd->bi_baudrate = 115200; + bd->bi_s_version[0] = 'Q'; + bd->bi_s_version[1] = 'M'; + bd->bi_s_version[2] = 'U'; + bd->bi_s_version[3] = '\0'; + bd->bi_r_version[0] = 'Q'; + bd->bi_r_version[1] = 'E'; + bd->bi_r_version[2] = 'M'; + bd->bi_r_version[3] = 'U'; + bd->bi_r_version[4] = '\0'; + bd->bi_procfreq = 133333333; + bd->bi_plb_busfreq = 33333333; + bd->bi_pci_busfreq = 33333333; + bd->bi_opbfreq = 33333333; +} - fpga = opaque; - switch (addr) { - case 0x0: - /* Read only */ - break; - case 0x1: - fpga->reg1 = value; - break; - default: - break; +static ram_addr_t __ppc405_set_bootinfo(CPUPPCState *env, ppc4xx_bd_info_t *bd) +{ + CPUState *cs = env_cpu(env); + ram_addr_t bdloc; + int i, n; + + /* We put the bd structure at the top of memory */ + if (bd->bi_memsize >= 0x01000000UL) { + bdloc = 0x01000000UL - sizeof(ppc4xx_bd_info_t); + } else { + bdloc = bd->bi_memsize - sizeof(ppc4xx_bd_info_t); + } + stl_be_phys(cs->as, bdloc + 0x00, bd->bi_memstart); + stl_be_phys(cs->as, bdloc + 0x04, bd->bi_memsize); + stl_be_phys(cs->as, bdloc + 0x08, bd->bi_flashstart); + stl_be_phys(cs->as, bdloc + 0x0C, bd->bi_flashsize); + stl_be_phys(cs->as, bdloc + 0x10, bd->bi_flashoffset); + stl_be_phys(cs->as, bdloc + 0x14, bd->bi_sramstart); + stl_be_phys(cs->as, bdloc + 0x18, bd->bi_sramsize); + stl_be_phys(cs->as, bdloc + 0x1C, bd->bi_bootflags); + stl_be_phys(cs->as, bdloc + 0x20, bd->bi_ipaddr); + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + 0x24 + i, bd->bi_enetaddr[i]); + } + stw_be_phys(cs->as, bdloc + 0x2A, bd->bi_ethspeed); + stl_be_phys(cs->as, bdloc + 0x2C, bd->bi_intfreq); + stl_be_phys(cs->as, bdloc + 0x30, bd->bi_busfreq); + stl_be_phys(cs->as, bdloc + 0x34, bd->bi_baudrate); + for (i = 0; i < 4; i++) { + stb_phys(cs->as, bdloc + 0x38 + i, bd->bi_s_version[i]); + } + for (i = 0; i < 32; i++) { + stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]); + } + stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_procfreq); + stl_be_phys(cs->as, bdloc + 0x60, bd->bi_plb_busfreq); + stl_be_phys(cs->as, bdloc + 0x64, bd->bi_pci_busfreq); + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + 0x68 + i, bd->bi_pci_enetaddr[i]); + } + n = 0x70; /* includes 2 bytes hole */ + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]); + } + stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq); + n += 4; + for (i = 0; i < 2; i++) { + stl_be_phys(cs->as, bdloc + n, bd->bi_iic_fast[i]); + n += 4; } -} -static const MemoryRegionOps ref405ep_fpga_ops = { - .read = ref405ep_fpga_readb, - .write = ref405ep_fpga_writeb, - .impl.min_access_size = 1, - .impl.max_access_size = 1, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .endianness = DEVICE_BIG_ENDIAN, -}; + return bdloc; +} -static void ref405ep_fpga_reset (void *opaque) +static ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size) { - ref405ep_fpga_t *fpga; + ppc4xx_bd_info_t bd; - fpga = opaque; - fpga->reg0 = 0x00; - fpga->reg1 = 0x0F; + memset(&bd, 0, sizeof(bd)); + + ppc405_set_default_bootinfo(&bd, ram_size); + + return __ppc405_set_bootinfo(env, &bd); } -static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) +static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu) { - ref405ep_fpga_t *fpga; - MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); + CPUPPCState *env = &cpu->env; + hwaddr boot_entry; + hwaddr kernel_base; + int kernel_size; + hwaddr initrd_base; + int initrd_size; + ram_addr_t bdloc; + int len; - fpga = g_malloc0(sizeof(ref405ep_fpga_t)); - memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga, - "fpga", 0x00000100); - memory_region_add_subregion(sysmem, base, fpga_memory); - qemu_register_reset(&ref405ep_fpga_reset, fpga); + bdloc = ppc405_set_bootinfo(env, machine->ram_size); + boot_info.bdloc = bdloc; + + kernel_size = load_elf(machine->kernel_filename, NULL, NULL, NULL, + &boot_entry, &kernel_base, NULL, NULL, + 1, PPC_ELF_MACHINE, 0, 0); + if (kernel_size < 0) { + error_report("Could not load kernel '%s' : %s", + machine->kernel_filename, load_elf_strerror(kernel_size)); + exit(1); + } + boot_info.entry = boot_entry; + + /* load initrd */ + if (machine->initrd_filename) { + initrd_base = INITRD_LOAD_ADDR; + 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'", + machine->initrd_filename); + exit(1); + } + + boot_info.initrd_base = initrd_base; + boot_info.initrd_size = initrd_size; + } + + if (machine->kernel_cmdline) { + len = strlen(machine->kernel_cmdline); + bdloc -= ((len + 255) & ~255); + cpu_physical_memory_write(bdloc, machine->kernel_cmdline, len + 1); + boot_info.cmdline_base = bdloc; + boot_info.cmdline_size = bdloc + len; + } + + /* Install our custom reset handler to start from Linux */ + qemu_register_reset(main_cpu_reset, cpu); + env->load_info = &boot_info; } -static void ref405ep_init(MachineState *machine) +static void ppc405_init(MachineState *machine) { - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *bios_name = machine->firmware ?: BIOS_FILENAME; + Ppc405MachineState *ppc405 = PPC405_MACHINE(machine); const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - char *filename; - ppc4xx_bd_info_t bd; - CPUPPCState *env; - DeviceState *dev; - SysBusDevice *s; - MemoryRegion *bios; - MemoryRegion *sram = g_new(MemoryRegion, 1); - ram_addr_t bdloc; - MemoryRegion *ram_memories = g_new(MemoryRegion, 2); - hwaddr ram_bases[2], ram_sizes[2]; - target_ulong sram_size; - long bios_size; - //int phy_addr = 0; - //static int phy_addr = 1; - target_ulong kernel_base, initrd_base; - long kernel_size, initrd_size; - int linux_boot; - int len; - DriveInfo *dinfo; MemoryRegion *sysmem = get_system_memory(); - DeviceState *uicdev; - 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_link(OBJECT(&ppc405->soc), "dram", + OBJECT(machine->ram), &error_abort); + object_property_set_uint(OBJECT(&ppc405->soc), "sys-clk", 33333333, + &error_abort); + qdev_realize(DEVICE(&ppc405->soc), NULL, &error_fatal); - /* XXX: fix this */ - memory_region_init_alias(&ram_memories[0], NULL, "ef405ep.ram.alias", - machine->ram, 0, machine->ram_size); - ram_bases[0] = 0; - ram_sizes[0] = machine->ram_size; - memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0); - ram_bases[1] = 0x00000000; - ram_sizes[1] = 0x00000000; - env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, - 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - /* allocate SRAM */ - sram_size = 512 * KiB; - memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size, - &error_fatal); - memory_region_add_subregion(sysmem, 0xFFF00000, sram); /* allocate and load BIOS */ -#ifdef USE_FLASH_BIOS - dinfo = drive_get(IF_PFLASH, 0, 0); - if (dinfo) { - bios_size = 8 * MiB; - pflash_cfi02_register((uint32_t)(-bios_size), - "ef405ep.bios", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - } else -#endif - { - bios = g_new(MemoryRegion, 1); + if (machine->firmware) { + MemoryRegion *bios = g_new(MemoryRegion, 1); + g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + machine->firmware); + long bios_size; + memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE, &error_fatal); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size = load_image_size(filename, - memory_region_get_ram_ptr(bios), - BIOS_SIZE); - g_free(filename); - if (bios_size < 0) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - bios_size = (bios_size + 0xfff) & ~0xfff; - memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); - } else if (!qtest_enabled() || kernel_filename != NULL) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); + if (!filename) { + error_report("Could not find firmware '%s'", machine->firmware); + exit(1); + } + + bios_size = load_image_size(filename, + memory_region_get_ram_ptr(bios), + BIOS_SIZE); + if (bios_size < 0) { + error_report("Could not load PowerPC BIOS '%s'", machine->firmware); exit(1); - } else { - /* Avoid an uninitialized variable warning */ - bios_size = -1; } + + bios_size = (bios_size + 0xfff) & ~0xfff; + memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } - /* Register FPGA */ - ref405ep_fpga_init(sysmem, 0xF0300000); - /* Register NVRAM */ - dev = qdev_new("sysbus-m48t08"); - qdev_prop_set_int32(dev, "base-year", 1968); - s = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, 0xF0000000); - /* Load kernel */ - linux_boot = (kernel_filename != NULL); - if (linux_boot) { - memset(&bd, 0, sizeof(bd)); - bd.bi_memstart = 0x00000000; - bd.bi_memsize = machine->ram_size; - bd.bi_flashstart = -bios_size; - bd.bi_flashsize = -bios_size; - bd.bi_flashoffset = 0; - bd.bi_sramstart = 0xFFF00000; - bd.bi_sramsize = sram_size; - bd.bi_bootflags = 0; - bd.bi_intfreq = 133333333; - bd.bi_busfreq = 33333333; - bd.bi_baudrate = 115200; - bd.bi_s_version[0] = 'Q'; - bd.bi_s_version[1] = 'M'; - bd.bi_s_version[2] = 'U'; - bd.bi_s_version[3] = '\0'; - bd.bi_r_version[0] = 'Q'; - bd.bi_r_version[1] = 'E'; - bd.bi_r_version[2] = 'M'; - bd.bi_r_version[3] = 'U'; - bd.bi_r_version[4] = '\0'; - bd.bi_procfreq = 133333333; - bd.bi_plb_busfreq = 33333333; - bd.bi_pci_busfreq = 33333333; - bd.bi_opbfreq = 33333333; - bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001); - env->gpr[3] = bdloc; + + /* Load kernel and initrd using U-Boot images */ + if (kernel_filename && machine->firmware) { + target_ulong kernel_base, initrd_base; + long kernel_size, initrd_size; + kernel_base = KERNEL_LOAD_ADDR; - /* now we can load the kernel */ kernel_size = load_image_targphys(kernel_filename, kernel_base, machine->ram_size - kernel_base); if (kernel_size < 0) { error_report("could not load kernel '%s'", kernel_filename); exit(1); } - printf("Load kernel size %ld at " TARGET_FMT_lx, - kernel_size, kernel_base); + /* load initrd */ - if (initrd_filename) { + if (machine->initrd_filename) { initrd_base = INITRD_LOAD_ADDR; - initrd_size = load_image_targphys(initrd_filename, 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); } - } else { - initrd_base = 0; - initrd_size = 0; - } - env->gpr[4] = initrd_base; - env->gpr[5] = initrd_size; - if (kernel_cmdline != NULL) { - len = strlen(kernel_cmdline); - bdloc -= ((len + 255) & ~255); - cpu_physical_memory_write(bdloc, kernel_cmdline, len + 1); - env->gpr[6] = bdloc; - env->gpr[7] = bdloc + len; - } else { - env->gpr[6] = 0; - env->gpr[7] = 0; } - env->nip = KERNEL_LOAD_ADDR; - } else { - kernel_base = 0; - kernel_size = 0; - initrd_base = 0; - initrd_size = 0; - bdloc = 0; + + /* 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); } } -static void ref405ep_class_init(ObjectClass *oc, void *data) +static void ppc405_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->desc = "ref405ep"; - mc->init = ref405ep_init; - mc->default_ram_size = 0x08000000; - mc->default_ram_id = "ef405ep.ram"; + mc->desc = "PPC405 generic machine"; + mc->init = ppc405_init; + mc->default_ram_size = 128 * MiB; + mc->default_ram_id = "ppc405.ram"; } -static const TypeInfo ref405ep_type = { - .name = MACHINE_TYPE_NAME("ref405ep"), +static const TypeInfo ppc405_machine_type = { + .name = TYPE_PPC405_MACHINE, .parent = TYPE_MACHINE, - .class_init = ref405ep_class_init, + .instance_size = sizeof(Ppc405MachineState), + .class_init = ppc405_machine_class_init, + .abstract = true, }; /*****************************************************************************/ -/* AMCC Taihu evaluation board */ -/* - PowerPC 405EP processor - * - SDRAM 128 MB at 0x00000000 - * - Boot flash 2 MB at 0xFFE00000 - * - Application flash 32 MB at 0xFC000000 - * - 2 serial ports - * - 2 ethernet PHY - * - 1 USB 1.1 device 0x50000000 - * - 1 LCD display 0x50100000 - * - 1 CPLD 0x50100000 - * - 1 I2C EEPROM - * - 1 I2C thermal sensor - * - a set of LEDs - * - bit-bang SPI port using GPIOs - * - 1 EBC interface connector 0 0x50200000 - * - 1 cardbus controller + expansion slot. - * - 1 PCI expansion slot. +/* PPC405EP reference board (IBM) */ +/* + * Standalone board with: + * - PowerPC 405EP CPU + * - SDRAM (0x00000000) + * - Flash (0xFFF80000) + * - SRAM (0xFFF00000) + * - NVRAM (0xF0000000) + * - FPGA (0xF0300000) */ -typedef struct taihu_cpld_t taihu_cpld_t; -struct taihu_cpld_t { + +#define PPC405EP_NVRAM_BASE 0xF0000000 +#define PPC405EP_FPGA_BASE 0xF0300000 +#define PPC405EP_FLASH_BASE 0xFFF80000 + +#define TYPE_REF405EP_FPGA "ref405ep-fpga" +OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA); +struct Ref405epFpgaState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint8_t reg0; uint8_t reg1; }; -static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) { - taihu_cpld_t *cpld; + Ref405epFpgaState *fpga = opaque; uint32_t ret; - cpld = opaque; switch (addr) { case 0x0: - ret = cpld->reg0; + ret = fpga->reg0; break; case 0x1: - ret = cpld->reg1; + ret = fpga->reg1; break; default: ret = 0; @@ -371,194 +407,113 @@ static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size) return ret; } -static void taihu_cpld_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) +static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, + unsigned size) { - taihu_cpld_t *cpld; + Ref405epFpgaState *fpga = opaque; - cpld = opaque; switch (addr) { case 0x0: /* Read only */ break; case 0x1: - cpld->reg1 = value; + fpga->reg1 = value; break; default: break; } } -static const MemoryRegionOps taihu_cpld_ops = { - .read = taihu_cpld_read, - .write = taihu_cpld_write, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static const MemoryRegionOps ref405ep_fpga_ops = { + .read = ref405ep_fpga_readb, + .write = ref405ep_fpga_writeb, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_BIG_ENDIAN, }; -static void taihu_cpld_reset (void *opaque) +static void ref405ep_fpga_reset(DeviceState *dev) { - taihu_cpld_t *cpld; + Ref405epFpgaState *fpga = REF405EP_FPGA(dev); - cpld = opaque; - cpld->reg0 = 0x01; - cpld->reg1 = 0x80; + fpga->reg0 = 0x00; + fpga->reg1 = 0x0F; } -static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) +static void ref405ep_fpga_realize(DeviceState *dev, Error **errp) { - taihu_cpld_t *cpld; - MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); + Ref405epFpgaState *s = REF405EP_FPGA(dev); - cpld = g_malloc0(sizeof(taihu_cpld_t)); - memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100); - memory_region_add_subregion(sysmem, base, cpld_memory); - qemu_register_reset(&taihu_cpld_reset, cpld); + memory_region_init_io(&s->iomem, OBJECT(s), &ref405ep_fpga_ops, s, + "fpga", 0x00000100); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); } -static void taihu_405ep_init(MachineState *machine) +static void ref405ep_fpga_class_init(ObjectClass *oc, void *data) { - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *bios_name = machine->firmware ?: BIOS_FILENAME; - const char *kernel_filename = machine->kernel_filename; - const char *initrd_filename = machine->initrd_filename; - char *filename; - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *bios; - MemoryRegion *ram_memories = g_new(MemoryRegion, 2); - hwaddr ram_bases[2], ram_sizes[2]; - long bios_size; - target_ulong kernel_base, initrd_base; - long kernel_size, initrd_size; - int linux_boot; - int fl_idx; - DriveInfo *dinfo; - DeviceState *uicdev; - - 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); - } + DeviceClass *dc = DEVICE_CLASS(oc); - ram_bases[0] = 0; - ram_sizes[0] = 0x04000000; - memory_region_init_alias(&ram_memories[0], NULL, - "taihu_405ep.ram-0", machine->ram, ram_bases[0], - ram_sizes[0]); - ram_bases[1] = 0x04000000; - ram_sizes[1] = 0x04000000; - memory_region_init_alias(&ram_memories[1], NULL, - "taihu_405ep.ram-1", machine->ram, ram_bases[1], - ram_sizes[1]); - ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, - 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - /* allocate and load BIOS */ - fl_idx = 0; -#if defined(USE_FLASH_BIOS) - dinfo = drive_get(IF_PFLASH, 0, fl_idx); - if (dinfo) { - bios_size = 2 * MiB; - pflash_cfi02_register(0xFFE00000, - "taihu_405ep.bios", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - fl_idx++; - } else -#endif - { - bios = g_new(MemoryRegion, 1); - memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, - &error_fatal); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size = load_image_size(filename, - memory_region_get_ram_ptr(bios), - BIOS_SIZE); - g_free(filename); - if (bios_size < 0) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - bios_size = (bios_size + 0xfff) & ~0xfff; - memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); - } else if (!qtest_enabled()) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - } - /* Register Linux flash */ - dinfo = drive_get(IF_PFLASH, 0, fl_idx); - if (dinfo) { - bios_size = 32 * MiB; - pflash_cfi02_register(0xfc000000, "taihu_405ep.flash", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - fl_idx++; - } - /* Register CLPD & LCD display */ - taihu_cpld_init(sysmem, 0x50100000); - /* Load kernel */ - linux_boot = (kernel_filename != NULL); - if (linux_boot) { - kernel_base = KERNEL_LOAD_ADDR; - /* now we can load the kernel */ - kernel_size = load_image_targphys(kernel_filename, kernel_base, - machine->ram_size - kernel_base); - if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - /* load initrd */ - if (initrd_filename) { - initrd_base = INITRD_LOAD_ADDR; - initrd_size = load_image_targphys(initrd_filename, initrd_base, - machine->ram_size - initrd_base); - if (initrd_size < 0) { - error_report("could not load initial ram disk '%s'", - initrd_filename); - exit(1); - } - } else { - initrd_base = 0; - initrd_size = 0; - } - } else { - kernel_base = 0; - kernel_size = 0; - initrd_base = 0; - initrd_size = 0; - } + dc->realize = ref405ep_fpga_realize; + dc->reset = ref405ep_fpga_reset; + /* Reason: only works as part of a ppc405 board */ + dc->user_creatable = false; +} + +static const TypeInfo ref405ep_fpga_type = { + .name = TYPE_REF405EP_FPGA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ref405epFpgaState), + .class_init = ref405ep_fpga_class_init, +}; + +static void ref405ep_init(MachineState *machine) +{ + DeviceState *dev; + SysBusDevice *s; + MemoryRegion *sram = g_new(MemoryRegion, 1); + + ppc405_init(machine); + + /* allocate SRAM */ + memory_region_init_ram(sram, NULL, "ref405ep.sram", PPC405EP_SRAM_SIZE, + &error_fatal); + memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram); + + /* Register FPGA */ + dev = qdev_new(TYPE_REF405EP_FPGA); + object_property_add_child(OBJECT(machine), "fpga", OBJECT(dev)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, PPC405EP_FPGA_BASE); + + /* Register NVRAM */ + dev = qdev_new("sysbus-m48t08"); + qdev_prop_set_int32(dev, "base-year", 1968); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE); } -static void taihu_class_init(ObjectClass *oc, void *data) +static void ref405ep_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->desc = "taihu"; - mc->init = taihu_405ep_init; - mc->default_ram_size = 0x08000000; - mc->default_ram_id = "taihu_405ep.ram"; + mc->desc = "ref405ep"; + mc->init = ref405ep_init; } -static const TypeInfo taihu_type = { - .name = MACHINE_TYPE_NAME("taihu"), - .parent = TYPE_MACHINE, - .class_init = taihu_class_init, +static const TypeInfo ref405ep_type = { + .name = MACHINE_TYPE_NAME("ref405ep"), + .parent = TYPE_PPC405_MACHINE, + .class_init = ref405ep_class_init, }; static void ppc405_machine_init(void) { + type_register_static(&ppc405_machine_type); type_register_static(&ref405ep_type); - type_register_static(&taihu_type); + type_register_static(&ref405ep_fpga_type); } type_init(ppc405_machine_init) |