|
|
1.1 root 1: /* 1.1.1.8 ! root 2: * QEMU PowerPC 440 Bamboo board emulation 1.1 root 3: * 4: * Copyright 2007 IBM Corporation. 5: * Authors: 1.1.1.8 ! root 6: * Jerone Young <[email protected]> ! 7: * Christian Ehrhardt <[email protected]> ! 8: * Hollis Blanchard <[email protected]> 1.1 root 9: * 10: * This work is licensed under the GNU GPL license version 2 or later. 11: * 12: */ 13: 14: #include "config.h" 15: #include "qemu-common.h" 16: #include "net.h" 17: #include "hw.h" 18: #include "pci.h" 19: #include "boards.h" 20: #include "kvm.h" 21: #include "kvm_ppc.h" 22: #include "device_tree.h" 1.1.1.3 root 23: #include "loader.h" 24: #include "elf.h" 1.1.1.7 root 25: #include "exec-memory.h" 1.1.1.8 ! root 26: #include "pc.h" ! 27: #include "ppc.h" ! 28: #include "ppc405.h" ! 29: #include "sysemu.h" ! 30: #include "sysbus.h" 1.1 root 31: 32: #define BINARY_DEVICE_TREE_FILE "bamboo.dtb" 33: 1.1.1.5 root 34: /* from u-boot */ 35: #define KERNEL_ADDR 0x1000000 36: #define FDT_ADDR 0x1800000 37: #define RAMDISK_ADDR 0x1900000 38: 1.1.1.8 ! root 39: #define PPC440EP_PCI_CONFIG 0xeec00000 ! 40: #define PPC440EP_PCI_INTACK 0xeed00000 ! 41: #define PPC440EP_PCI_SPECIAL 0xeed00000 ! 42: #define PPC440EP_PCI_REGS 0xef400000 ! 43: #define PPC440EP_PCI_IO 0xe8000000 ! 44: #define PPC440EP_PCI_IOLEN 0x00010000 ! 45: ! 46: #define PPC440EP_SDRAM_NR_BANKS 4 ! 47: ! 48: static const unsigned int ppc440ep_sdram_bank_sizes[] = { ! 49: 256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0 ! 50: }; ! 51: ! 52: static target_phys_addr_t entry; ! 53: 1.1.1.4 root 54: static int bamboo_load_device_tree(target_phys_addr_t addr, 1.1 root 55: uint32_t ramsize, 56: target_phys_addr_t initrd_base, 57: target_phys_addr_t initrd_size, 58: const char *kernel_cmdline) 59: { 1.1.1.4 root 60: int ret = -1; 1.1.1.3 root 61: #ifdef CONFIG_FDT 1.1 root 62: uint32_t mem_reg_property[] = { 0, 0, ramsize }; 1.1.1.2 root 63: char *filename; 64: int fdt_size; 1.1.1.4 root 65: void *fdt; 1.1.1.7 root 66: uint32_t tb_freq = 400000000; 67: uint32_t clock_freq = 400000000; 1.1 root 68: 1.1.1.2 root 69: filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); 70: if (!filename) { 1.1 root 71: goto out; 1.1.1.2 root 72: } 73: fdt = load_device_tree(filename, &fdt_size); 1.1.1.7 root 74: g_free(filename); 1.1.1.2 root 75: if (fdt == NULL) { 76: goto out; 77: } 1.1 root 78: 79: /* Manipulate device tree in memory. */ 80: 81: ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, 82: sizeof(mem_reg_property)); 83: if (ret < 0) 84: fprintf(stderr, "couldn't set /memory/reg\n"); 85: 86: ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", 87: initrd_base); 88: if (ret < 0) 89: fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 90: 91: ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", 92: (initrd_base + initrd_size)); 93: if (ret < 0) 94: fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 95: 96: ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", 97: kernel_cmdline); 98: if (ret < 0) 99: fprintf(stderr, "couldn't set /chosen/bootargs\n"); 100: 1.1.1.7 root 101: /* Copy data from the host device tree into the guest. Since the guest can 102: * directly access the timebase without host involvement, we must expose 103: * the correct frequencies. */ 104: if (kvm_enabled()) { 105: tb_freq = kvmppc_get_tbfreq(); 106: clock_freq = kvmppc_get_clockfreq(); 107: } 108: 109: qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency", 110: clock_freq); 111: qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency", 112: tb_freq); 1.1 root 113: 1.1.1.4 root 114: ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); 1.1.1.7 root 115: g_free(fdt); 1.1.1.2 root 116: 1.1 root 117: out: 118: #endif 119: 1.1.1.4 root 120: return ret; 1.1 root 121: } 122: 1.1.1.8 ! root 123: /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ ! 124: static void mmubooke_create_initial_mapping(CPUPPCState *env, ! 125: target_ulong va, ! 126: target_phys_addr_t pa) ! 127: { ! 128: ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; ! 129: ! 130: tlb->attr = 0; ! 131: tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); ! 132: tlb->size = 1 << 31; /* up to 0x80000000 */ ! 133: tlb->EPN = va & TARGET_PAGE_MASK; ! 134: tlb->RPN = pa & TARGET_PAGE_MASK; ! 135: tlb->PID = 0; ! 136: ! 137: tlb = &env->tlb.tlbe[1]; ! 138: tlb->attr = 0; ! 139: tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); ! 140: tlb->size = 1 << 31; /* up to 0xffffffff */ ! 141: tlb->EPN = 0x80000000 & TARGET_PAGE_MASK; ! 142: tlb->RPN = 0x80000000 & TARGET_PAGE_MASK; ! 143: tlb->PID = 0; ! 144: } ! 145: ! 146: static void main_cpu_reset(void *opaque) ! 147: { ! 148: CPUPPCState *env = opaque; ! 149: ! 150: cpu_state_reset(env); ! 151: env->gpr[1] = (16<<20) - 8; ! 152: env->gpr[3] = FDT_ADDR; ! 153: env->nip = entry; ! 154: ! 155: /* Create a mapping for the kernel. */ ! 156: mmubooke_create_initial_mapping(env, 0, 0); ! 157: } ! 158: 1.1.1.2 root 159: static void bamboo_init(ram_addr_t ram_size, 1.1 root 160: const char *boot_device, 161: const char *kernel_filename, 162: const char *kernel_cmdline, 163: const char *initrd_filename, 164: const char *cpu_model) 165: { 166: unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 }; 1.1.1.7 root 167: MemoryRegion *address_space_mem = get_system_memory(); 1.1.1.8 ! root 168: MemoryRegion *ram_memories ! 169: = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories)); ! 170: target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS]; ! 171: target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS]; ! 172: qemu_irq *pic; ! 173: qemu_irq *irqs; 1.1 root 174: PCIBus *pcibus; 1.1.1.8 ! root 175: CPUPPCState *env; 1.1 root 176: uint64_t elf_entry; 177: uint64_t elf_lowaddr; 1.1.1.3 root 178: target_phys_addr_t loadaddr = 0; 1.1 root 179: target_long initrd_size = 0; 1.1.1.8 ! root 180: DeviceState *dev; 1.1.1.5 root 181: int success; 1.1 root 182: int i; 183: 184: /* Setup CPU. */ 1.1.1.8 ! root 185: if (cpu_model == NULL) { ! 186: cpu_model = "440EP"; ! 187: } ! 188: env = cpu_init(cpu_model); ! 189: if (!env) { ! 190: fprintf(stderr, "Unable to initialize CPU!\n"); ! 191: exit(1); ! 192: } ! 193: ! 194: qemu_register_reset(main_cpu_reset, env); ! 195: ppc_booke_timers_init(env, 400000000, 0); ! 196: ppc_dcr_init(env, NULL, NULL); ! 197: ! 198: /* interrupt controller */ ! 199: irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); ! 200: irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; ! 201: irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; ! 202: pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); ! 203: ! 204: /* SDRAM controller */ ! 205: memset(ram_bases, 0, sizeof(ram_bases)); ! 206: memset(ram_sizes, 0, sizeof(ram_sizes)); ! 207: ram_size = ppc4xx_sdram_adjust(ram_size, PPC440EP_SDRAM_NR_BANKS, ! 208: ram_memories, ! 209: ram_bases, ram_sizes, ! 210: ppc440ep_sdram_bank_sizes); ! 211: /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */ ! 212: ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories, ! 213: ram_bases, ram_sizes, 1); ! 214: ! 215: /* PCI */ ! 216: dev = sysbus_create_varargs("ppc4xx-pcihost", PPC440EP_PCI_CONFIG, ! 217: pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]], ! 218: pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]], ! 219: NULL); ! 220: pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); ! 221: if (!pcibus) { ! 222: fprintf(stderr, "couldn't create PCI controller!\n"); ! 223: exit(1); ! 224: } ! 225: ! 226: isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN); ! 227: ! 228: if (serial_hds[0] != NULL) { ! 229: serial_mm_init(address_space_mem, 0xef600300, 0, pic[0], ! 230: PPC_SERIAL_MM_BAUDBASE, serial_hds[0], ! 231: DEVICE_BIG_ENDIAN); ! 232: } ! 233: if (serial_hds[1] != NULL) { ! 234: serial_mm_init(address_space_mem, 0xef600400, 0, pic[1], ! 235: PPC_SERIAL_MM_BAUDBASE, serial_hds[1], ! 236: DEVICE_BIG_ENDIAN); ! 237: } 1.1 root 238: 239: if (pcibus) { 240: /* Register network interfaces. */ 241: for (i = 0; i < nb_nics; i++) { 242: /* There are no PCI NICs on the Bamboo board, but there are 243: * PCI slots, so we can pick whatever default model we want. */ 1.1.1.3 root 244: pci_nic_init_nofail(&nd_table[i], "e1000", NULL); 1.1 root 245: } 246: } 247: 248: /* Load kernel. */ 249: if (kernel_filename) { 1.1.1.5 root 250: success = load_uimage(kernel_filename, &entry, &loadaddr, NULL); 251: if (success < 0) { 252: success = load_elf(kernel_filename, NULL, NULL, &elf_entry, 253: &elf_lowaddr, NULL, 1, ELF_MACHINE, 0); 1.1 root 254: entry = elf_entry; 255: loadaddr = elf_lowaddr; 256: } 257: /* XXX try again as binary */ 1.1.1.5 root 258: if (success < 0) { 1.1 root 259: fprintf(stderr, "qemu: could not load kernel '%s'\n", 260: kernel_filename); 261: exit(1); 262: } 263: } 264: 265: /* Load initrd. */ 266: if (initrd_filename) { 1.1.1.5 root 267: initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR, 268: ram_size - RAMDISK_ADDR); 1.1 root 269: 270: if (initrd_size < 0) { 1.1.1.5 root 271: fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n", 272: initrd_filename, RAMDISK_ADDR); 1.1 root 273: exit(1); 274: } 275: } 276: 277: /* If we're loading a kernel directly, we must load the device tree too. */ 278: if (kernel_filename) { 1.1.1.5 root 279: if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR, 280: initrd_size, kernel_cmdline) < 0) { 1.1 root 281: fprintf(stderr, "couldn't load device tree\n"); 282: exit(1); 283: } 284: } 285: 286: if (kvm_enabled()) 287: kvmppc_init(); 288: } 289: 1.1.1.2 root 290: static QEMUMachine bamboo_machine = { 1.1.1.8 ! root 291: .name = "bamboo", 1.1 root 292: .desc = "bamboo", 293: .init = bamboo_init, 294: }; 1.1.1.2 root 295: 296: static void bamboo_machine_init(void) 297: { 298: qemu_register_machine(&bamboo_machine); 299: } 300: 301: machine_init(bamboo_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.