|
|
1.1 ! root 1: /* ! 2: * Model of Xilinx Virtex5 ML507 PPC-440 refdesign. ! 3: * ! 4: * Copyright (c) 2010 Edgar E. Iglesias. ! 5: * ! 6: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 7: * of this software and associated documentation files (the "Software"), to deal ! 8: * in the Software without restriction, including without limitation the rights ! 9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 10: * copies of the Software, and to permit persons to whom the Software is ! 11: * furnished to do so, subject to the following conditions: ! 12: * ! 13: * The above copyright notice and this permission notice shall be included in ! 14: * all copies or substantial portions of the Software. ! 15: * ! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 22: * THE SOFTWARE. ! 23: */ ! 24: ! 25: #include "sysbus.h" ! 26: #include "hw.h" ! 27: #include "pc.h" ! 28: #include "net.h" ! 29: #include "flash.h" ! 30: #include "sysemu.h" ! 31: #include "devices.h" ! 32: #include "boards.h" ! 33: #include "device_tree.h" ! 34: #include "loader.h" ! 35: #include "elf.h" ! 36: #include "qemu-log.h" ! 37: ! 38: #include "ppc.h" ! 39: #include "ppc4xx.h" ! 40: #include "ppc440.h" ! 41: #include "ppc405.h" ! 42: ! 43: #include "blockdev.h" ! 44: #include "xilinx.h" ! 45: ! 46: #define EPAPR_MAGIC (0x45504150) ! 47: #define FLASH_SIZE (16 * 1024 * 1024) ! 48: ! 49: static struct boot_info ! 50: { ! 51: uint32_t bootstrap_pc; ! 52: uint32_t cmdline; ! 53: uint32_t fdt; ! 54: uint32_t ima_size; ! 55: void *vfdt; ! 56: } boot_info; ! 57: ! 58: /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ ! 59: static void mmubooke_create_initial_mapping(CPUState *env, ! 60: target_ulong va, ! 61: target_phys_addr_t pa) ! 62: { ! 63: ppcemb_tlb_t *tlb = &env->tlb[0].tlbe; ! 64: ! 65: tlb->attr = 0; ! 66: tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); ! 67: tlb->size = 1 << 31; /* up to 0x80000000 */ ! 68: tlb->EPN = va & TARGET_PAGE_MASK; ! 69: tlb->RPN = pa & TARGET_PAGE_MASK; ! 70: tlb->PID = 0; ! 71: ! 72: tlb = &env->tlb[1].tlbe; ! 73: tlb->attr = 0; ! 74: tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); ! 75: tlb->size = 1 << 31; /* up to 0xffffffff */ ! 76: tlb->EPN = 0x80000000 & TARGET_PAGE_MASK; ! 77: tlb->RPN = 0x80000000 & TARGET_PAGE_MASK; ! 78: tlb->PID = 0; ! 79: } ! 80: ! 81: static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size, ! 82: int do_init, ! 83: const char *cpu_model, ! 84: clk_setup_t *cpu_clk, clk_setup_t *tb_clk, ! 85: uint32_t sysclk) ! 86: { ! 87: CPUState *env; ! 88: qemu_irq *irqs; ! 89: ! 90: env = cpu_init(cpu_model); ! 91: if (!env) { ! 92: fprintf(stderr, "Unable to initialize CPU!\n"); ! 93: exit(1); ! 94: } ! 95: ! 96: cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */ ! 97: cpu_clk->opaque = env; ! 98: /* Set time-base frequency to sysclk */ ! 99: tb_clk->cb = ppc_emb_timers_init(env, sysclk, PPC_INTERRUPT_DECR); ! 100: tb_clk->opaque = env; ! 101: ! 102: ppc_dcr_init(env, NULL, NULL); ! 103: ! 104: /* interrupt controller */ ! 105: irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); ! 106: irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; ! 107: irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; ! 108: ppcuic_init(env, irqs, 0x0C0, 0, 1); ! 109: return env; ! 110: } ! 111: ! 112: static void main_cpu_reset(void *opaque) ! 113: { ! 114: CPUState *env = opaque; ! 115: struct boot_info *bi = env->load_info; ! 116: ! 117: cpu_reset(env); ! 118: /* Linux Kernel Parameters (passing device tree): ! 119: * r3: pointer to the fdt ! 120: * r4: 0 ! 121: * r5: 0 ! 122: * r6: epapr magic ! 123: * r7: size of IMA in bytes ! 124: * r8: 0 ! 125: * r9: 0 ! 126: */ ! 127: env->gpr[1] = (16<<20) - 8; ! 128: /* Provide a device-tree. */ ! 129: env->gpr[3] = bi->fdt; ! 130: env->nip = bi->bootstrap_pc; ! 131: ! 132: /* Create a mapping for the kernel. */ ! 133: mmubooke_create_initial_mapping(env, 0, 0); ! 134: env->gpr[6] = tswap32(EPAPR_MAGIC); ! 135: env->gpr[7] = bi->ima_size; ! 136: } ! 137: ! 138: #define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb" ! 139: static int xilinx_load_device_tree(target_phys_addr_t addr, ! 140: uint32_t ramsize, ! 141: target_phys_addr_t initrd_base, ! 142: target_phys_addr_t initrd_size, ! 143: const char *kernel_cmdline) ! 144: { ! 145: char *path; ! 146: int fdt_size; ! 147: #ifdef CONFIG_FDT ! 148: void *fdt; ! 149: int r; ! 150: ! 151: /* Try the local "ppc.dtb" override. */ ! 152: fdt = load_device_tree("ppc.dtb", &fdt_size); ! 153: if (!fdt) { ! 154: path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); ! 155: if (path) { ! 156: fdt = load_device_tree(path, &fdt_size); ! 157: qemu_free(path); ! 158: } ! 159: if (!fdt) { ! 160: return 0; ! 161: } ! 162: } ! 163: ! 164: r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); ! 165: if (r < 0) ! 166: fprintf(stderr, "couldn't set /chosen/bootargs\n"); ! 167: cpu_physical_memory_write (addr, (void *)fdt, fdt_size); ! 168: #else ! 169: /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob ! 170: to the kernel. */ ! 171: fdt_size = load_image_targphys("ppc.dtb", addr, 0x10000); ! 172: if (fdt_size < 0) { ! 173: path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); ! 174: if (path) { ! 175: fdt_size = load_image_targphys(path, addr, 0x10000); ! 176: qemu_free(path); ! 177: } ! 178: } ! 179: ! 180: if (kernel_cmdline) { ! 181: fprintf(stderr, ! 182: "Warning: missing libfdt, cannot pass cmdline to kernel!\n"); ! 183: } ! 184: #endif ! 185: return fdt_size; ! 186: } ! 187: ! 188: static void virtex_init(ram_addr_t ram_size, ! 189: const char *boot_device, ! 190: const char *kernel_filename, ! 191: const char *kernel_cmdline, ! 192: const char *initrd_filename, const char *cpu_model) ! 193: { ! 194: DeviceState *dev; ! 195: CPUState *env; ! 196: target_phys_addr_t ram_base = 0; ! 197: DriveInfo *dinfo; ! 198: ram_addr_t phys_ram; ! 199: ram_addr_t phys_flash; ! 200: qemu_irq irq[32], *cpu_irq; ! 201: clk_setup_t clk_setup[7]; ! 202: int kernel_size; ! 203: int i; ! 204: ! 205: /* init CPUs */ ! 206: if (cpu_model == NULL) { ! 207: cpu_model = "440-Xilinx"; ! 208: } ! 209: ! 210: memset(clk_setup, 0, sizeof(clk_setup)); ! 211: env = ppc440_init_xilinx(&ram_size, 1, cpu_model, &clk_setup[0], ! 212: &clk_setup[1], 400000000); ! 213: qemu_register_reset(main_cpu_reset, env); ! 214: ! 215: phys_ram = qemu_ram_alloc(NULL, "ram", ram_size); ! 216: cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM); ! 217: ! 218: phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE); ! 219: dinfo = drive_get(IF_PFLASH, 0, 0); ! 220: pflash_cfi01_register(0xfc000000, phys_flash, ! 221: dinfo ? dinfo->bdrv : NULL, (64 * 1024), ! 222: FLASH_SIZE >> 16, ! 223: 1, 0x89, 0x18, 0x0000, 0x0, 1); ! 224: ! 225: cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT]; ! 226: dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0); ! 227: for (i = 0; i < 32; i++) { ! 228: irq[i] = qdev_get_gpio_in(dev, i); ! 229: } ! 230: ! 231: serial_mm_init(0x83e01003ULL, 2, irq[9], 115200, serial_hds[0], 1, 0); ! 232: ! 233: /* 2 timers at irq 2 @ 62 Mhz. */ ! 234: xilinx_timer_create(0x83c00000, irq[3], 2, 62 * 1000000); ! 235: ! 236: if (kernel_filename) { ! 237: uint64_t entry, low, high; ! 238: target_phys_addr_t boot_offset; ! 239: ! 240: /* Boots a kernel elf binary. */ ! 241: kernel_size = load_elf(kernel_filename, NULL, NULL, ! 242: &entry, &low, &high, 1, ELF_MACHINE, 0); ! 243: boot_info.bootstrap_pc = entry & 0x00ffffff; ! 244: ! 245: if (kernel_size < 0) { ! 246: boot_offset = 0x1200000; ! 247: /* If we failed loading ELF's try a raw image. */ ! 248: kernel_size = load_image_targphys(kernel_filename, ! 249: boot_offset, ! 250: ram_size); ! 251: boot_info.bootstrap_pc = boot_offset; ! 252: high = boot_info.bootstrap_pc + kernel_size + 8192; ! 253: } ! 254: ! 255: boot_info.ima_size = kernel_size; ! 256: ! 257: /* Provide a device-tree. */ ! 258: boot_info.fdt = high + (8192 * 2); ! 259: boot_info.fdt &= ~8191; ! 260: xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline); ! 261: } ! 262: env->load_info = &boot_info; ! 263: } ! 264: ! 265: static QEMUMachine virtex_machine = { ! 266: .name = "virtex-ml507", ! 267: .desc = "Xilinx Virtex ML507 reference design", ! 268: .init = virtex_init, ! 269: }; ! 270: ! 271: static void virtex_machine_init(void) ! 272: { ! 273: qemu_register_machine(&virtex_machine); ! 274: } ! 275: ! 276: machine_init(virtex_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.