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" 162c65db5eSPaolo Bonzini #include "qemu/datadir.h" 174b387f9eSBALATON Zoltan #include "qemu/error-report.h" 184b387f9eSBALATON Zoltan #include "qapi/error.h" 194b387f9eSBALATON Zoltan #include "hw/boards.h" 204b387f9eSBALATON Zoltan #include "sysemu/kvm.h" 214b387f9eSBALATON Zoltan #include "kvm_ppc.h" 224b387f9eSBALATON Zoltan #include "sysemu/device_tree.h" 234b387f9eSBALATON Zoltan #include "sysemu/block-backend.h" 244b387f9eSBALATON Zoltan #include "hw/loader.h" 254b387f9eSBALATON Zoltan #include "elf.h" 264b387f9eSBALATON Zoltan #include "exec/memory.h" 2772a56a1fSMichael S. Tsirkin #include "ppc440.h" 2872a56a1fSMichael S. Tsirkin #include "ppc405.h" 294b387f9eSBALATON Zoltan #include "hw/block/flash.h" 304b387f9eSBALATON Zoltan #include "sysemu/sysemu.h" 3171e8a915SMarkus Armbruster #include "sysemu/reset.h" 324b387f9eSBALATON Zoltan #include "hw/sysbus.h" 334b387f9eSBALATON Zoltan #include "hw/char/serial.h" 344b387f9eSBALATON Zoltan #include "hw/i2c/ppc4xx_i2c.h" 3593198b6cSCorey Minyard #include "hw/i2c/smbus_eeprom.h" 364b387f9eSBALATON Zoltan #include "hw/usb/hcd-ehci.h" 37ad633de6SDavid Gibson #include "hw/ppc/fdt.h" 38a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 39706e9442SPeter Maydell #include "hw/intc/ppc-uic.h" 404b387f9eSBALATON Zoltan 4143f7868dSGuenter Roeck #include <libfdt.h> 4243f7868dSGuenter Roeck 434b387f9eSBALATON Zoltan #define BINARY_DEVICE_TREE_FILE "canyonlands.dtb" 444b387f9eSBALATON Zoltan #define UBOOT_FILENAME "u-boot-sam460-20100605.bin" 454b387f9eSBALATON Zoltan /* to extract the official U-Boot bin from the updater: */ 464b387f9eSBALATON Zoltan /* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \ 474b387f9eSBALATON Zoltan if=updater/updater-460 of=u-boot-sam460-20100605.bin */ 484b387f9eSBALATON Zoltan 494b387f9eSBALATON Zoltan /* from Sam460 U-Boot include/configs/Sam460ex.h */ 504b387f9eSBALATON Zoltan #define FLASH_BASE 0xfff00000 514b387f9eSBALATON Zoltan #define FLASH_BASE_H 0x4 52ab3dd749SPhilippe Mathieu-Daudé #define FLASH_SIZE (1 * MiB) 534b387f9eSBALATON Zoltan #define UBOOT_LOAD_BASE 0xfff80000 544b387f9eSBALATON Zoltan #define UBOOT_SIZE 0x00080000 554b387f9eSBALATON Zoltan #define UBOOT_ENTRY 0xfffffffc 564b387f9eSBALATON Zoltan 574b387f9eSBALATON Zoltan /* from U-Boot */ 584b387f9eSBALATON Zoltan #define EPAPR_MAGIC (0x45504150) 594b387f9eSBALATON Zoltan #define KERNEL_ADDR 0x1000000 604b387f9eSBALATON Zoltan #define FDT_ADDR 0x1800000 614b387f9eSBALATON Zoltan #define RAMDISK_ADDR 0x1900000 624b387f9eSBALATON Zoltan 634b387f9eSBALATON Zoltan /* Sam460ex IRQ MAP: 644b387f9eSBALATON Zoltan IRQ0 = ETH_INT 654b387f9eSBALATON Zoltan IRQ1 = FPGA_INT 664b387f9eSBALATON Zoltan IRQ2 = PCI_INT (PCIA, PCIB, PCIC, PCIB) 674b387f9eSBALATON Zoltan IRQ3 = FPGA_INT2 684b387f9eSBALATON Zoltan IRQ11 = RTC_INT 694b387f9eSBALATON Zoltan IRQ12 = SM502_INT 704b387f9eSBALATON Zoltan */ 714b387f9eSBALATON Zoltan 72f8815532SBALATON Zoltan #define CPU_FREQ 1150000000 7343f7868dSGuenter Roeck #define PLB_FREQ 230000000 7443f7868dSGuenter Roeck #define OPB_FREQ 115000000 7543f7868dSGuenter Roeck #define EBC_FREQ 115000000 7643f7868dSGuenter Roeck #define UART_FREQ 11059200 774b387f9eSBALATON Zoltan #define SDRAM_NR_BANKS 4 784b387f9eSBALATON Zoltan 796a9938a3SBALATON Zoltan /* The SoC could also handle 4 GiB but firmware does not work with that. */ 806a9938a3SBALATON Zoltan /* Maybe it overflows a signed 32 bit number somewhere? */ 817d8ccf58SBALATON Zoltan static const ram_addr_t ppc460ex_sdram_bank_sizes[] = { 826a9938a3SBALATON Zoltan 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB, 836a9938a3SBALATON Zoltan 32 * MiB, 0 844b387f9eSBALATON Zoltan }; 854b387f9eSBALATON Zoltan 864b387f9eSBALATON Zoltan struct boot_info { 874b387f9eSBALATON Zoltan uint32_t dt_base; 884b387f9eSBALATON Zoltan uint32_t dt_size; 894b387f9eSBALATON Zoltan uint32_t entry; 904b387f9eSBALATON Zoltan }; 914b387f9eSBALATON Zoltan 924b387f9eSBALATON Zoltan static int sam460ex_load_uboot(void) 934b387f9eSBALATON Zoltan { 94f30bc995SMarkus Armbruster /* 95f30bc995SMarkus Armbruster * This first creates 1MiB of flash memory mapped at the end of 96f30bc995SMarkus Armbruster * the 32-bit address space (0xFFF00000..0xFFFFFFFF). 97f30bc995SMarkus Armbruster * 98f30bc995SMarkus Armbruster * If_PFLASH unit 0 is defined, the flash memory is initialized 99f30bc995SMarkus Armbruster * from that block backend. 100f30bc995SMarkus Armbruster * 101f30bc995SMarkus Armbruster * Else, it's initialized to zero. And then 512KiB of ROM get 102f30bc995SMarkus Armbruster * mapped on top of its second half (0xFFF80000..0xFFFFFFFF), 103f30bc995SMarkus Armbruster * initialized from u-boot-sam460-20100605.bin. 104f30bc995SMarkus Armbruster * 105f30bc995SMarkus Armbruster * This doesn't smell right. 106f30bc995SMarkus Armbruster * 107f30bc995SMarkus Armbruster * The physical hardware appears to have 512KiB flash memory. 108f30bc995SMarkus Armbruster * 109f30bc995SMarkus Armbruster * TODO Figure out what we really need here, and clean this up. 110f30bc995SMarkus Armbruster */ 111f30bc995SMarkus Armbruster 1124b387f9eSBALATON Zoltan DriveInfo *dinfo; 1134b387f9eSBALATON Zoltan 1144b387f9eSBALATON Zoltan dinfo = drive_get(IF_PFLASH, 0, 0); 115f30bc995SMarkus Armbruster if (!pflash_cfi01_register(FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32), 116940d5b13SMarkus Armbruster "sam460ex.flash", FLASH_SIZE, 117f30bc995SMarkus Armbruster dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, 118ce14710fSMarkus Armbruster 64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1)) { 119371b74e2SMao Zhongyi error_report("Error registering flash memory"); 1204b387f9eSBALATON Zoltan /* XXX: return an error instead? */ 1214b387f9eSBALATON Zoltan exit(1); 1224b387f9eSBALATON Zoltan } 1234b387f9eSBALATON Zoltan 124f30bc995SMarkus Armbruster if (!dinfo) { 1254b387f9eSBALATON Zoltan /*error_report("No flash image given with the 'pflash' parameter," 1264b387f9eSBALATON Zoltan " using default u-boot image");*/ 127f30bc995SMarkus Armbruster rom_add_file_fixed(UBOOT_FILENAME, 128f30bc995SMarkus Armbruster UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32), 129f30bc995SMarkus Armbruster -1); 1304b387f9eSBALATON Zoltan } 1314b387f9eSBALATON Zoltan 1324b387f9eSBALATON Zoltan return 0; 1334b387f9eSBALATON Zoltan } 1344b387f9eSBALATON Zoltan 1354b387f9eSBALATON Zoltan static int sam460ex_load_device_tree(hwaddr addr, 1364b387f9eSBALATON Zoltan uint32_t ramsize, 1374b387f9eSBALATON Zoltan hwaddr initrd_base, 1384b387f9eSBALATON Zoltan hwaddr initrd_size, 1394b387f9eSBALATON Zoltan const char *kernel_cmdline) 1404b387f9eSBALATON Zoltan { 1414b387f9eSBALATON Zoltan uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) }; 1424b387f9eSBALATON Zoltan char *filename; 1434b387f9eSBALATON Zoltan int fdt_size; 1444b387f9eSBALATON Zoltan void *fdt; 145f8815532SBALATON Zoltan uint32_t tb_freq = CPU_FREQ; 146f8815532SBALATON Zoltan uint32_t clock_freq = CPU_FREQ; 14743f7868dSGuenter Roeck int offset; 1484b387f9eSBALATON Zoltan 1494b387f9eSBALATON Zoltan filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); 1504b387f9eSBALATON Zoltan if (!filename) { 15151b0d834SDavid Gibson error_report("Couldn't find dtb file `%s'", BINARY_DEVICE_TREE_FILE); 15251b0d834SDavid Gibson exit(1); 1534b387f9eSBALATON Zoltan } 1544b387f9eSBALATON Zoltan fdt = load_device_tree(filename, &fdt_size); 15551b0d834SDavid Gibson if (!fdt) { 15651b0d834SDavid Gibson error_report("Couldn't load dtb file `%s'", filename); 1573cc702d6SBALATON Zoltan g_free(filename); 15851b0d834SDavid Gibson exit(1); 1594b387f9eSBALATON Zoltan } 1603cc702d6SBALATON Zoltan g_free(filename); 1614b387f9eSBALATON Zoltan 1624b387f9eSBALATON Zoltan /* Manipulate device tree in memory. */ 1634b387f9eSBALATON Zoltan 164e753f331SDavid Gibson qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, 1654b387f9eSBALATON Zoltan sizeof(mem_reg_property)); 1664b387f9eSBALATON Zoltan 1674b387f9eSBALATON Zoltan /* default FDT doesn't have a /chosen node... */ 1684b387f9eSBALATON Zoltan qemu_fdt_add_subnode(fdt, "/chosen"); 1694b387f9eSBALATON Zoltan 170e753f331SDavid Gibson qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd_base); 1714b387f9eSBALATON Zoltan 172e753f331SDavid Gibson qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", 1734b387f9eSBALATON Zoltan (initrd_base + initrd_size)); 1744b387f9eSBALATON Zoltan 175e753f331SDavid Gibson qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); 1764b387f9eSBALATON Zoltan 1774b387f9eSBALATON Zoltan /* Copy data from the host device tree into the guest. Since the guest can 1784b387f9eSBALATON Zoltan * directly access the timebase without host involvement, we must expose 1794b387f9eSBALATON Zoltan * the correct frequencies. */ 1804b387f9eSBALATON Zoltan if (kvm_enabled()) { 1814b387f9eSBALATON Zoltan tb_freq = kvmppc_get_tbfreq(); 1824b387f9eSBALATON Zoltan clock_freq = kvmppc_get_clockfreq(); 1834b387f9eSBALATON Zoltan } 1844b387f9eSBALATON Zoltan 1854b387f9eSBALATON Zoltan qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency", 1864b387f9eSBALATON Zoltan clock_freq); 1874b387f9eSBALATON Zoltan qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency", 1884b387f9eSBALATON Zoltan tb_freq); 1894b387f9eSBALATON Zoltan 19043f7868dSGuenter Roeck /* Remove cpm node if it exists (it is not emulated) */ 19143f7868dSGuenter Roeck offset = fdt_path_offset(fdt, "/cpm"); 19243f7868dSGuenter Roeck if (offset >= 0) { 193ad633de6SDavid Gibson _FDT(fdt_nop_node(fdt, offset)); 19443f7868dSGuenter Roeck } 19543f7868dSGuenter Roeck 19643f7868dSGuenter Roeck /* set serial port clocks */ 19743f7868dSGuenter Roeck offset = fdt_node_offset_by_compatible(fdt, -1, "ns16550"); 19843f7868dSGuenter Roeck while (offset >= 0) { 199ad633de6SDavid Gibson _FDT(fdt_setprop_cell(fdt, offset, "clock-frequency", UART_FREQ)); 20043f7868dSGuenter Roeck offset = fdt_node_offset_by_compatible(fdt, offset, "ns16550"); 20143f7868dSGuenter Roeck } 20243f7868dSGuenter Roeck 20343f7868dSGuenter Roeck /* some more clocks */ 20443f7868dSGuenter Roeck qemu_fdt_setprop_cell(fdt, "/plb", "clock-frequency", 20543f7868dSGuenter Roeck PLB_FREQ); 20643f7868dSGuenter Roeck qemu_fdt_setprop_cell(fdt, "/plb/opb", "clock-frequency", 20743f7868dSGuenter Roeck OPB_FREQ); 20843f7868dSGuenter Roeck qemu_fdt_setprop_cell(fdt, "/plb/opb/ebc", "clock-frequency", 20943f7868dSGuenter Roeck EBC_FREQ); 21043f7868dSGuenter Roeck 2114b387f9eSBALATON Zoltan rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); 2124b387f9eSBALATON Zoltan g_free(fdt); 2134b387f9eSBALATON Zoltan 21451b0d834SDavid Gibson return fdt_size; 2154b387f9eSBALATON Zoltan } 2164b387f9eSBALATON Zoltan 2174b387f9eSBALATON Zoltan /* Create reset TLB entries for BookE, mapping only the flash memory. */ 2184b387f9eSBALATON Zoltan static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env) 2194b387f9eSBALATON Zoltan { 2204b387f9eSBALATON Zoltan ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; 2214b387f9eSBALATON Zoltan 2224b387f9eSBALATON Zoltan /* on reset the flash is mapped by a shadow TLB, 2234b387f9eSBALATON Zoltan * but since we don't implement them we need to use 2244b387f9eSBALATON Zoltan * the same values U-Boot will use to avoid a fault. 2254b387f9eSBALATON Zoltan */ 2264b387f9eSBALATON Zoltan tlb->attr = 0; 2274b387f9eSBALATON Zoltan tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); 2284b387f9eSBALATON Zoltan tlb->size = 0x10000000; /* up to 0xffffffff */ 2294b387f9eSBALATON Zoltan tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK; 2304b387f9eSBALATON Zoltan tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4; 2314b387f9eSBALATON Zoltan tlb->PID = 0; 2324b387f9eSBALATON Zoltan } 2334b387f9eSBALATON Zoltan 2344b387f9eSBALATON Zoltan /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ 2354b387f9eSBALATON Zoltan static void mmubooke_create_initial_mapping(CPUPPCState *env, 2364b387f9eSBALATON Zoltan target_ulong va, 2374b387f9eSBALATON Zoltan hwaddr pa) 2384b387f9eSBALATON Zoltan { 2394b387f9eSBALATON Zoltan ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; 2404b387f9eSBALATON Zoltan 2414b387f9eSBALATON Zoltan tlb->attr = 0; 2424b387f9eSBALATON Zoltan tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); 2434b387f9eSBALATON Zoltan tlb->size = 1 << 31; /* up to 0x80000000 */ 2444b387f9eSBALATON Zoltan tlb->EPN = va & TARGET_PAGE_MASK; 2454b387f9eSBALATON Zoltan tlb->RPN = pa & TARGET_PAGE_MASK; 2464b387f9eSBALATON Zoltan tlb->PID = 0; 2474b387f9eSBALATON Zoltan } 2484b387f9eSBALATON Zoltan 2494b387f9eSBALATON Zoltan static void main_cpu_reset(void *opaque) 2504b387f9eSBALATON Zoltan { 2514b387f9eSBALATON Zoltan PowerPCCPU *cpu = opaque; 2524b387f9eSBALATON Zoltan CPUPPCState *env = &cpu->env; 2534b387f9eSBALATON Zoltan struct boot_info *bi = env->load_info; 2544b387f9eSBALATON Zoltan 2554b387f9eSBALATON Zoltan cpu_reset(CPU(cpu)); 2564b387f9eSBALATON Zoltan 2574b387f9eSBALATON Zoltan /* either we have a kernel to boot or we jump to U-Boot */ 2584b387f9eSBALATON Zoltan if (bi->entry != UBOOT_ENTRY) { 259ab3dd749SPhilippe Mathieu-Daudé env->gpr[1] = (16 * MiB) - 8; 2604b387f9eSBALATON Zoltan env->gpr[3] = FDT_ADDR; 2614b387f9eSBALATON Zoltan env->nip = bi->entry; 2624b387f9eSBALATON Zoltan 2634b387f9eSBALATON Zoltan /* Create a mapping for the kernel. */ 2644b387f9eSBALATON Zoltan mmubooke_create_initial_mapping(env, 0, 0); 2654b387f9eSBALATON Zoltan env->gpr[6] = tswap32(EPAPR_MAGIC); 266ab3dd749SPhilippe Mathieu-Daudé env->gpr[7] = (16 * MiB) - 8; /* bi->ima_size; */ 2674b387f9eSBALATON Zoltan 2684b387f9eSBALATON Zoltan } else { 2694b387f9eSBALATON Zoltan env->nip = UBOOT_ENTRY; 2704b387f9eSBALATON Zoltan mmubooke_create_initial_mapping_uboot(env); 2714b387f9eSBALATON Zoltan } 2724b387f9eSBALATON Zoltan } 2734b387f9eSBALATON Zoltan 2744b387f9eSBALATON Zoltan static void sam460ex_init(MachineState *machine) 2754b387f9eSBALATON Zoltan { 2764b387f9eSBALATON Zoltan MemoryRegion *address_space_mem = get_system_memory(); 2774b387f9eSBALATON Zoltan MemoryRegion *isa = g_new(MemoryRegion, 1); 2784b387f9eSBALATON Zoltan MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS); 27908fd9917SBALATON Zoltan hwaddr ram_bases[SDRAM_NR_BANKS] = {0}; 28008fd9917SBALATON Zoltan hwaddr ram_sizes[SDRAM_NR_BANKS] = {0}; 2814b387f9eSBALATON Zoltan MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); 282706e9442SPeter Maydell DeviceState *uic[4]; 283706e9442SPeter Maydell qemu_irq mal_irqs[4]; 284706e9442SPeter Maydell int i; 2854b387f9eSBALATON Zoltan PCIBus *pci_bus; 2864b387f9eSBALATON Zoltan PowerPCCPU *cpu; 2874b387f9eSBALATON Zoltan CPUPPCState *env; 28808fd9917SBALATON Zoltan I2CBus *i2c; 2894b387f9eSBALATON Zoltan hwaddr entry = UBOOT_ENTRY; 2904b387f9eSBALATON Zoltan target_long initrd_size = 0; 2914b387f9eSBALATON Zoltan DeviceState *dev; 2924b387f9eSBALATON Zoltan SysBusDevice *sbdev; 2934b387f9eSBALATON Zoltan struct boot_info *boot_info; 29408fd9917SBALATON Zoltan uint8_t *spd_data; 29508fd9917SBALATON Zoltan int success; 2964b387f9eSBALATON Zoltan 2974b387f9eSBALATON Zoltan cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); 2984b387f9eSBALATON Zoltan env = &cpu->env; 2994b387f9eSBALATON Zoltan if (env->mmu_model != POWERPC_MMU_BOOKE) { 3004b387f9eSBALATON Zoltan error_report("Only MMU model BookE is supported by this machine."); 3014b387f9eSBALATON Zoltan exit(1); 3024b387f9eSBALATON Zoltan } 3034b387f9eSBALATON Zoltan 3044b387f9eSBALATON Zoltan qemu_register_reset(main_cpu_reset, cpu); 3054b387f9eSBALATON Zoltan boot_info = g_malloc0(sizeof(*boot_info)); 3064b387f9eSBALATON Zoltan env->load_info = boot_info; 3074b387f9eSBALATON Zoltan 308f8815532SBALATON Zoltan ppc_booke_timers_init(cpu, CPU_FREQ, 0); 3094b387f9eSBALATON Zoltan ppc_dcr_init(env, NULL, NULL); 3104b387f9eSBALATON Zoltan 3114b387f9eSBALATON Zoltan /* PLB arbitrer */ 312*695bce07SCédric Le Goater dev = qdev_new(TYPE_PPC405_PLB); 313*695bce07SCédric Le Goater ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); 314*695bce07SCédric Le Goater object_unref(OBJECT(dev)); 3154b387f9eSBALATON Zoltan 3164b387f9eSBALATON Zoltan /* interrupt controllers */ 317706e9442SPeter Maydell for (i = 0; i < ARRAY_SIZE(uic); i++) { 318706e9442SPeter Maydell SysBusDevice *sbd; 319706e9442SPeter Maydell /* 320706e9442SPeter Maydell * UICs 1, 2 and 3 are cascaded through UIC 0. 321706e9442SPeter Maydell * input_ints[n] is the interrupt number on UIC 0 which 322706e9442SPeter Maydell * the INT output of UIC n is connected to. The CINT output 323706e9442SPeter Maydell * of UIC n connects to input_ints[n] + 1. 324706e9442SPeter Maydell * The entry in input_ints[] for UIC 0 is ignored, because UIC 0's 325706e9442SPeter Maydell * INT and CINT outputs are connected to the CPU. 326706e9442SPeter Maydell */ 327706e9442SPeter Maydell const int input_ints[] = { -1, 30, 10, 16 }; 328706e9442SPeter Maydell 329706e9442SPeter Maydell uic[i] = qdev_new(TYPE_PPC_UIC); 330706e9442SPeter Maydell sbd = SYS_BUS_DEVICE(uic[i]); 331706e9442SPeter Maydell 332706e9442SPeter Maydell qdev_prop_set_uint32(uic[i], "dcr-base", 0xc0 + i * 0x10); 333706e9442SPeter Maydell object_property_set_link(OBJECT(uic[i]), "cpu", OBJECT(cpu), 334706e9442SPeter Maydell &error_fatal); 335706e9442SPeter Maydell sysbus_realize_and_unref(sbd, &error_fatal); 336706e9442SPeter Maydell 337706e9442SPeter Maydell if (i == 0) { 338706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, 33947b60fc6SCédric Le Goater qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); 340706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, 34147b60fc6SCédric Le Goater qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT)); 342706e9442SPeter Maydell } else { 343706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, 344706e9442SPeter Maydell qdev_get_gpio_in(uic[0], input_ints[i])); 345706e9442SPeter Maydell sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, 346706e9442SPeter Maydell qdev_get_gpio_in(uic[0], input_ints[i] + 1)); 347706e9442SPeter Maydell } 348706e9442SPeter Maydell } 3494b387f9eSBALATON Zoltan 3504b387f9eSBALATON Zoltan /* SDRAM controller */ 3514b387f9eSBALATON Zoltan /* put all RAM on first bank because board has one slot 3524b387f9eSBALATON Zoltan * and firmware only checks that */ 353b28f0188SIgor Mammedov ppc4xx_sdram_banks(machine->ram, 1, ram_memories, ram_bases, ram_sizes, 3544b387f9eSBALATON Zoltan ppc460ex_sdram_bank_sizes); 3554b387f9eSBALATON Zoltan 3564b387f9eSBALATON Zoltan /* FIXME: does 460EX have ECC interrupts? */ 3574b387f9eSBALATON Zoltan ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories, 3584b387f9eSBALATON Zoltan ram_bases, ram_sizes, 1); 3594b387f9eSBALATON Zoltan 36008fd9917SBALATON Zoltan /* IIC controllers and devices */ 361706e9442SPeter Maydell dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, 362706e9442SPeter Maydell qdev_get_gpio_in(uic[0], 2)); 36308fd9917SBALATON Zoltan i2c = PPC4xx_I2C(dev)->bus; 36408fd9917SBALATON Zoltan /* SPD EEPROM on RAM module */ 365fc0cfc1dSMarkus Armbruster spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2, 366f26740c6SMarkus Armbruster ram_sizes[0]); 36708fd9917SBALATON Zoltan spd_data[20] = 4; /* SO-DIMM module */ 36808fd9917SBALATON Zoltan smbus_eeprom_init_one(i2c, 0x50, spd_data); 36908fd9917SBALATON Zoltan /* RTC */ 3701373b15bSPhilippe Mathieu-Daudé i2c_slave_create_simple(i2c, "m41t80", 0x68); 3714b387f9eSBALATON Zoltan 372706e9442SPeter Maydell dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, 373706e9442SPeter Maydell qdev_get_gpio_in(uic[0], 3)); 3744b387f9eSBALATON Zoltan 3754b387f9eSBALATON Zoltan /* External bus controller */ 376415a6333SCédric Le Goater dev = qdev_new(TYPE_PPC405_EBC); 377415a6333SCédric Le Goater ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); 378415a6333SCédric Le Goater object_unref(OBJECT(dev)); 3794b387f9eSBALATON Zoltan 3804b387f9eSBALATON Zoltan /* CPR */ 3814b387f9eSBALATON Zoltan ppc4xx_cpr_init(env); 3824b387f9eSBALATON Zoltan 3834b387f9eSBALATON Zoltan /* PLB to AHB bridge */ 3844b387f9eSBALATON Zoltan ppc4xx_ahb_init(env); 3854b387f9eSBALATON Zoltan 3864b387f9eSBALATON Zoltan /* System DCRs */ 3874b387f9eSBALATON Zoltan ppc4xx_sdr_init(env); 3884b387f9eSBALATON Zoltan 3894b387f9eSBALATON Zoltan /* MAL */ 390706e9442SPeter Maydell for (i = 0; i < ARRAY_SIZE(mal_irqs); i++) { 391ed021dafSDaniel Henrique Barboza mal_irqs[i] = qdev_get_gpio_in(uic[2], 3 + i); 392706e9442SPeter Maydell } 393706e9442SPeter Maydell ppc4xx_mal_init(env, 4, 16, mal_irqs); 3944b387f9eSBALATON Zoltan 3953c409c19SBALATON Zoltan /* DMA */ 3963c409c19SBALATON Zoltan ppc4xx_dma_init(env, 0x200); 3973c409c19SBALATON Zoltan 3984b387f9eSBALATON Zoltan /* 256K of L2 cache as memory */ 3994b387f9eSBALATON Zoltan ppc4xx_l2sram_init(env); 4004b387f9eSBALATON Zoltan /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */ 401ab3dd749SPhilippe Mathieu-Daudé memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 * KiB, 4024b387f9eSBALATON Zoltan &error_abort); 4034b387f9eSBALATON Zoltan memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram); 4044b387f9eSBALATON Zoltan 4054b387f9eSBALATON Zoltan /* USB */ 406706e9442SPeter Maydell sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, 407706e9442SPeter Maydell qdev_get_gpio_in(uic[2], 29)); 4083e80f690SMarkus Armbruster dev = qdev_new("sysbus-ohci"); 4094b387f9eSBALATON Zoltan qdev_prop_set_string(dev, "masterbus", "usb-bus.0"); 4104b387f9eSBALATON Zoltan qdev_prop_set_uint32(dev, "num-ports", 6); 4114b387f9eSBALATON Zoltan sbdev = SYS_BUS_DEVICE(dev); 4123c6ef471SMarkus Armbruster sysbus_realize_and_unref(sbdev, &error_fatal); 4134b387f9eSBALATON Zoltan sysbus_mmio_map(sbdev, 0, 0x4bffd0000); 414706e9442SPeter Maydell sysbus_connect_irq(sbdev, 0, qdev_get_gpio_in(uic[2], 30)); 4154b387f9eSBALATON Zoltan usb_create_simple(usb_bus_find(-1), "usb-kbd"); 4164b387f9eSBALATON Zoltan usb_create_simple(usb_bus_find(-1), "usb-mouse"); 4174b387f9eSBALATON Zoltan 4184b387f9eSBALATON Zoltan /* PCI bus */ 4194b387f9eSBALATON Zoltan ppc460ex_pcie_init(env); 4206484ab3dSBALATON Zoltan /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ 421706e9442SPeter Maydell dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, 422706e9442SPeter Maydell qdev_get_gpio_in(uic[1], 0)); 423f17969dbSBALATON Zoltan pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); 424f17969dbSBALATON Zoltan 4254b387f9eSBALATON Zoltan memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 4264b387f9eSBALATON Zoltan 0, 0x10000); 4274b387f9eSBALATON Zoltan memory_region_add_subregion(get_system_memory(), 0xc08000000, isa); 4284b387f9eSBALATON Zoltan 4294b387f9eSBALATON Zoltan /* PCI devices */ 4304b387f9eSBALATON Zoltan pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501"); 4314b387f9eSBALATON Zoltan /* SoC has a single SATA port but we don't emulate that yet 4324b387f9eSBALATON Zoltan * However, firmware and usual clients have driver for SiI311x 4334b387f9eSBALATON Zoltan * so add one for convenience by default */ 4344b387f9eSBALATON Zoltan if (defaults_enabled()) { 4354b387f9eSBALATON Zoltan pci_create_simple(pci_bus, -1, "sii3112"); 4364b387f9eSBALATON Zoltan } 4374b387f9eSBALATON Zoltan 4384b387f9eSBALATON Zoltan /* SoC has 4 UARTs 4394b387f9eSBALATON Zoltan * but board has only one wired and two are present in fdt */ 4409bca0edbSPeter Maydell if (serial_hd(0) != NULL) { 441706e9442SPeter Maydell serial_mm_init(address_space_mem, 0x4ef600300, 0, 442706e9442SPeter Maydell qdev_get_gpio_in(uic[1], 1), 4439bca0edbSPeter Maydell PPC_SERIAL_MM_BAUDBASE, serial_hd(0), 4444b387f9eSBALATON Zoltan DEVICE_BIG_ENDIAN); 4454b387f9eSBALATON Zoltan } 4469bca0edbSPeter Maydell if (serial_hd(1) != NULL) { 447706e9442SPeter Maydell serial_mm_init(address_space_mem, 0x4ef600400, 0, 448706e9442SPeter Maydell qdev_get_gpio_in(uic[0], 1), 4499bca0edbSPeter Maydell PPC_SERIAL_MM_BAUDBASE, serial_hd(1), 4504b387f9eSBALATON Zoltan DEVICE_BIG_ENDIAN); 4514b387f9eSBALATON Zoltan } 4524b387f9eSBALATON Zoltan 4534b387f9eSBALATON Zoltan /* Load U-Boot image. */ 4544b387f9eSBALATON Zoltan if (!machine->kernel_filename) { 4554b387f9eSBALATON Zoltan success = sam460ex_load_uboot(); 4564b387f9eSBALATON Zoltan if (success < 0) { 457371b74e2SMao Zhongyi error_report("could not load firmware"); 4584b387f9eSBALATON Zoltan exit(1); 4594b387f9eSBALATON Zoltan } 4604b387f9eSBALATON Zoltan } 4614b387f9eSBALATON Zoltan 4624b387f9eSBALATON Zoltan /* Load kernel. */ 4634b387f9eSBALATON Zoltan if (machine->kernel_filename) { 464617160c9SBALATON Zoltan hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; 4654b387f9eSBALATON Zoltan success = load_uimage(machine->kernel_filename, &entry, &loadaddr, 4664b387f9eSBALATON Zoltan NULL, NULL, NULL); 4674b387f9eSBALATON Zoltan if (success < 0) { 468617160c9SBALATON Zoltan uint64_t elf_entry; 4694b387f9eSBALATON Zoltan 470617160c9SBALATON Zoltan success = load_elf(machine->kernel_filename, NULL, NULL, NULL, 471617160c9SBALATON Zoltan &elf_entry, NULL, NULL, NULL, 472617160c9SBALATON Zoltan 1, PPC_ELF_MACHINE, 0, 0); 4734b387f9eSBALATON Zoltan entry = elf_entry; 4744b387f9eSBALATON Zoltan } 4754b387f9eSBALATON Zoltan /* XXX try again as binary */ 4764b387f9eSBALATON Zoltan if (success < 0) { 477371b74e2SMao Zhongyi error_report("could not load kernel '%s'", 4784b387f9eSBALATON Zoltan machine->kernel_filename); 4794b387f9eSBALATON Zoltan exit(1); 4804b387f9eSBALATON Zoltan } 4814b387f9eSBALATON Zoltan } 4824b387f9eSBALATON Zoltan 4834b387f9eSBALATON Zoltan /* Load initrd. */ 4844b387f9eSBALATON Zoltan if (machine->initrd_filename) { 4854b387f9eSBALATON Zoltan initrd_size = load_image_targphys(machine->initrd_filename, 4864b387f9eSBALATON Zoltan RAMDISK_ADDR, 4874b387f9eSBALATON Zoltan machine->ram_size - RAMDISK_ADDR); 4884b387f9eSBALATON Zoltan if (initrd_size < 0) { 489371b74e2SMao Zhongyi error_report("could not load ram disk '%s' at %x", 4904b387f9eSBALATON Zoltan machine->initrd_filename, RAMDISK_ADDR); 4914b387f9eSBALATON Zoltan exit(1); 4924b387f9eSBALATON Zoltan } 4934b387f9eSBALATON Zoltan } 4944b387f9eSBALATON Zoltan 4954b387f9eSBALATON Zoltan /* If we're loading a kernel directly, we must load the device tree too. */ 4964b387f9eSBALATON Zoltan if (machine->kernel_filename) { 4974b387f9eSBALATON Zoltan int dt_size; 4984b387f9eSBALATON Zoltan 4994b387f9eSBALATON Zoltan dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size, 5004b387f9eSBALATON Zoltan RAMDISK_ADDR, initrd_size, 5014b387f9eSBALATON Zoltan machine->kernel_cmdline); 5024b387f9eSBALATON Zoltan 5034b387f9eSBALATON Zoltan boot_info->dt_base = FDT_ADDR; 5044b387f9eSBALATON Zoltan boot_info->dt_size = dt_size; 5054b387f9eSBALATON Zoltan } 5064b387f9eSBALATON Zoltan 5074b387f9eSBALATON Zoltan boot_info->entry = entry; 5084b387f9eSBALATON Zoltan } 5094b387f9eSBALATON Zoltan 5104b387f9eSBALATON Zoltan static void sam460ex_machine_init(MachineClass *mc) 5114b387f9eSBALATON Zoltan { 5124b387f9eSBALATON Zoltan mc->desc = "aCube Sam460ex"; 5134b387f9eSBALATON Zoltan mc->init = sam460ex_init; 5144b387f9eSBALATON Zoltan mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("460exb"); 515d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 512 * MiB; 516b28f0188SIgor Mammedov mc->default_ram_id = "ppc4xx.sdram"; 5174b387f9eSBALATON Zoltan } 5184b387f9eSBALATON Zoltan 5194b387f9eSBALATON Zoltan DEFINE_MACHINE("sam460ex", sam460ex_machine_init) 520