|
|
1.1 ! root 1: /* ! 2: * ARM Versatile Express emulation. ! 3: * ! 4: * Copyright (c) 2010 - 2011 B Labs Ltd. ! 5: * Copyright (c) 2011 Linaro Limited ! 6: * Written by Bahadir Balban, Amit Mahajan, Peter Maydell ! 7: * ! 8: * This program is free software; you can redistribute it and/or modify ! 9: * it under the terms of the GNU General Public License version 2 as ! 10: * published by the Free Software Foundation. ! 11: * ! 12: * This program is distributed in the hope that it will be useful, ! 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: * GNU General Public License for more details. ! 16: * ! 17: * You should have received a copy of the GNU General Public License along ! 18: * with this program; if not, see <http://www.gnu.org/licenses/>. ! 19: */ ! 20: ! 21: #include "sysbus.h" ! 22: #include "arm-misc.h" ! 23: #include "primecell.h" ! 24: #include "devices.h" ! 25: #include "net.h" ! 26: #include "sysemu.h" ! 27: #include "boards.h" ! 28: ! 29: #define SMP_BOOT_ADDR 0xe0000000 ! 30: ! 31: #define VEXPRESS_BOARD_ID 0x8e0 ! 32: ! 33: static struct arm_boot_info vexpress_binfo = { ! 34: .smp_loader_start = SMP_BOOT_ADDR, ! 35: }; ! 36: ! 37: static void vexpress_a9_init(ram_addr_t ram_size, ! 38: const char *boot_device, ! 39: const char *kernel_filename, const char *kernel_cmdline, ! 40: const char *initrd_filename, const char *cpu_model) ! 41: { ! 42: CPUState *env = NULL; ! 43: ram_addr_t ram_offset, vram_offset, sram_offset; ! 44: DeviceState *dev, *sysctl; ! 45: SysBusDevice *busdev; ! 46: qemu_irq *irqp; ! 47: qemu_irq pic[64]; ! 48: int n; ! 49: qemu_irq cpu_irq[4]; ! 50: uint32_t proc_id; ! 51: uint32_t sys_id; ! 52: ram_addr_t low_ram_size, vram_size, sram_size; ! 53: ! 54: if (!cpu_model) { ! 55: cpu_model = "cortex-a9"; ! 56: } ! 57: ! 58: for (n = 0; n < smp_cpus; n++) { ! 59: env = cpu_init(cpu_model); ! 60: if (!env) { ! 61: fprintf(stderr, "Unable to find CPU definition\n"); ! 62: exit(1); ! 63: } ! 64: irqp = arm_pic_init_cpu(env); ! 65: cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; ! 66: } ! 67: ! 68: if (ram_size > 0x40000000) { ! 69: /* 1GB is the maximum the address space permits */ ! 70: fprintf(stderr, "vexpress: cannot model more than 1GB RAM\n"); ! 71: exit(1); ! 72: } ! 73: ! 74: ram_offset = qemu_ram_alloc(NULL, "vexpress.highmem", ram_size); ! 75: low_ram_size = ram_size; ! 76: if (low_ram_size > 0x4000000) { ! 77: low_ram_size = 0x4000000; ! 78: } ! 79: /* RAM is from 0x60000000 upwards. The bottom 64MB of the ! 80: * address space should in theory be remappable to various ! 81: * things including ROM or RAM; we always map the RAM there. ! 82: */ ! 83: cpu_register_physical_memory(0x0, low_ram_size, ram_offset | IO_MEM_RAM); ! 84: cpu_register_physical_memory(0x60000000, ram_size, ! 85: ram_offset | IO_MEM_RAM); ! 86: ! 87: /* 0x1e000000 A9MPCore (SCU) private memory region */ ! 88: dev = qdev_create(NULL, "a9mpcore_priv"); ! 89: qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); ! 90: qdev_init_nofail(dev); ! 91: busdev = sysbus_from_qdev(dev); ! 92: vexpress_binfo.smp_priv_base = 0x1e000000; ! 93: sysbus_mmio_map(busdev, 0, vexpress_binfo.smp_priv_base); ! 94: for (n = 0; n < smp_cpus; n++) { ! 95: sysbus_connect_irq(busdev, n, cpu_irq[n]); ! 96: } ! 97: /* Interrupts [42:0] are from the motherboard; ! 98: * [47:43] are reserved; [63:48] are daughterboard ! 99: * peripherals. Note that some documentation numbers ! 100: * external interrupts starting from 32 (because the ! 101: * A9MP has internal interrupts 0..31). ! 102: */ ! 103: for (n = 0; n < 64; n++) { ! 104: pic[n] = qdev_get_gpio_in(dev, n); ! 105: } ! 106: ! 107: /* Motherboard peripherals CS7 : 0x10000000 .. 0x10020000 */ ! 108: sys_id = 0x1190f500; ! 109: proc_id = 0x0c000191; ! 110: ! 111: /* 0x10000000 System registers */ ! 112: sysctl = qdev_create(NULL, "realview_sysctl"); ! 113: qdev_prop_set_uint32(sysctl, "sys_id", sys_id); ! 114: qdev_init_nofail(sysctl); ! 115: qdev_prop_set_uint32(sysctl, "proc_id", proc_id); ! 116: sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000); ! 117: ! 118: /* 0x10001000 SP810 system control */ ! 119: /* 0x10002000 serial bus PCI */ ! 120: /* 0x10004000 PL041 audio */ ! 121: ! 122: dev = sysbus_create_varargs("pl181", 0x10005000, pic[9], pic[10], NULL); ! 123: /* Wire up MMC card detect and read-only signals */ ! 124: qdev_connect_gpio_out(dev, 0, ! 125: qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT)); ! 126: qdev_connect_gpio_out(dev, 1, ! 127: qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN)); ! 128: ! 129: sysbus_create_simple("pl050_keyboard", 0x10006000, pic[12]); ! 130: sysbus_create_simple("pl050_mouse", 0x10007000, pic[13]); ! 131: ! 132: sysbus_create_simple("pl011", 0x10009000, pic[5]); ! 133: sysbus_create_simple("pl011", 0x1000a000, pic[6]); ! 134: sysbus_create_simple("pl011", 0x1000b000, pic[7]); ! 135: sysbus_create_simple("pl011", 0x1000c000, pic[8]); ! 136: ! 137: /* 0x1000f000 SP805 WDT */ ! 138: ! 139: sysbus_create_simple("sp804", 0x10011000, pic[2]); ! 140: sysbus_create_simple("sp804", 0x10012000, pic[3]); ! 141: ! 142: /* 0x10016000 Serial Bus DVI */ ! 143: ! 144: sysbus_create_simple("pl031", 0x10017000, pic[4]); /* RTC */ ! 145: ! 146: /* 0x1001a000 Compact Flash */ ! 147: ! 148: /* 0x1001f000 PL111 CLCD (motherboard) */ ! 149: ! 150: /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */ ! 151: ! 152: /* 0x10020000 PL111 CLCD (daughterboard) */ ! 153: sysbus_create_simple("pl110", 0x10020000, pic[44]); ! 154: ! 155: /* 0x10060000 AXI RAM */ ! 156: /* 0x100e0000 PL341 Dynamic Memory Controller */ ! 157: /* 0x100e1000 PL354 Static Memory Controller */ ! 158: /* 0x100e2000 System Configuration Controller */ ! 159: ! 160: sysbus_create_simple("sp804", 0x100e4000, pic[48]); ! 161: /* 0x100e5000 SP805 Watchdog module */ ! 162: /* 0x100e6000 BP147 TrustZone Protection Controller */ ! 163: /* 0x100e9000 PL301 'Fast' AXI matrix */ ! 164: /* 0x100ea000 PL301 'Slow' AXI matrix */ ! 165: /* 0x100ec000 TrustZone Address Space Controller */ ! 166: /* 0x10200000 CoreSight debug APB */ ! 167: /* 0x1e00a000 PL310 L2 Cache Controller */ ! 168: ! 169: /* CS0: NOR0 flash : 0x40000000 .. 0x44000000 */ ! 170: /* CS4: NOR1 flash : 0x44000000 .. 0x48000000 */ ! 171: /* CS2: SRAM : 0x48000000 .. 0x4a000000 */ ! 172: sram_size = 0x2000000; ! 173: sram_offset = qemu_ram_alloc(NULL, "vexpress.sram", sram_size); ! 174: cpu_register_physical_memory(0x48000000, sram_size, ! 175: sram_offset | IO_MEM_RAM); ! 176: ! 177: /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */ ! 178: ! 179: /* 0x4c000000 Video RAM */ ! 180: vram_size = 0x800000; ! 181: vram_offset = qemu_ram_alloc(NULL, "vexpress.vram", vram_size); ! 182: cpu_register_physical_memory(0x4c000000, vram_size, ! 183: vram_offset | IO_MEM_RAM); ! 184: ! 185: /* 0x4e000000 LAN9118 Ethernet */ ! 186: if (nd_table[0].vlan) { ! 187: lan9118_init(&nd_table[0], 0x4e000000, pic[15]); ! 188: } ! 189: ! 190: /* 0x4f000000 ISP1761 USB */ ! 191: ! 192: /* ??? Hack to map an additional page of ram for the secondary CPU ! 193: startup code. I guess this works on real hardware because the ! 194: BootROM happens to be in ROM/flash or in memory that isn't clobbered ! 195: until after Linux boots the secondary CPUs. */ ! 196: ram_offset = qemu_ram_alloc(NULL, "vexpress.hack", 0x1000); ! 197: cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000, ! 198: ram_offset | IO_MEM_RAM); ! 199: ! 200: vexpress_binfo.ram_size = ram_size; ! 201: vexpress_binfo.kernel_filename = kernel_filename; ! 202: vexpress_binfo.kernel_cmdline = kernel_cmdline; ! 203: vexpress_binfo.initrd_filename = initrd_filename; ! 204: vexpress_binfo.nb_cpus = smp_cpus; ! 205: vexpress_binfo.board_id = VEXPRESS_BOARD_ID; ! 206: vexpress_binfo.loader_start = 0x60000000; ! 207: arm_load_kernel(first_cpu, &vexpress_binfo); ! 208: } ! 209: ! 210: ! 211: static QEMUMachine vexpress_a9_machine = { ! 212: .name = "vexpress-a9", ! 213: .desc = "ARM Versatile Express for Cortex-A9", ! 214: .init = vexpress_a9_init, ! 215: .use_scsi = 1, ! 216: .max_cpus = 4, ! 217: }; ! 218: ! 219: static void vexpress_machine_init(void) ! 220: { ! 221: qemu_register_machine(&vexpress_a9_machine); ! 222: } ! 223: ! 224: machine_init(vexpress_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.