14b387f9eSBALATON Zoltan /* 24b387f9eSBALATON Zoltan * QEMU aCube Sam460ex board emulation 34b387f9eSBALATON Zoltan * 44b387f9eSBALATON Zoltan * Copyright (c) 2012 François Revol 508fd9917SBALATON Zoltan * Copyright (c) 2016-2019 BALATON Zoltan 64b387f9eSBALATON Zoltan * 74b387f9eSBALATON Zoltan * This file is derived from hw/ppc440_bamboo.c, 84b387f9eSBALATON Zoltan * the copyright for that material belongs to the original owners. 94b387f9eSBALATON Zoltan * 104b387f9eSBALATON Zoltan * This work is licensed under the GNU GPL license version 2 or later. 114b387f9eSBALATON Zoltan * 124b387f9eSBALATON Zoltan */ 134b387f9eSBALATON Zoltan 144b387f9eSBALATON Zoltan #include "qemu/osdep.h" 15ab3dd749SPhilippe Mathieu-Daudé #include "qemu/units.h" 164b387f9eSBALATON Zoltan #include "qemu-common.h" 172c65db5eSPaolo Bonzini #include "qemu/datadir.h" 184b387f9eSBALATON Zoltan #include "qemu/error-report.h" 194b387f9eSBALATON Zoltan #include "qapi/error.h" 204b387f9eSBALATON Zoltan #include "hw/boards.h" 214b387f9eSBALATON Zoltan #include "sysemu/kvm.h" 224b387f9eSBALATON Zoltan #include "kvm_ppc.h" 234b387f9eSBALATON Zoltan #include "sysemu/device_tree.h" 244b387f9eSBALATON Zoltan #include "sysemu/block-backend.h" 254b387f9eSBALATON Zoltan #include "hw/loader.h" 264b387f9eSBALATON Zoltan #include "elf.h" 274b387f9eSBALATON Zoltan #include "exec/address-spaces.h" 284b387f9eSBALATON Zoltan #include "exec/memory.h" 2972a56a1fSMichael S. Tsirkin #include "ppc440.h" 3072a56a1fSMichael S. Tsirkin #include "ppc405.h" 314b387f9eSBALATON Zoltan #include "hw/block/flash.h" 324b387f9eSBALATON Zoltan #include "sysemu/sysemu.h" 334b387f9eSBALATON Zoltan #include "sysemu/qtest.h" 3471e8a915SMarkus Armbruster #include "sysemu/reset.h" 354b387f9eSBALATON Zoltan #include "hw/sysbus.h" 364b387f9eSBALATON Zoltan #include "hw/char/serial.h" 374b387f9eSBALATON Zoltan #include "hw/i2c/ppc4xx_i2c.h" 3893198b6cSCorey Minyard #include "hw/i2c/smbus_eeprom.h" 394b387f9eSBALATON Zoltan #include "hw/usb/hcd-ehci.h" 40ad633de6SDavid Gibson #include "hw/ppc/fdt.h" 41a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 42706e9442SPeter Maydell #include "hw/intc/ppc-uic.h" 434b387f9eSBALATON Zoltan 4443f7868dSGuenter Roeck #include <libfdt.h> 4543f7868dSGuenter Roeck 464b387f9eSBALATON Zoltan #define BINARY_DEVICE_TREE_FILE "canyonlands.dtb" 474b387f9eSBALATON Zoltan #define UBOOT_FILENAME "u-boot-sam460-20100605.bin" 484b387f9eSBALATON Zoltan /* to extract the official U-Boot bin from the updater: */ 494b387f9eSBALATON Zoltan /* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \ 504b387f9eSBALATON Zoltan if=updater/updater-460 of=u-boot-sam460-20100605.bin */ 514b387f9eSBALATON Zoltan 524b387f9eSBALATON Zoltan /* from Sam460 U-Boot include/configs/Sam460ex.h */ 534b387f9eSBALATON Zoltan #define FLASH_BASE 0xfff00000 544b387f9eSBALATON Zoltan #define FLASH_BASE_H 0x4 55ab3dd749SPhilippe Mathieu-Daudé #define FLASH_SIZE (1 * MiB) 564b387f9eSBALATON Zoltan #define UBOOT_LOAD_BASE 0xfff80000 574b387f9eSBALATON Zoltan #define UBOOT_SIZE 0x00080000 584b387f9eSBALATON Zoltan #define UBOOT_ENTRY 0xfffffffc 594b387f9eSBALATON Zoltan 604b387f9eSBALATON Zoltan /* from U-Boot */ 614b387f9eSBALATON Zoltan #define EPAPR_MAGIC (0x45504150) 624b387f9eSBALATON Zoltan #define KERNEL_ADDR 0x1000000 634b387f9eSBALATON Zoltan #define FDT_ADDR 0x1800000 644b387f9eSBALATON Zoltan #define RAMDISK_ADDR 0x1900000 654b387f9eSBALATON Zoltan 664b387f9eSBALATON Zoltan /* Sam460ex IRQ MAP: 674b387f9eSBALATON Zoltan IRQ0 = ETH_INT 684b387f9eSBALATON Zoltan IRQ1 = FPGA_INT 694b387f9eSBALATON Zoltan IRQ2 = PCI_INT (PCIA, PCIB, PCIC, PCIB) 704b387f9eSBALATON Zoltan IRQ3 = FPGA_INT2 714b387f9eSBALATON Zoltan IRQ11 = RTC_INT 724b387f9eSBALATON Zoltan IRQ12 = SM502_INT 734b387f9eSBALATON Zoltan */ 744b387f9eSBALATON Zoltan 75f8815532SBALATON Zoltan #define CPU_FREQ 1150000000 7643f7868dSGuenter Roeck #define PLB_FREQ 230000000 7743f7868dSGuenter Roeck #define OPB_FREQ 115000000 7843f7868dSGuenter Roeck #define EBC_FREQ 115000000 7943f7868dSGuenter Roeck #define UART_FREQ 11059200 804b387f9eSBALATON Zoltan #define SDRAM_NR_BANKS 4 814b387f9eSBALATON Zoltan 826a9938a3SBALATON Zoltan /* The SoC could also handle 4 GiB but firmware does not work with that. */ 836a9938a3SBALATON Zoltan /* Maybe it overflows a signed 32 bit number somewhere? */ 847d8ccf58SBALATON Zoltan static const ram_addr_t ppc460ex_sdram_bank_sizes[] = { 856a9938a3SBALATON Zoltan 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB, 866a9938a3SBALATON Zoltan 32 * MiB, 0 874b387f9eSBALATON Zoltan }; 884b387f9eSBALATON Zoltan 894b387f9eSBALATON Zoltan struct boot_info { 904b387f9eSBALATON Zoltan uint32_t dt_base; 914b387f9eSBALATON Zoltan uint32_t dt_size; 924b387f9eSBALATON Zoltan uint32_t entry; 934b387f9eSBALATON Zoltan }; 944b387f9eSBALATON Zoltan 954b387f9eSBALATON Zoltan static int sam460ex_load_uboot(void) 964b387f9eSBALATON Zoltan { 97f30bc995SMarkus Armbruster /* 98f30bc995SMarkus Armbruster * This first creates 1MiB of flash memory mapped at the end of 99f30bc995SMarkus Armbruster * the 32-bit address space (0xFFF00000..0xFFFFFFFF). 100f30bc995SMarkus Armbruster * 101f30bc995SMarkus Armbruster * If_PFLASH unit 0 is defined, the flash memory is initialized 102f30bc995SMarkus Armbruster * from that block backend. 103f30bc995SMarkus Armbruster * 104f30bc995SMarkus Armbruster * Else, it's initialized to zero. And then 512KiB of ROM get 105f30bc995SMarkus Armbruster * mapped on top of its second half (0xFFF80000..0xFFFFFFFF), 106f30bc995SMarkus Armbruster * initialized from u-boot-sam460-20100605.bin. 107f30bc995SMarkus Armbruster * 108f30bc995SMarkus Armbruster * This doesn't smell right. 109f30bc995SMarkus Armbruster * 110f30bc995SMarkus Armbruster * The physical hardware appears to have 512KiB flash memory. 111f30bc995SMarkus Armbruster * 112f30bc995SMarkus Armbruster * TODO Figure out what we really need here, and clean this up. 113f30bc995SMarkus Armbruster */ 114f30bc995SMarkus Armbruster 1154b387f9eSBALATON Zoltan DriveInfo *dinfo; 1164b387f9eSBALATON Zoltan 1174b387f9eSBALATON Zoltan dinfo = drive_get(IF_PFLASH, 0, 0); 118f30bc995SMarkus Armbruster if (!pflash_cfi01_register(FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32), 119940d5b13SMarkus Armbruster "sam460ex.flash", FLASH_SIZE, 120f30bc995SMarkus Armbruster dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, 121ce14710fSMarkus Armbruster 64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1)) { 122371b74e2SMao Zhongyi error_report("Error registering flash memory"); 1234b387f9eSBALATON Zoltan /* XXX: return an error instead? */ 1244b387f9eSBALATON Zoltan exit(1); 1254b387f9eSBALATON Zoltan } 1264b387f9eSBALATON Zoltan 127f30bc995SMarkus Armbruster if (!dinfo) { 1284b387f9eSBALATON Zoltan /*error_report("No flash image given with the 'pflash' parameter," 1294b387f9eSBALATON Zoltan " using default u-boot image");*/ 130f30bc995SMarkus Armbruster rom_add_file_fixed(UBOOT_FILENAME, 131f30bc995SMarkus Armbruster UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32), 132f30bc995SMarkus Armbruster -1); 1334b387f9eSBALATON Zoltan } 1344b387f9eSBALATON Zoltan 1354b387f9eSBALATON Zoltan return 0; 1364b387f9eSBALATON Zoltan } 1374b387f9eSBALATON Zoltan 1384b387f9eSBALATON Zoltan static int sam460ex_load_device_tree(hwaddr addr, 1394b387f9eSBALATON Zoltan uint32_t ramsize, 1404b387f9eSBALATON Zoltan hwaddr initrd_base, 1414b387f9eSBALATON Zoltan hwaddr initrd_size, 1424b387f9eSBALATON Zoltan const char *kernel_cmdline) 1434b387f9eSBALATON Zoltan { 1444b387f9eSBALATON Zoltan uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) }; 1454b387f9eSBALATON Zoltan char *filename; 1464b387f9eSBALATON Zoltan int fdt_size; 1474b387f9eSBALATON Zoltan void *fdt; 148f8815532SBALATON Zoltan uint32_t tb_freq = CPU_FREQ; 149f8815532SBALATON Zoltan uint32_t clock_freq = CPU_FREQ; 15043f7868dSGuenter Roeck int offset; 1514b387f9eSBALATON Zoltan 1524b387f9eSBALATON Zoltan filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); 1534b387f9eSBALATON Zoltan if (!filename) { 15451b0d834SDavid Gibson error_report("Couldn't find dtb file `%s'", BINARY_DEVICE_TREE_FILE); 15551b0d834SDavid Gibson exit(1); 1564b387f9eSBALATON Zoltan } 1574b387f9eSBALATON Zoltan fdt = load_device_tree(filename, &fdt_size); 15851b0d834SDavid Gibson if (!fdt) { 15951b0d834SDavid Gibson error_report("Couldn't load dtb file `%s'", filename); 1603cc702d6SBALATON Zoltan g_free(filename); 16151b0d834SDavid Gibson exit(1); 1624b387f9eSBALATON Zoltan } 1633cc702d6SBALATON Zoltan g_free(filename); 1644b387f9eSBALATON Zoltan 1654b387f9eSBALATON Zoltan /* Manipulate device tree in memory. */ 1664b387f9eSBALATON Zoltan 167e753f331SDavid Gibson qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, 1684b387f9eSBALATON Zoltan sizeof(mem_reg_property)); 1694b387f9eSBALATON Zoltan 1704b387f9eSBALATON Zoltan /* default FDT doesn't have a /chosen node... */ 1714b387f9eSBALATON Zoltan qemu_fdt_add_subnode(fdt, "/chosen"); 1724b387f9eSBALATON Zoltan 173e753f331SDavid Gibson qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd_base); 1744b387f9eSBALATON Zoltan 175e753f331SDavid Gibson qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", 1764b387f9eSBALATON Zoltan (initrd_base + initrd_size)); 1774b387f9eSBALATON Zoltan 178e753f331SDavid Gibson qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); 1794b387f9eSBALATON Zoltan 1804b387f9eSBALATON Zoltan /* Copy data from the host device tree into the guest. Since the guest can 1814b387f9eSBALATON Zoltan * directly access the timebase without host involvement, we must expose 1824b387f9eSBALATON Zoltan * the correct frequencies. */ 1834b387f9eSBALATON Zoltan if (kvm_enabled()) { 1844b387f9eSBALATON Zoltan tb_freq = kvmppc_get_tbfreq(); 1854b387f9eSBALATON Zoltan clock_freq = kvmppc_get_clockfreq(); 1864b387f9eSBALATON Zoltan } 1874b387f9eSBALATON Zoltan 1884b387f9eSBALATON Zoltan qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency", 1894b387f9eSBALATON Zoltan clock_freq); 1904b387f9eSBALATON Zoltan qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency", 1914b387f9eSBALATON Zoltan tb_freq); 1924b387f9eSBALATON Zoltan 19343f7868dSGuenter Roeck /* Remove cpm node if it exists (it is not emulated) */ 19443f7868dSGuenter Roeck offset = fdt_path_offset(fdt, "/cpm"); 19543f7868dSGuenter Roeck if (offset >= 0) { 196ad633de6SDavid Gibson _FDT(fdt_nop_node(fdt, offset)); 19743f7868dSGuenter Roeck } 19843f7868dSGuenter Roeck 19943f7868dSGuenter Roeck /* set serial port clocks */ 20043f7868dSGuenter Roeck offset = fdt_node_offset_by_compatible(fdt, -1, "ns16550"); 20143f7868dSGuenter Roeck while (offset >= 0) { 202ad633de6SDavid Gibson _FDT(fdt_setprop_cell(fdt, offset, "clock-frequency", UART_FREQ)); 20343f7868dSGuenter Roeck offset = fdt_node_offset_by_compatible(fdt, offset, "ns16550"); 20443f7868dSGuenter Roeck } 20543f7868dSGuenter Roeck 20643f7868dSGuenter Roeck /* some more clocks */ 20743f7868dSGuenter Roeck qemu_fdt_setprop_cell(fdt, "/plb", "clock-frequency", 20843f7868dSGuenter Roeck PLB_FREQ); 20943f7868dSGuenter Roeck qemu_fdt_setprop_cell(fdt, "/plb/opb", "clock-frequency", 21043f7868dSGuenter Roeck OPB_FREQ); 21143f7868dSGuenter Roeck qemu_fdt_setprop_cell(fdt, "/plb/opb/ebc", "clock-frequency", 21243f7868dSGuenter Roeck EBC_FREQ); 21343f7868dSGuenter Roeck 2144b387f9eSBALATON Zoltan rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); 2154b387f9eSBALATON Zoltan g_free(fdt); 2164b387f9eSBALATON Zoltan 21751b0d834SDavid Gibson return fdt_size; 2184b387f9eSBALATON Zoltan } 2194b387f9eSBALATON Zoltan 2204b387f9eSBALATON Zoltan /* Create reset TLB entries for BookE, mapping only the flash memory. */ 2214b387f9eSBALATON Zoltan static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env) 2224b387f9eSBALATON Zoltan { 2234b387f9eSBALATON Zoltan ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; 2244b387f9eSBALATON Zoltan 2254b387f9eSBALATON Zoltan /* on reset the flash is mapped by a shadow TLB, 2264b387f9eSBALATON Zoltan * but since we don't implement them we need to use 2274b387f9eSBALATON Zoltan * the same values U-Boot will use to avoid a fault. 2284b387f9eSBALATON Zoltan */ 2294b387f9eSBALATON Zoltan tlb->attr = 0; 2304b387f9eSBALATON Zoltan tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); 2314b387f9eSBALATON Zoltan tlb->size = 0x10000000; /* up to 0xffffffff */ 2324b387f9eSBALATON Zoltan tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK; 2334b387f9eSBALATON Zoltan tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4; 2344b387f9eSBALATON Zoltan tlb->PID = 0; 2354b387f9eSBALATON Zoltan } 2364b387f9eSBALATON Zoltan 2374b387f9eSBALATON Zoltan /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ 2384b387f9eSBALATON Zoltan static void mmubooke_create_initial_mapping(CPUPPCState *env, 2394b387f9eSBALATON Zoltan target_ulong va, 2404b387f9eSBALATON Zoltan hwaddr pa) 2414b387f9eSBALATON Zoltan { 2424b387f9eSBALATON Zoltan ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; 2434b387f9eSBALATON Zoltan 2444b387f9eSBALATON Zoltan tlb->attr = 0; 2454b387f9eSBALATON Zoltan tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); 2464b387f9eSBALATON Zoltan tlb->size = 1 << 31; /* up to 0x80000000 */ 2474b387f9eSBALATON Zoltan tlb->EPN = va & TARGET_PAGE_MASK; 2484b387f9eSBALATON Zoltan tlb->RPN = pa & TARGET_PAGE_MASK; 2494b387f9eSBALATON Zoltan tlb->PID = 0; 2504b387f9eSBALATON Zoltan } 2514b387f9eSBALATON Zoltan 2524b387f9eSBALATON Zoltan static void main_cpu_reset(void *opaque) 2534b387f9eSBALATON Zoltan { 2544b387f9eSBALATON Zoltan PowerPCCPU *cpu = opaque; 2554b387f9eSBALATON Zoltan CPUPPCState *env = &cpu->env; 2564b387f9eSBALATON Zoltan struct boot_info *bi = env->load_info; 2574b387f9eSBALATON Zoltan 2584b387f9eSBALATON Zoltan cpu_reset(CPU(cpu)); 2594b387f9eSBALATON Zoltan 2604b387f9eSBALATON Zoltan /* either we have a kernel to boot or we jump to U-Boot */ 2614b387f9eSBALATON Zoltan if (bi->entry != UBOOT_ENTRY) { 262ab3dd749SPhilippe Mathieu-Daudé env->gpr[1] = (16 * MiB) - 8; 2634b387f9eSBALATON Zoltan env->gpr[3] = FDT_ADDR; 2644b387f9eSBALATON Zoltan env->nip = bi->entry; 2654b387f9eSBALATON Zoltan 2664b387f9eSBALATON Zoltan /* Create a mapping for the kernel. */ 2674b387f9eSBALATON Zoltan mmubooke_create_initial_mapping(env, 0, 0); 2684b387f9eSBALATON Zoltan env->gpr[6] = tswap32(EPAPR_MAGIC); 269ab3dd749SPhilippe Mathieu-Daudé env->gpr[7] = (16 * MiB) - 8; /* bi->ima_size; */ 2704b387f9eSBALATON Zoltan 2714b387f9eSBALATON Zoltan } else { 2724b387f9eSBALATON Zoltan env->nip = UBOOT_ENTRY; 2734b387f9eSBALATON Zoltan mmubooke_create_initial_mapping_uboot(env); 2744b387f9eSBALATON Zoltan } 2754b387f9eSBALATON Zoltan } 2764b387f9eSBALATON Zoltan 2774b387f9eSBALATON Zoltan static void sam460ex_init(MachineState *machine) 2784b387f9eSBALATON Zoltan { 2794b387f9eSBALATON Zoltan MemoryRegion *address_space_mem = get_system_memory(); 2804b387f9eSBALATON Zoltan MemoryRegion *isa = g_new(MemoryRegion, 1); 2814b387f9eSBALATON Zoltan MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS); 28208fd9917SBALATON Zoltan hwaddr ram_bases[SDRAM_NR_BANKS] = {0}; 28308fd9917SBALATON Zoltan hwaddr ram_sizes[SDRAM_NR_BANKS] = {0}; 2844b387f9eSBALATON Zoltan MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); 285706e9442SPeter Maydell DeviceState *uic[4]; 286706e9442SPeter Maydell qemu_irq mal_irqs[4]; 287706e9442SPeter Maydell int i; 2884b387f9eSBALATON Zoltan PCIBus *pci_bus; 2894b387f9eSBALATON Zoltan PowerPCCPU *cpu; 2904b387f9eSBALATON Zoltan CPUPPCState *env; 29108fd9917SBALATON Zoltan I2CBus *i2c; 2924b387f9eSBALATON Zoltan hwaddr entry = UBOOT_ENTRY; 2934b387f9eSBALATON Zoltan target_long initrd_size = 0; 2944b387f9eSBALATON Zoltan DeviceState *dev; 2954b387f9eSBALATON Zoltan SysBusDevice *sbdev; 2964b387f9eSBALATON Zoltan struct boot_info *boot_info; 29708fd9917SBALATON Zoltan uint8_t *spd_data; 29808fd9917SBALATON Zoltan int success; 2994b387f9eSBALATON Zoltan 3004b387f9eSBALATON Zoltan cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); 3014b387f9eSBALATON Zoltan env = &cpu->env; 3024b387f9eSBALATON Zoltan if (env->mmu_model != POWERPC_MMU_BOOKE) { 3034b387f9eSBALATON Zoltan error_report("Only MMU model BookE is supported by this machine."); 3044b387f9eSBALATON Zoltan exit(1); 3054b387f9eSBALATON Zoltan } 3064b387f9eSBALATON Zoltan 3074b387f9eSBALATON Zoltan qemu_register_reset(main_cpu_reset, cpu); 3084b387f9eSBALATON Zoltan boot_info = g_malloc0(sizeof(*boot_info)); 3094b387f9eSBALATON Zoltan env->load_info = boot_info; 3104b387f9eSBALATON Zoltan 311f8815532SBALATON Zoltan ppc_booke_timers_init(cpu, CPU_FREQ, 0); 3124b387f9eSBALATON Zoltan ppc_dcr_init(env, NULL, NULL); 3134b387f9eSBALATON Zoltan 3144b387f9eSBALATON Zoltan /* PLB arbitrer */ 3154b387f9eSBALATON Zoltan ppc4xx_plb_init(env); 3164b387f9eSBALATON Zoltan 3174b387f9eSBALATON Zoltan /* interrupt controllers */ 318706e9442SPeter Maydell for (i = 0; i < ARRAY_SIZE(uic); i++) { 319706e9442SPeter Maydell SysBusDevice *sbd; 320706e9442SPeter Maydell /* 321706e9442SPeter Maydell * UICs 1, 2 and 3 are cascaded through UIC 0. 322706e9442SPeter Maydell * input_ints[n] is the interrupt number on UIC 0 which 323706e9442SPeter Maydell * the INT output of UIC n is connected to. The CINT output 324706e9442SPeter Maydell * of UIC n connects to input_ints[n] + 1. 325706e9442SPeter Maydell * The entry in input_ints[] for UIC 0 is ignored, because UIC 0's 326706e9442SPeter Maydell * INT and CINT outputs are connected to the CPU. 327706e9442SPeter Maydell */ 328706e9442SPeter Maydell const int input_ints[] = { -1, 30, 10, 16 }; 329706e9442SPeter Maydell 330706e9442SPeter Maydell uic[i] = qdev_new(TYPE_PPC_UIC); 331706e9442SPeter Maydell sbd = SYS_BUS_DEVICE(uic[i]); 332706e9442SPeter Maydell 333706e9442SPeter Maydell qdev_prop_set_uint32(uic[i], "dcr-base", 0xc0 + i * 0x10); 334706e9442SPeter Maydell object_property_set_link(OBJECT(uic[i]), "cpu", OBJECT(cpu), 335706e9442SPeter Maydell &error_fatal); 336706e9442SPeter Maydell sysbus_realize_and_unref(sbd, &error_fatal); 337706e9442SPeter Maydell 338706e9442SPeter Maydell if (i == 0) { 339706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, 340706e9442SPeter Maydell ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]); 341706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, 342706e9442SPeter Maydell ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]); 343706e9442SPeter Maydell } else { 344706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, 345706e9442SPeter Maydell qdev_get_gpio_in(uic[0], input_ints[i])); 346706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, 347706e9442SPeter Maydell qdev_get_gpio_in(uic[0], input_ints[i] + 1)); 348706e9442SPeter Maydell } 349706e9442SPeter Maydell } 3504b387f9eSBALATON Zoltan 3514b387f9eSBALATON Zoltan /* SDRAM controller */ 3524b387f9eSBALATON Zoltan /* put all RAM on first bank because board has one slot 3534b387f9eSBALATON Zoltan * and firmware only checks that */ 354b28f0188SIgor Mammedov ppc4xx_sdram_banks(machine->ram, 1, ram_memories, ram_bases, ram_sizes, 3554b387f9eSBALATON Zoltan ppc460ex_sdram_bank_sizes); 3564b387f9eSBALATON Zoltan 3574b387f9eSBALATON Zoltan /* FIXME: does 460EX have ECC interrupts? */ 3584b387f9eSBALATON Zoltan ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories, 3594b387f9eSBALATON Zoltan ram_bases, ram_sizes, 1); 3604b387f9eSBALATON Zoltan 36108fd9917SBALATON Zoltan /* IIC controllers and devices */ 362706e9442SPeter Maydell dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, 363706e9442SPeter Maydell qdev_get_gpio_in(uic[0], 2)); 36408fd9917SBALATON Zoltan i2c = PPC4xx_I2C(dev)->bus; 36508fd9917SBALATON Zoltan /* SPD EEPROM on RAM module */ 366fc0cfc1dSMarkus Armbruster spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2, 367f26740c6SMarkus Armbruster ram_sizes[0]); 36808fd9917SBALATON Zoltan spd_data[20] = 4; /* SO-DIMM module */ 36908fd9917SBALATON Zoltan smbus_eeprom_init_one(i2c, 0x50, spd_data); 37008fd9917SBALATON Zoltan /* RTC */ 3711373b15bSPhilippe Mathieu-Daudé i2c_slave_create_simple(i2c, "m41t80", 0x68); 3724b387f9eSBALATON Zoltan 373706e9442SPeter Maydell dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, 374706e9442SPeter Maydell qdev_get_gpio_in(uic[0], 3)); 3754b387f9eSBALATON Zoltan 3764b387f9eSBALATON Zoltan /* External bus controller */ 3774b387f9eSBALATON Zoltan ppc405_ebc_init(env); 3784b387f9eSBALATON Zoltan 3794b387f9eSBALATON Zoltan /* CPR */ 3804b387f9eSBALATON Zoltan ppc4xx_cpr_init(env); 3814b387f9eSBALATON Zoltan 3824b387f9eSBALATON Zoltan /* PLB to AHB bridge */ 3834b387f9eSBALATON Zoltan ppc4xx_ahb_init(env); 3844b387f9eSBALATON Zoltan 3854b387f9eSBALATON Zoltan /* System DCRs */ 3864b387f9eSBALATON Zoltan ppc4xx_sdr_init(env); 3874b387f9eSBALATON Zoltan 3884b387f9eSBALATON Zoltan /* MAL */ 389706e9442SPeter Maydell for (i = 0; i < ARRAY_SIZE(mal_irqs); i++) { 390706e9442SPeter Maydell mal_irqs[0] = qdev_get_gpio_in(uic[2], 3 + i); 391706e9442SPeter Maydell } 392706e9442SPeter Maydell ppc4xx_mal_init(env, 4, 16, mal_irqs); 3934b387f9eSBALATON Zoltan 3943c409c19SBALATON Zoltan /* DMA */ 3953c409c19SBALATON Zoltan ppc4xx_dma_init(env, 0x200); 3963c409c19SBALATON Zoltan 3974b387f9eSBALATON Zoltan /* 256K of L2 cache as memory */ 3984b387f9eSBALATON Zoltan ppc4xx_l2sram_init(env); 3994b387f9eSBALATON Zoltan /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */ 400ab3dd749SPhilippe Mathieu-Daudé memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 * KiB, 4014b387f9eSBALATON Zoltan &error_abort); 4024b387f9eSBALATON Zoltan memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram); 4034b387f9eSBALATON Zoltan 4044b387f9eSBALATON Zoltan /* USB */ 405706e9442SPeter Maydell sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, 406706e9442SPeter Maydell qdev_get_gpio_in(uic[2], 29)); 4073e80f690SMarkus Armbruster dev = qdev_new("sysbus-ohci"); 4084b387f9eSBALATON Zoltan qdev_prop_set_string(dev, "masterbus", "usb-bus.0"); 4094b387f9eSBALATON Zoltan qdev_prop_set_uint32(dev, "num-ports", 6); 4104b387f9eSBALATON Zoltan sbdev = SYS_BUS_DEVICE(dev); 4113c6ef471SMarkus Armbruster sysbus_realize_and_unref(sbdev, &error_fatal); 4124b387f9eSBALATON Zoltan sysbus_mmio_map(sbdev, 0, 0x4bffd0000); 413706e9442SPeter Maydell sysbus_connect_irq(sbdev, 0, qdev_get_gpio_in(uic[2], 30)); 4144b387f9eSBALATON Zoltan usb_create_simple(usb_bus_find(-1), "usb-kbd"); 4154b387f9eSBALATON Zoltan usb_create_simple(usb_bus_find(-1), "usb-mouse"); 4164b387f9eSBALATON Zoltan 4174b387f9eSBALATON Zoltan /* PCI bus */ 4184b387f9eSBALATON Zoltan ppc460ex_pcie_init(env); 4196484ab3dSBALATON Zoltan /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ 420706e9442SPeter Maydell dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, 421706e9442SPeter Maydell qdev_get_gpio_in(uic[1], 0)); 422*f17969dbSBALATON Zoltan pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); 423*f17969dbSBALATON Zoltan 4244b387f9eSBALATON Zoltan memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 4254b387f9eSBALATON Zoltan 0, 0x10000); 4264b387f9eSBALATON Zoltan memory_region_add_subregion(get_system_memory(), 0xc08000000, isa); 4274b387f9eSBALATON Zoltan 4284b387f9eSBALATON Zoltan /* PCI devices */ 4294b387f9eSBALATON Zoltan pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501"); 4304b387f9eSBALATON Zoltan /* SoC has a single SATA port but we don't emulate that yet 4314b387f9eSBALATON Zoltan * However, firmware and usual clients have driver for SiI311x 4324b387f9eSBALATON Zoltan * so add one for convenience by default */ 4334b387f9eSBALATON Zoltan if (defaults_enabled()) { 4344b387f9eSBALATON Zoltan pci_create_simple(pci_bus, -1, "sii3112"); 4354b387f9eSBALATON Zoltan } 4364b387f9eSBALATON Zoltan 4374b387f9eSBALATON Zoltan /* SoC has 4 UARTs 4384b387f9eSBALATON Zoltan * but board has only one wired and two are present in fdt */ 4399bca0edbSPeter Maydell if (serial_hd(0) != NULL) { 440706e9442SPeter Maydell serial_mm_init(address_space_mem, 0x4ef600300, 0, 441706e9442SPeter Maydell qdev_get_gpio_in(uic[1], 1), 4429bca0edbSPeter Maydell PPC_SERIAL_MM_BAUDBASE, serial_hd(0), 4434b387f9eSBALATON Zoltan DEVICE_BIG_ENDIAN); 4444b387f9eSBALATON Zoltan } 4459bca0edbSPeter Maydell if (serial_hd(1) != NULL) { 446706e9442SPeter Maydell serial_mm_init(address_space_mem, 0x4ef600400, 0, 447706e9442SPeter Maydell qdev_get_gpio_in(uic[0], 1), 4489bca0edbSPeter Maydell PPC_SERIAL_MM_BAUDBASE, serial_hd(1), 4494b387f9eSBALATON Zoltan DEVICE_BIG_ENDIAN); 4504b387f9eSBALATON Zoltan } 4514b387f9eSBALATON Zoltan 4524b387f9eSBALATON Zoltan /* Load U-Boot image. */ 4534b387f9eSBALATON Zoltan if (!machine->kernel_filename) { 4544b387f9eSBALATON Zoltan success = sam460ex_load_uboot(); 4554b387f9eSBALATON Zoltan if (success < 0) { 456371b74e2SMao Zhongyi error_report("could not load firmware"); 4574b387f9eSBALATON Zoltan exit(1); 4584b387f9eSBALATON Zoltan } 4594b387f9eSBALATON Zoltan } 4604b387f9eSBALATON Zoltan 4614b387f9eSBALATON Zoltan /* Load kernel. */ 4624b387f9eSBALATON Zoltan if (machine->kernel_filename) { 463617160c9SBALATON Zoltan hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; 4644b387f9eSBALATON Zoltan success = load_uimage(machine->kernel_filename, &entry, &loadaddr, 4654b387f9eSBALATON Zoltan NULL, NULL, NULL); 4664b387f9eSBALATON Zoltan if (success < 0) { 467617160c9SBALATON Zoltan uint64_t elf_entry; 4684b387f9eSBALATON Zoltan 469617160c9SBALATON Zoltan success = load_elf(machine->kernel_filename, NULL, NULL, NULL, 470617160c9SBALATON Zoltan &elf_entry, NULL, NULL, NULL, 471617160c9SBALATON Zoltan 1, PPC_ELF_MACHINE, 0, 0); 4724b387f9eSBALATON Zoltan entry = elf_entry; 4734b387f9eSBALATON Zoltan } 4744b387f9eSBALATON Zoltan /* XXX try again as binary */ 4754b387f9eSBALATON Zoltan if (success < 0) { 476371b74e2SMao Zhongyi error_report("could not load kernel '%s'", 4774b387f9eSBALATON Zoltan machine->kernel_filename); 4784b387f9eSBALATON Zoltan exit(1); 4794b387f9eSBALATON Zoltan } 4804b387f9eSBALATON Zoltan } 4814b387f9eSBALATON Zoltan 4824b387f9eSBALATON Zoltan /* Load initrd. */ 4834b387f9eSBALATON Zoltan if (machine->initrd_filename) { 4844b387f9eSBALATON Zoltan initrd_size = load_image_targphys(machine->initrd_filename, 4854b387f9eSBALATON Zoltan RAMDISK_ADDR, 4864b387f9eSBALATON Zoltan machine->ram_size - RAMDISK_ADDR); 4874b387f9eSBALATON Zoltan if (initrd_size < 0) { 488371b74e2SMao Zhongyi error_report("could not load ram disk '%s' at %x", 4894b387f9eSBALATON Zoltan machine->initrd_filename, RAMDISK_ADDR); 4904b387f9eSBALATON Zoltan exit(1); 4914b387f9eSBALATON Zoltan } 4924b387f9eSBALATON Zoltan } 4934b387f9eSBALATON Zoltan 4944b387f9eSBALATON Zoltan /* If we're loading a kernel directly, we must load the device tree too. */ 4954b387f9eSBALATON Zoltan if (machine->kernel_filename) { 4964b387f9eSBALATON Zoltan int dt_size; 4974b387f9eSBALATON Zoltan 4984b387f9eSBALATON Zoltan dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size, 4994b387f9eSBALATON Zoltan RAMDISK_ADDR, initrd_size, 5004b387f9eSBALATON Zoltan machine->kernel_cmdline); 5014b387f9eSBALATON Zoltan 5024b387f9eSBALATON Zoltan boot_info->dt_base = FDT_ADDR; 5034b387f9eSBALATON Zoltan boot_info->dt_size = dt_size; 5044b387f9eSBALATON Zoltan } 5054b387f9eSBALATON Zoltan 5064b387f9eSBALATON Zoltan boot_info->entry = entry; 5074b387f9eSBALATON Zoltan } 5084b387f9eSBALATON Zoltan 5094b387f9eSBALATON Zoltan static void sam460ex_machine_init(MachineClass *mc) 5104b387f9eSBALATON Zoltan { 5114b387f9eSBALATON Zoltan mc->desc = "aCube Sam460ex"; 5124b387f9eSBALATON Zoltan mc->init = sam460ex_init; 5134b387f9eSBALATON Zoltan mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("460exb"); 514d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 515b28f0188SIgor Mammedov mc->default_ram_id = "ppc4xx.sdram"; 5164b387f9eSBALATON Zoltan } 5174b387f9eSBALATON Zoltan 5184b387f9eSBALATON Zoltan DEFINE_MACHINE("sam460ex", sam460ex_machine_init) 519