11db09b84Saurel32 /* 2b3305981SScott Wood * QEMU PowerPC e500-based platforms 31db09b84Saurel32 * 41db09b84Saurel32 * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved. 51db09b84Saurel32 * 61db09b84Saurel32 * Author: Yu Liu, <yu.liu@freescale.com> 71db09b84Saurel32 * 81db09b84Saurel32 * This file is derived from hw/ppc440_bamboo.c, 91db09b84Saurel32 * the copyright for that material belongs to the original owners. 101db09b84Saurel32 * 111db09b84Saurel32 * This is free software; you can redistribute it and/or modify 121db09b84Saurel32 * it under the terms of the GNU General Public License as published by 131db09b84Saurel32 * the Free Software Foundation; either version 2 of the License, or 141db09b84Saurel32 * (at your option) any later version. 151db09b84Saurel32 */ 161db09b84Saurel32 171db09b84Saurel32 #include "config.h" 181db09b84Saurel32 #include "qemu-common.h" 19e6eaabebSScott Wood #include "e500.h" 203eddc1beSBharat Bhushan #include "e500-ccsr.h" 211422e32dSPaolo Bonzini #include "net/net.h" 22*1de7afc9SPaolo Bonzini #include "qemu/config-file.h" 234a18e7c9SScott Wood #include "hw/hw.h" 24488cb996SGerd Hoffmann #include "hw/serial.h" 25a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h" 264a18e7c9SScott Wood #include "hw/boards.h" 271db09b84Saurel32 #include "sysemu.h" 281db09b84Saurel32 #include "kvm.h" 291db09b84Saurel32 #include "kvm_ppc.h" 301db09b84Saurel32 #include "device_tree.h" 314a18e7c9SScott Wood #include "hw/openpic.h" 324a18e7c9SScott Wood #include "hw/ppc.h" 334a18e7c9SScott Wood #include "hw/loader.h" 34ca20cf32SBlue Swirl #include "elf.h" 354a18e7c9SScott Wood #include "hw/sysbus.h" 36022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 37*1de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 389e2c1298SAlexander Graf #include "hw/ppce500_pci.h" 391db09b84Saurel32 401db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" 411db09b84Saurel32 #define UIMAGE_LOAD_BASE 0 429dd5eba1SScott Wood #define DTC_LOAD_PAD 0x1800000 4375bb6589SLiu Yu #define DTC_PAD_MASK 0xFFFFF 4475bb6589SLiu Yu #define INITRD_LOAD_PAD 0x2000000 4575bb6589SLiu Yu #define INITRD_PAD_MASK 0xFFFFFF 461db09b84Saurel32 471db09b84Saurel32 #define RAM_SIZES_ALIGN (64UL << 20) 481db09b84Saurel32 49b3305981SScott Wood /* TODO: parameterize */ 50ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE 0xE0000000ULL 51ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE 0x00100000ULL 52dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET 0x40000ULL 53a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET 0x41600ULL 54dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL 55dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL 56dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET 0x8000ULL 57dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \ 58dffb1dc2SBharat Bhushan MPC8544_PCI_REGS_OFFSET) 59ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE 0x1000ULL 60ed2bc496SAlexander Graf #define MPC8544_PCI_IO 0xE1000000ULL 61dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET 0xe0000ULL 62ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE 0xEF000000ULL 631db09b84Saurel32 643b989d49SAlexander Graf struct boot_info 653b989d49SAlexander Graf { 663b989d49SAlexander Graf uint32_t dt_base; 67cba2026aSAlexander Graf uint32_t dt_size; 683b989d49SAlexander Graf uint32_t entry; 693b989d49SAlexander Graf }; 703b989d49SAlexander Graf 71347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, 72347dd79dSAlexander Graf int nr_slots, int *len) 730dbc0798SAlexander Graf { 74347dd79dSAlexander Graf int i = 0; 75347dd79dSAlexander Graf int slot; 76347dd79dSAlexander Graf int pci_irq; 779e2c1298SAlexander Graf int host_irq; 78347dd79dSAlexander Graf int last_slot = first_slot + nr_slots; 79347dd79dSAlexander Graf uint32_t *pci_map; 800dbc0798SAlexander Graf 81347dd79dSAlexander Graf *len = nr_slots * 4 * 7 * sizeof(uint32_t); 82347dd79dSAlexander Graf pci_map = g_malloc(*len); 83347dd79dSAlexander Graf 84347dd79dSAlexander Graf for (slot = first_slot; slot < last_slot; slot++) { 85347dd79dSAlexander Graf for (pci_irq = 0; pci_irq < 4; pci_irq++) { 86347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(slot << 11); 87347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 88347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 89347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(pci_irq + 1); 90347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(mpic); 919e2c1298SAlexander Graf host_irq = ppce500_pci_map_irq_slot(slot, pci_irq); 929e2c1298SAlexander Graf pci_map[i++] = cpu_to_be32(host_irq + 1); 93347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x1); 940dbc0798SAlexander Graf } 950dbc0798SAlexander Graf } 960dbc0798SAlexander Graf 97347dd79dSAlexander Graf assert((i * sizeof(uint32_t)) == *len); 98347dd79dSAlexander Graf 99347dd79dSAlexander Graf return pci_map; 100347dd79dSAlexander Graf } 101347dd79dSAlexander Graf 102a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset, 103a053a7ceSAlexander Graf const char *soc, const char *mpic, 104a053a7ceSAlexander Graf const char *alias, int idx, bool defcon) 105a053a7ceSAlexander Graf { 106a053a7ceSAlexander Graf char ser[128]; 107a053a7ceSAlexander Graf 108a053a7ceSAlexander Graf snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset); 109a053a7ceSAlexander Graf qemu_devtree_add_subnode(fdt, ser); 110a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, ser, "device_type", "serial"); 111a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550"); 112a053a7ceSAlexander Graf qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100); 113a053a7ceSAlexander Graf qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx); 114a053a7ceSAlexander Graf qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0); 1157e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2); 116a053a7ceSAlexander Graf qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic); 117a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", alias, ser); 118a053a7ceSAlexander Graf 119a053a7ceSAlexander Graf if (defcon) { 120a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); 121a053a7ceSAlexander Graf } 122a053a7ceSAlexander Graf } 123a053a7ceSAlexander Graf 124b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env, 125e6eaabebSScott Wood PPCE500Params *params, 126a8170e5eSAvi Kivity hwaddr addr, 127a8170e5eSAvi Kivity hwaddr initrd_base, 128a8170e5eSAvi Kivity hwaddr initrd_size) 1291db09b84Saurel32 { 130dbf916d8SAurelien Jarno int ret = -1; 131e6eaabebSScott Wood uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) }; 1327ec632b4Spbrook int fdt_size; 133dbf916d8SAurelien Jarno void *fdt; 1345de6b46dSAlexander Graf uint8_t hypercall[16]; 135911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 136911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 137621d05e3SAlexander Graf int i; 138e6eaabebSScott Wood const char *toplevel_compat = NULL; /* user override */ 139ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 1405da96624SAlexander Graf char soc[128]; 14119ac9deaSAlexander Graf char mpic[128]; 14219ac9deaSAlexander Graf uint32_t mpic_ph; 143a911b7a9SAlexander Graf uint32_t msi_ph; 144f5038483SAlexander Graf char gutil[128]; 1450dbc0798SAlexander Graf char pci[128]; 146a911b7a9SAlexander Graf char msi[128]; 147347dd79dSAlexander Graf uint32_t *pci_map = NULL; 148347dd79dSAlexander Graf int len; 1493627757eSAlexander Graf uint32_t pci_ranges[14] = 1503627757eSAlexander Graf { 1513627757eSAlexander Graf 0x2000000, 0x0, 0xc0000000, 1523627757eSAlexander Graf 0x0, 0xc0000000, 1533627757eSAlexander Graf 0x0, 0x20000000, 1543627757eSAlexander Graf 1553627757eSAlexander Graf 0x1000000, 0x0, 0x0, 1563627757eSAlexander Graf 0x0, 0xe1000000, 1573627757eSAlexander Graf 0x0, 0x10000, 1583627757eSAlexander Graf }; 15925b42708SAlexander Graf QemuOpts *machine_opts; 160d1b93565SAlexander Graf const char *dtb_file = NULL; 161d1b93565SAlexander Graf 162d1b93565SAlexander Graf machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); 163d1b93565SAlexander Graf if (machine_opts) { 164d1b93565SAlexander Graf dtb_file = qemu_opt_get(machine_opts, "dtb"); 165e6eaabebSScott Wood toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 166d1b93565SAlexander Graf } 167d1b93565SAlexander Graf 168d1b93565SAlexander Graf if (dtb_file) { 169d1b93565SAlexander Graf char *filename; 170d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 171d1b93565SAlexander Graf if (!filename) { 172d1b93565SAlexander Graf goto out; 173d1b93565SAlexander Graf } 174d1b93565SAlexander Graf 175d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 176d1b93565SAlexander Graf if (!fdt) { 177d1b93565SAlexander Graf goto out; 178d1b93565SAlexander Graf } 179d1b93565SAlexander Graf goto done; 180d1b93565SAlexander Graf } 1811db09b84Saurel32 1822636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 1835cea8590SPaul Brook if (fdt == NULL) { 1845cea8590SPaul Brook goto out; 1855cea8590SPaul Brook } 1861db09b84Saurel32 1871db09b84Saurel32 /* Manipulate device tree in memory. */ 1883627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); 1893627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); 19051b852b7SAlexander Graf 191dd0bcfcaSAlexander Graf qemu_devtree_add_subnode(fdt, "/memory"); 192dd0bcfcaSAlexander Graf qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); 193dd0bcfcaSAlexander Graf qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, 1941db09b84Saurel32 sizeof(mem_reg_property)); 1951db09b84Saurel32 196f5231aafSAlexander Graf qemu_devtree_add_subnode(fdt, "/chosen"); 1973b989d49SAlexander Graf if (initrd_size) { 1981db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", 1991db09b84Saurel32 initrd_base); 2003b989d49SAlexander Graf if (ret < 0) { 2011db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 2023b989d49SAlexander Graf } 2031db09b84Saurel32 2041db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", 2051db09b84Saurel32 (initrd_base + initrd_size)); 2063b989d49SAlexander Graf if (ret < 0) { 2071db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 2083b989d49SAlexander Graf } 2093b989d49SAlexander Graf } 2101db09b84Saurel32 2111db09b84Saurel32 ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", 212e6eaabebSScott Wood params->kernel_cmdline); 2131db09b84Saurel32 if (ret < 0) 2141db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 2151db09b84Saurel32 2161db09b84Saurel32 if (kvm_enabled()) { 217911d6e7aSAlexander Graf /* Read out host's frequencies */ 218911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 219911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 2205de6b46dSAlexander Graf 2215de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 222d50f71a5SAlexander Graf qemu_devtree_add_subnode(fdt, "/hypervisor"); 2235de6b46dSAlexander Graf qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible", 2245de6b46dSAlexander Graf "linux,kvm"); 2255de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 2265de6b46dSAlexander Graf qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions", 2275de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 2281db09b84Saurel32 } 2291db09b84Saurel32 230625e665bSAlexander Graf /* Create CPU nodes */ 231625e665bSAlexander Graf qemu_devtree_add_subnode(fdt, "/cpus"); 232625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1); 233625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0); 234625e665bSAlexander Graf 2351e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 2361e3debf0SAlexander Graf the first node as boot node and be happy */ 2371e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 238621d05e3SAlexander Graf char cpu_name[128]; 2391d2e5c52SAlexander Graf uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); 24010f25a46SAlexander Graf 2411e3debf0SAlexander Graf for (env = first_cpu; env != NULL; env = env->next_cpu) { 2421e3debf0SAlexander Graf if (env->cpu_index == i) { 2431e3debf0SAlexander Graf break; 2441e3debf0SAlexander Graf } 245621d05e3SAlexander Graf } 246911d6e7aSAlexander Graf 2471e3debf0SAlexander Graf if (!env) { 2481e3debf0SAlexander Graf continue; 2491e3debf0SAlexander Graf } 2501e3debf0SAlexander Graf 2511e3debf0SAlexander Graf snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index); 2521e3debf0SAlexander Graf qemu_devtree_add_subnode(fdt, cpu_name); 2531e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 2541e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 2551e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu"); 2561e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index); 2571e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size", 2581e3debf0SAlexander Graf env->dcache_line_size); 2591e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size", 2601e3debf0SAlexander Graf env->icache_line_size); 2611e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 2621e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 2631e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 2641e3debf0SAlexander Graf if (env->cpu_index) { 2651e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled"); 2661e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table"); 2671d2e5c52SAlexander Graf qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr", 2681d2e5c52SAlexander Graf cpu_release_addr); 2691e3debf0SAlexander Graf } else { 2701e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay"); 2711e3debf0SAlexander Graf } 2721db09b84Saurel32 } 2731db09b84Saurel32 2740cfc6e8dSAlexander Graf qemu_devtree_add_subnode(fdt, "/aliases"); 2755da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 276ed2bc496SAlexander Graf snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); 2775da96624SAlexander Graf qemu_devtree_add_subnode(fdt, soc); 2785da96624SAlexander Graf qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); 279ebb9518aSAlexander Graf qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb, 280ebb9518aSAlexander Graf sizeof(compatible_sb)); 2815da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); 2825da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); 2833627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, 2843627757eSAlexander Graf MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, 2855da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 2865da96624SAlexander Graf /* XXX should contain a reasonable value */ 2875da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); 2885da96624SAlexander Graf 289dffb1dc2SBharat Bhushan snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); 29019ac9deaSAlexander Graf qemu_devtree_add_subnode(fdt, mpic); 29119ac9deaSAlexander Graf qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); 2927e99826cSAlexander Graf qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); 293dffb1dc2SBharat Bhushan qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 294dffb1dc2SBharat Bhushan 0x40000); 29519ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); 2967e99826cSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 29719ac9deaSAlexander Graf mpic_ph = qemu_devtree_alloc_phandle(fdt); 29819ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); 29919ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 30019ac9deaSAlexander Graf qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 30119ac9deaSAlexander Graf 3020cfc6e8dSAlexander Graf /* 3030cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 3040cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 3050cfc6e8dSAlexander Graf * devices in reverse order to the dt. 3060cfc6e8dSAlexander Graf */ 307dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, 308a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 309dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, 310a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 3110cfc6e8dSAlexander Graf 312ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 313dffb1dc2SBharat Bhushan MPC8544_UTIL_OFFSET); 314f5038483SAlexander Graf qemu_devtree_add_subnode(fdt, gutil); 315f5038483SAlexander Graf qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 316dffb1dc2SBharat Bhushan qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); 317f5038483SAlexander Graf qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 318f5038483SAlexander Graf 319a911b7a9SAlexander Graf snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); 320a911b7a9SAlexander Graf qemu_devtree_add_subnode(fdt, msi); 321a911b7a9SAlexander Graf qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); 322a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); 323a911b7a9SAlexander Graf msi_ph = qemu_devtree_alloc_phandle(fdt); 324a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); 325a911b7a9SAlexander Graf qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic); 326a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "interrupts", 327a911b7a9SAlexander Graf 0xe0, 0x0, 328a911b7a9SAlexander Graf 0xe1, 0x0, 329a911b7a9SAlexander Graf 0xe2, 0x0, 330a911b7a9SAlexander Graf 0xe3, 0x0, 331a911b7a9SAlexander Graf 0xe4, 0x0, 332a911b7a9SAlexander Graf 0xe5, 0x0, 333a911b7a9SAlexander Graf 0xe6, 0x0, 334a911b7a9SAlexander Graf 0xe7, 0x0); 335a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph); 336a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph); 337a911b7a9SAlexander Graf 338ed2bc496SAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); 3390dbc0798SAlexander Graf qemu_devtree_add_subnode(fdt, pci); 3400dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); 3410dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 3420dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "device_type", "pci"); 3430dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 3440dbc0798SAlexander Graf 0x0, 0x7); 345347dd79dSAlexander Graf pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic), 346492ec48dSAlexander Graf params->pci_first_slot, params->pci_nr_slots, 347492ec48dSAlexander Graf &len); 348347dd79dSAlexander Graf qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len); 3490dbc0798SAlexander Graf qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 3507e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); 3510dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); 3523627757eSAlexander Graf for (i = 0; i < 14; i++) { 3530dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 3540dbc0798SAlexander Graf } 355a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph); 3560dbc0798SAlexander Graf qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 3573627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, 3583627757eSAlexander Graf MPC8544_PCI_REGS_BASE, 0, 0x1000); 3590dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666); 3600dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1); 3610dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2); 3620dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); 3630dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); 3640dbc0798SAlexander Graf 365e6eaabebSScott Wood params->fixup_devtree(params, fdt); 366e6eaabebSScott Wood 367e6eaabebSScott Wood if (toplevel_compat) { 368e6eaabebSScott Wood qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat, 369e6eaabebSScott Wood strlen(toplevel_compat) + 1); 370e6eaabebSScott Wood } 371e6eaabebSScott Wood 372d1b93565SAlexander Graf done: 37371193433SAlexander Graf qemu_devtree_dumpdtb(fdt, fdt_size); 37404088adbSLiu Yu ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); 375cba2026aSAlexander Graf if (ret < 0) { 376cba2026aSAlexander Graf goto out; 377cba2026aSAlexander Graf } 3787267c094SAnthony Liguori g_free(fdt); 379cba2026aSAlexander Graf ret = fdt_size; 3807ec632b4Spbrook 3811db09b84Saurel32 out: 382347dd79dSAlexander Graf g_free(pci_map); 3831db09b84Saurel32 38404088adbSLiu Yu return ret; 3851db09b84Saurel32 } 3861db09b84Saurel32 387cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 388a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size) 389d1e256feSAlexander Graf { 390cba2026aSAlexander Graf return 63 - clz64(size >> 10); 391d1e256feSAlexander Graf } 392d1e256feSAlexander Graf 393cba2026aSAlexander Graf static void mmubooke_create_initial_mapping(CPUPPCState *env) 3943b989d49SAlexander Graf { 395cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 396d1e256feSAlexander Graf ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 397a8170e5eSAvi Kivity hwaddr size, dt_end; 398cba2026aSAlexander Graf int ps; 3993b989d49SAlexander Graf 400cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 401cba2026aSAlexander Graf the device tree top */ 402cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 403cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 404fb37c302SAlexander Graf if (ps & 1) { 405fb37c302SAlexander Graf /* e500v2 can only do even TLB size bits */ 406fb37c302SAlexander Graf ps++; 407fb37c302SAlexander Graf } 408cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 409d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 410cba2026aSAlexander Graf tlb->mas2 = 0; 411cba2026aSAlexander Graf tlb->mas7_3 = 0; 412d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 41393dd5e85SScott Wood 41493dd5e85SScott Wood env->tlb_dirty = true; 4153b989d49SAlexander Graf } 4163b989d49SAlexander Graf 417b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 4185c145dacSAlexander Graf { 41938f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 42038f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 4215c145dacSAlexander Graf 42238f92da6SAndreas Färber cpu_reset(CPU(cpu)); 4235c145dacSAlexander Graf 4245c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 4255c145dacSAlexander Graf implementing non-kernel boot. */ 4265c145dacSAlexander Graf env->halted = 1; 4275c145dacSAlexander Graf env->exception_index = EXCP_HLT; 4283b989d49SAlexander Graf } 4293b989d49SAlexander Graf 430b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 4313b989d49SAlexander Graf { 43238f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 43338f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 4343b989d49SAlexander Graf struct boot_info *bi = env->load_info; 4353b989d49SAlexander Graf 43638f92da6SAndreas Färber cpu_reset(CPU(cpu)); 4373b989d49SAlexander Graf 4383b989d49SAlexander Graf /* Set initial guest state. */ 4395c145dacSAlexander Graf env->halted = 0; 4403b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 4413b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 4423b989d49SAlexander Graf env->nip = bi->entry; 443cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 4443b989d49SAlexander Graf } 4453b989d49SAlexander Graf 446e6eaabebSScott Wood void ppce500_init(PPCE500Params *params) 4471db09b84Saurel32 { 44839186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 4492646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 4501db09b84Saurel32 PCIBus *pci_bus; 451e2684c0bSAndreas Färber CPUPPCState *env = NULL; 4521db09b84Saurel32 uint64_t elf_entry; 4531db09b84Saurel32 uint64_t elf_lowaddr; 454a8170e5eSAvi Kivity hwaddr entry=0; 455a8170e5eSAvi Kivity hwaddr loadaddr=UIMAGE_LOAD_BASE; 4561db09b84Saurel32 target_long kernel_size=0; 45775bb6589SLiu Yu target_ulong dt_base = 0; 45875bb6589SLiu Yu target_ulong initrd_base = 0; 4591db09b84Saurel32 target_long initrd_size=0; 460d0b72631SAlexander Graf int i = 0, j, k; 4611db09b84Saurel32 unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; 462a915249fSAlexander Graf qemu_irq **irqs, *mpic; 463be13cc7aSAlexander Graf DeviceState *dev; 464e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 4653eddc1beSBharat Bhushan MemoryRegion *ccsr_addr_space; 466dffb1dc2SBharat Bhushan SysBusDevice *s; 4673eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 4681db09b84Saurel32 469e61c36d5SAlexander Graf /* Setup CPUs */ 470e6eaabebSScott Wood if (params->cpu_model == NULL) { 471e6eaabebSScott Wood params->cpu_model = "e500v2_v30"; 472ef250db6SAlexander Graf } 473ef250db6SAlexander Graf 474a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 475a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 476e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 477397b457dSAndreas Färber PowerPCCPU *cpu; 478e61c36d5SAlexander Graf qemu_irq *input; 479397b457dSAndreas Färber 480e6eaabebSScott Wood cpu = cpu_ppc_init(params->cpu_model); 481397b457dSAndreas Färber if (cpu == NULL) { 4821db09b84Saurel32 fprintf(stderr, "Unable to initialize CPU!\n"); 4831db09b84Saurel32 exit(1); 4841db09b84Saurel32 } 485397b457dSAndreas Färber env = &cpu->env; 4861db09b84Saurel32 487e61c36d5SAlexander Graf if (!firstenv) { 488e61c36d5SAlexander Graf firstenv = env; 489e61c36d5SAlexander Graf } 490e61c36d5SAlexander Graf 491a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 492a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 493a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 494a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 495e61c36d5SAlexander Graf env->spr[SPR_BOOKE_PIR] = env->cpu_index = i; 496dffb1dc2SBharat Bhushan env->mpic_cpu_base = MPC8544_CCSRBAR_BASE + 497dffb1dc2SBharat Bhushan MPC8544_MPIC_REGS_OFFSET + 0x20000; 498e61c36d5SAlexander Graf 499ddd1055bSFabien Chouteau ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500); 5003b989d49SAlexander Graf 5013b989d49SAlexander Graf /* Register reset handler */ 5025c145dacSAlexander Graf if (!i) { 5035c145dacSAlexander Graf /* Primary CPU */ 5045c145dacSAlexander Graf struct boot_info *boot_info; 505e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 506b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 507e61c36d5SAlexander Graf env->load_info = boot_info; 5085c145dacSAlexander Graf } else { 5095c145dacSAlexander Graf /* Secondary CPUs */ 510b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 5115c145dacSAlexander Graf } 512e61c36d5SAlexander Graf } 513e61c36d5SAlexander Graf 514e61c36d5SAlexander Graf env = firstenv; 5153b989d49SAlexander Graf 5161db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 5171db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 5181db09b84Saurel32 5191db09b84Saurel32 /* Register Memory */ 520c5705a77SAvi Kivity memory_region_init_ram(ram, "mpc8544ds.ram", ram_size); 521c5705a77SAvi Kivity vmstate_register_ram_global(ram); 5222646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 5231db09b84Saurel32 5243eddc1beSBharat Bhushan dev = qdev_create(NULL, "e500-ccsr"); 5253eddc1beSBharat Bhushan object_property_add_child(qdev_get_machine(), "e500-ccsr", 5263eddc1beSBharat Bhushan OBJECT(dev), NULL); 5273eddc1beSBharat Bhushan qdev_init_nofail(dev); 5283eddc1beSBharat Bhushan ccsr = CCSR(dev); 5293eddc1beSBharat Bhushan ccsr_addr_space = &ccsr->ccsr_space; 5303eddc1beSBharat Bhushan memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, 5313eddc1beSBharat Bhushan ccsr_addr_space); 532dffb1dc2SBharat Bhushan 5331db09b84Saurel32 /* MPIC */ 534d0b72631SAlexander Graf mpic = g_new(qemu_irq, 256); 535d0b72631SAlexander Graf dev = qdev_create(NULL, "openpic"); 536d0b72631SAlexander Graf qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); 537d0b72631SAlexander Graf qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20); 538d0b72631SAlexander Graf qdev_init_nofail(dev); 539d0b72631SAlexander Graf s = sysbus_from_qdev(dev); 540a915249fSAlexander Graf 541d0b72631SAlexander Graf k = 0; 542d0b72631SAlexander Graf for (i = 0; i < smp_cpus; i++) { 543d0b72631SAlexander Graf for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { 544d0b72631SAlexander Graf sysbus_connect_irq(s, k++, irqs[i][j]); 545a915249fSAlexander Graf } 546d0b72631SAlexander Graf } 547d0b72631SAlexander Graf 548d0b72631SAlexander Graf for (i = 0; i < 256; i++) { 549d0b72631SAlexander Graf mpic[i] = qdev_get_gpio_in(dev, i); 550d0b72631SAlexander Graf } 551d0b72631SAlexander Graf 552d0b72631SAlexander Graf memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET, 553d0b72631SAlexander Graf s->mmio[0].memory); 5541db09b84Saurel32 5551db09b84Saurel32 /* Serial */ 5562d48377aSBlue Swirl if (serial_hds[0]) { 5573eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 558cdbb912aSAlexander Graf 0, mpic[42], 399193, 5592ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 5602d48377aSBlue Swirl } 5611db09b84Saurel32 5622d48377aSBlue Swirl if (serial_hds[1]) { 5633eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 564cdbb912aSAlexander Graf 0, mpic[42], 399193, 56559de4f98SBharat Bhushan serial_hds[1], DEVICE_BIG_ENDIAN); 5662d48377aSBlue Swirl } 5671db09b84Saurel32 568b0fb8423SAlexander Graf /* General Utility device */ 569dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "mpc8544-guts"); 570dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 571dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 5723eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, 573dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 574b0fb8423SAlexander Graf 5751db09b84Saurel32 /* PCI */ 576dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "e500-pcihost"); 577492ec48dSAlexander Graf qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); 578dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 579dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 580dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]); 581dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]); 582dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]); 583dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]); 5843eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, 585dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 586dffb1dc2SBharat Bhushan 587d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 5881db09b84Saurel32 if (!pci_bus) 5891db09b84Saurel32 printf("couldn't create PCI controller!\n"); 5901db09b84Saurel32 591a1bc20dfSAlexander Graf sysbus_mmio_map(sysbus_from_qdev(dev), 1, MPC8544_PCI_IO); 5921db09b84Saurel32 5931db09b84Saurel32 if (pci_bus) { 5941db09b84Saurel32 /* Register network interfaces. */ 5951db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 59607caea31SMarkus Armbruster pci_nic_init_nofail(&nd_table[i], "virtio", NULL); 5971db09b84Saurel32 } 5981db09b84Saurel32 } 5991db09b84Saurel32 6005c145dacSAlexander Graf /* Register spinning region */ 6015c145dacSAlexander Graf sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); 6025c145dacSAlexander Graf 6031db09b84Saurel32 /* Load kernel. */ 604e6eaabebSScott Wood if (params->kernel_filename) { 605e6eaabebSScott Wood kernel_size = load_uimage(params->kernel_filename, &entry, 606e6eaabebSScott Wood &loadaddr, NULL); 6071db09b84Saurel32 if (kernel_size < 0) { 608e6eaabebSScott Wood kernel_size = load_elf(params->kernel_filename, NULL, NULL, 609e6eaabebSScott Wood &elf_entry, &elf_lowaddr, NULL, 1, 610e6eaabebSScott Wood ELF_MACHINE, 0); 6111db09b84Saurel32 entry = elf_entry; 6121db09b84Saurel32 loadaddr = elf_lowaddr; 6131db09b84Saurel32 } 6141db09b84Saurel32 /* XXX try again as binary */ 6151db09b84Saurel32 if (kernel_size < 0) { 6161db09b84Saurel32 fprintf(stderr, "qemu: could not load kernel '%s'\n", 617e6eaabebSScott Wood params->kernel_filename); 6181db09b84Saurel32 exit(1); 6191db09b84Saurel32 } 6201db09b84Saurel32 } 6211db09b84Saurel32 6221db09b84Saurel32 /* Load initrd. */ 623e6eaabebSScott Wood if (params->initrd_filename) { 6247e7ec2d2SScott Wood initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) & 6257e7ec2d2SScott Wood ~INITRD_PAD_MASK; 626e6eaabebSScott Wood initrd_size = load_image_targphys(params->initrd_filename, initrd_base, 627d7585251Spbrook ram_size - initrd_base); 6281db09b84Saurel32 6291db09b84Saurel32 if (initrd_size < 0) { 6301db09b84Saurel32 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 631e6eaabebSScott Wood params->initrd_filename); 6321db09b84Saurel32 exit(1); 6331db09b84Saurel32 } 6341db09b84Saurel32 } 6351db09b84Saurel32 6361db09b84Saurel32 /* If we're loading a kernel directly, we must load the device tree too. */ 637e6eaabebSScott Wood if (params->kernel_filename) { 6385c145dacSAlexander Graf struct boot_info *boot_info; 639cba2026aSAlexander Graf int dt_size; 6405c145dacSAlexander Graf 641cba2026aSAlexander Graf dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 642e6eaabebSScott Wood dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base, 643e6eaabebSScott Wood initrd_size); 644cba2026aSAlexander Graf if (dt_size < 0) { 6451db09b84Saurel32 fprintf(stderr, "couldn't load device tree\n"); 6461db09b84Saurel32 exit(1); 6471db09b84Saurel32 } 6481db09b84Saurel32 649e61c36d5SAlexander Graf boot_info = env->load_info; 6503b989d49SAlexander Graf boot_info->entry = entry; 6513b989d49SAlexander Graf boot_info->dt_base = dt_base; 652cba2026aSAlexander Graf boot_info->dt_size = dt_size; 6531db09b84Saurel32 } 6541db09b84Saurel32 6553b989d49SAlexander Graf if (kvm_enabled()) { 6561db09b84Saurel32 kvmppc_init(); 6573b989d49SAlexander Graf } 6581db09b84Saurel32 } 6593eddc1beSBharat Bhushan 6603eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev) 6613eddc1beSBharat Bhushan { 6623eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 6633eddc1beSBharat Bhushan 6643eddc1beSBharat Bhushan ccsr = CCSR(dev); 6653eddc1beSBharat Bhushan memory_region_init(&ccsr->ccsr_space, "e500-ccsr", 6663eddc1beSBharat Bhushan MPC8544_CCSRBAR_SIZE); 6673eddc1beSBharat Bhushan return 0; 6683eddc1beSBharat Bhushan } 6693eddc1beSBharat Bhushan 6703eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data) 6713eddc1beSBharat Bhushan { 6723eddc1beSBharat Bhushan SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 6733eddc1beSBharat Bhushan k->init = e500_ccsr_initfn; 6743eddc1beSBharat Bhushan } 6753eddc1beSBharat Bhushan 6763eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = { 6773eddc1beSBharat Bhushan .name = TYPE_CCSR, 6783eddc1beSBharat Bhushan .parent = TYPE_SYS_BUS_DEVICE, 6793eddc1beSBharat Bhushan .instance_size = sizeof(PPCE500CCSRState), 6803eddc1beSBharat Bhushan .class_init = e500_ccsr_class_init, 6813eddc1beSBharat Bhushan }; 6823eddc1beSBharat Bhushan 6833eddc1beSBharat Bhushan static void e500_register_types(void) 6843eddc1beSBharat Bhushan { 6853eddc1beSBharat Bhushan type_register_static(&e500_ccsr_info); 6863eddc1beSBharat Bhushan } 6873eddc1beSBharat Bhushan 6883eddc1beSBharat Bhushan type_init(e500_register_types) 689