|
|
1.1.1.4 ! root 1: /* 1.1 root 2: * ARM Versatile Platform/Application Baseboard System emulation. 3: * 1.1.1.4 ! root 4: * Copyright (c) 2005-2007 CodeSourcery. 1.1 root 5: * Written by Paul Brook 6: * 7: * This code is licenced under the GPL. 8: */ 9: 1.1.1.4 ! root 10: #include "hw.h" ! 11: #include "arm-misc.h" ! 12: #include "primecell.h" ! 13: #include "devices.h" ! 14: #include "net.h" ! 15: #include "sysemu.h" ! 16: #include "pci.h" ! 17: #include "boards.h" 1.1 root 18: 19: /* Primary interrupt controller. */ 20: 21: typedef struct vpb_sic_state 22: { 23: uint32_t base; 24: uint32_t level; 25: uint32_t mask; 26: uint32_t pic_enable; 1.1.1.4 ! root 27: qemu_irq *parent; 1.1 root 28: int irq; 29: } vpb_sic_state; 30: 31: static void vpb_sic_update(vpb_sic_state *s) 32: { 33: uint32_t flags; 34: 35: flags = s->level & s->mask; 1.1.1.4 ! root 36: qemu_set_irq(s->parent[s->irq], flags != 0); 1.1 root 37: } 38: 39: static void vpb_sic_update_pic(vpb_sic_state *s) 40: { 41: int i; 42: uint32_t mask; 43: 44: for (i = 21; i <= 30; i++) { 45: mask = 1u << i; 46: if (!(s->pic_enable & mask)) 47: continue; 1.1.1.4 ! root 48: qemu_set_irq(s->parent[i], (s->level & mask) != 0); 1.1 root 49: } 50: } 51: 52: static void vpb_sic_set_irq(void *opaque, int irq, int level) 53: { 54: vpb_sic_state *s = (vpb_sic_state *)opaque; 55: if (level) 56: s->level |= 1u << irq; 57: else 58: s->level &= ~(1u << irq); 59: if (s->pic_enable & (1u << irq)) 1.1.1.4 ! root 60: qemu_set_irq(s->parent[irq], level); 1.1 root 61: vpb_sic_update(s); 62: } 63: 64: static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset) 65: { 66: vpb_sic_state *s = (vpb_sic_state *)opaque; 67: 68: offset -= s->base; 69: switch (offset >> 2) { 70: case 0: /* STATUS */ 71: return s->level & s->mask; 72: case 1: /* RAWSTAT */ 73: return s->level; 74: case 2: /* ENABLE */ 75: return s->mask; 76: case 4: /* SOFTINT */ 77: return s->level & 1; 78: case 8: /* PICENABLE */ 79: return s->pic_enable; 80: default: 1.1.1.3 root 81: printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset); 1.1 root 82: return 0; 83: } 84: } 85: 86: static void vpb_sic_write(void *opaque, target_phys_addr_t offset, 87: uint32_t value) 88: { 89: vpb_sic_state *s = (vpb_sic_state *)opaque; 90: offset -= s->base; 91: 92: switch (offset >> 2) { 93: case 2: /* ENSET */ 94: s->mask |= value; 95: break; 96: case 3: /* ENCLR */ 97: s->mask &= ~value; 98: break; 99: case 4: /* SOFTINTSET */ 100: if (value) 101: s->mask |= 1; 102: break; 103: case 5: /* SOFTINTCLR */ 104: if (value) 105: s->mask &= ~1u; 106: break; 107: case 8: /* PICENSET */ 108: s->pic_enable |= (value & 0x7fe00000); 109: vpb_sic_update_pic(s); 110: break; 111: case 9: /* PICENCLR */ 112: s->pic_enable &= ~value; 113: vpb_sic_update_pic(s); 114: break; 115: default: 1.1.1.3 root 116: printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset); 1.1 root 117: return; 118: } 119: vpb_sic_update(s); 120: } 121: 122: static CPUReadMemoryFunc *vpb_sic_readfn[] = { 123: vpb_sic_read, 124: vpb_sic_read, 125: vpb_sic_read 126: }; 127: 128: static CPUWriteMemoryFunc *vpb_sic_writefn[] = { 129: vpb_sic_write, 130: vpb_sic_write, 131: vpb_sic_write 132: }; 133: 1.1.1.4 ! root 134: static qemu_irq *vpb_sic_init(uint32_t base, qemu_irq *parent, int irq) 1.1 root 135: { 136: vpb_sic_state *s; 1.1.1.4 ! root 137: qemu_irq *qi; 1.1 root 138: int iomemtype; 139: 140: s = (vpb_sic_state *)qemu_mallocz(sizeof(vpb_sic_state)); 141: if (!s) 142: return NULL; 1.1.1.4 ! root 143: qi = qemu_allocate_irqs(vpb_sic_set_irq, s, 32); 1.1 root 144: s->base = base; 145: s->parent = parent; 146: s->irq = irq; 147: iomemtype = cpu_register_io_memory(0, vpb_sic_readfn, 148: vpb_sic_writefn, s); 1.1.1.4 ! root 149: cpu_register_physical_memory(base, 0x00001000, iomemtype); 1.1 root 150: /* ??? Save/restore. */ 1.1.1.4 ! root 151: return qi; 1.1 root 152: } 153: 154: /* Board init. */ 155: 156: /* The AB and PB boards both use the same core, just with different 157: peripherans and expansion busses. For now we emulate a subset of the 158: PB peripherals and just change the board ID. */ 159: 1.1.1.4 ! root 160: static void versatile_init(int ram_size, int vga_ram_size, ! 161: const char *boot_device, DisplayState *ds, 1.1 root 162: const char *kernel_filename, const char *kernel_cmdline, 1.1.1.4 ! root 163: const char *initrd_filename, const char *cpu_model, ! 164: int board_id) 1.1 root 165: { 166: CPUState *env; 1.1.1.4 ! root 167: qemu_irq *pic; ! 168: qemu_irq *sic; 1.1.1.2 root 169: void *scsi_hba; 170: PCIBus *pci_bus; 171: NICInfo *nd; 172: int n; 173: int done_smc = 0; 1.1.1.4 ! root 174: int index; 1.1 root 175: 1.1.1.4 ! root 176: if (!cpu_model) ! 177: cpu_model = "arm926"; ! 178: env = cpu_init(cpu_model); ! 179: if (!env) { ! 180: fprintf(stderr, "Unable to find CPU definition\n"); ! 181: exit(1); ! 182: } 1.1 root 183: /* ??? RAM shoud repeat to fill physical memory space. */ 184: /* SDRAM at address zero. */ 185: cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); 186: 1.1.1.3 root 187: arm_sysctl_init(0x10000000, 0x41007004); 1.1 root 188: pic = arm_pic_init_cpu(env); 1.1.1.4 ! root 189: pic = pl190_init(0x10140000, pic[0], pic[1]); 1.1 root 190: sic = vpb_sic_init(0x10003000, pic, 31); 1.1.1.4 ! root 191: pl050_init(0x10006000, sic[3], 0); ! 192: pl050_init(0x10007000, sic[4], 1); 1.1 root 193: 1.1.1.3 root 194: pci_bus = pci_vpb_init(sic, 27, 0); 1.1.1.2 root 195: /* The Versatile PCI bridge does not provide access to PCI IO space, 196: so many of the qemu PCI devices are not useable. */ 197: for(n = 0; n < nb_nics; n++) { 198: nd = &nd_table[n]; 199: if (!nd->model) 200: nd->model = done_smc ? "rtl8139" : "smc91c111"; 201: if (strcmp(nd->model, "smc91c111") == 0) { 1.1.1.4 ! root 202: smc91c111_init(nd, 0x10010000, sic[25]); 1.1 root 203: } else { 1.1.1.3 root 204: pci_nic_init(pci_bus, nd, -1); 1.1.1.2 root 205: } 206: } 207: if (usb_enabled) { 1.1.1.4 ! root 208: usb_ohci_init_pci(pci_bus, 3, -1); ! 209: } ! 210: if (drive_get_max_bus(IF_SCSI) > 0) { ! 211: fprintf(stderr, "qemu: too many SCSI bus\n"); ! 212: exit(1); 1.1.1.2 root 213: } 214: scsi_hba = lsi_scsi_init(pci_bus, -1); 1.1.1.4 ! root 215: for (n = 0; n < LSI_MAX_DEVS; n++) { ! 216: index = drive_get_index(IF_SCSI, 0, n); ! 217: if (index == -1) ! 218: continue; ! 219: lsi_scsi_attach(scsi_hba, drives_table[index].bdrv, n); 1.1 root 220: } 221: 1.1.1.4 ! root 222: pl011_init(0x101f1000, pic[12], serial_hds[0], PL011_ARM); ! 223: pl011_init(0x101f2000, pic[13], serial_hds[1], PL011_ARM); ! 224: pl011_init(0x101f3000, pic[14], serial_hds[2], PL011_ARM); ! 225: pl011_init(0x10009000, sic[6], serial_hds[3], PL011_ARM); ! 226: ! 227: pl080_init(0x10130000, pic[17], 8); ! 228: sp804_init(0x101e2000, pic[4]); ! 229: sp804_init(0x101e3000, pic[5]); 1.1 root 230: 231: /* The versatile/PB actually has a modified Color LCD controller 232: that includes hardware cursor support from the PL111. */ 1.1.1.4 ! root 233: pl110_init(ds, 0x10120000, pic[16], 1); ! 234: ! 235: index = drive_get_index(IF_SD, 0, 0); ! 236: if (index == -1) { ! 237: fprintf(stderr, "qemu: missing SecureDigital card\n"); ! 238: exit(1); ! 239: } ! 240: ! 241: pl181_init(0x10005000, drives_table[index].bdrv, sic[22], sic[1]); ! 242: #if 0 ! 243: /* Disabled because there's no way of specifying a block device. */ ! 244: pl181_init(0x1000b000, NULL, sic, 23, 2); ! 245: #endif ! 246: ! 247: /* Add PL031 Real Time Clock. */ ! 248: pl031_init(0x101e8000,pic[10]); 1.1 root 249: 250: /* Memory map for Versatile/PB: */ 251: /* 0x10000000 System registers. */ 252: /* 0x10001000 PCI controller config registers. */ 253: /* 0x10002000 Serial bus interface. */ 254: /* 0x10003000 Secondary interrupt controller. */ 255: /* 0x10004000 AACI (audio). */ 1.1.1.4 ! root 256: /* 0x10005000 MMCI0. */ 1.1 root 257: /* 0x10006000 KMI0 (keyboard). */ 258: /* 0x10007000 KMI1 (mouse). */ 259: /* 0x10008000 Character LCD Interface. */ 260: /* 0x10009000 UART3. */ 261: /* 0x1000a000 Smart card 1. */ 1.1.1.4 ! root 262: /* 0x1000b000 MMCI1. */ 1.1 root 263: /* 0x10010000 Ethernet. */ 264: /* 0x10020000 USB. */ 265: /* 0x10100000 SSMC. */ 266: /* 0x10110000 MPMC. */ 267: /* 0x10120000 CLCD Controller. */ 268: /* 0x10130000 DMA Controller. */ 269: /* 0x10140000 Vectored interrupt controller. */ 270: /* 0x101d0000 AHB Monitor Interface. */ 271: /* 0x101e0000 System Controller. */ 272: /* 0x101e1000 Watchdog Interface. */ 273: /* 0x101e2000 Timer 0/1. */ 274: /* 0x101e3000 Timer 2/3. */ 275: /* 0x101e4000 GPIO port 0. */ 276: /* 0x101e5000 GPIO port 1. */ 277: /* 0x101e6000 GPIO port 2. */ 278: /* 0x101e7000 GPIO port 3. */ 279: /* 0x101e8000 RTC. */ 280: /* 0x101f0000 Smart card 0. */ 281: /* 0x101f1000 UART0. */ 282: /* 0x101f2000 UART1. */ 283: /* 0x101f3000 UART2. */ 284: /* 0x101f4000 SSPI. */ 285: 1.1.1.3 root 286: arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline, 1.1.1.4 ! root 287: initrd_filename, board_id, 0x0); 1.1 root 288: } 289: 1.1.1.4 ! root 290: static void vpb_init(int ram_size, int vga_ram_size, ! 291: const char *boot_device, DisplayState *ds, 1.1 root 292: const char *kernel_filename, const char *kernel_cmdline, 1.1.1.4 ! root 293: const char *initrd_filename, const char *cpu_model) 1.1 root 294: { 1.1.1.4 ! root 295: versatile_init(ram_size, vga_ram_size, ! 296: boot_device, ds, 1.1 root 297: kernel_filename, kernel_cmdline, 1.1.1.4 ! root 298: initrd_filename, cpu_model, 0x183); 1.1 root 299: } 300: 1.1.1.4 ! root 301: static void vab_init(int ram_size, int vga_ram_size, ! 302: const char *boot_device, DisplayState *ds, 1.1 root 303: const char *kernel_filename, const char *kernel_cmdline, 1.1.1.4 ! root 304: const char *initrd_filename, const char *cpu_model) 1.1 root 305: { 1.1.1.4 ! root 306: versatile_init(ram_size, vga_ram_size, ! 307: boot_device, ds, 1.1 root 308: kernel_filename, kernel_cmdline, 1.1.1.4 ! root 309: initrd_filename, cpu_model, 0x25e); 1.1 root 310: } 311: 312: QEMUMachine versatilepb_machine = { 313: "versatilepb", 314: "ARM Versatile/PB (ARM926EJ-S)", 315: vpb_init, 316: }; 317: 318: QEMUMachine versatileab_machine = { 319: "versatileab", 320: "ARM Versatile/AB (ARM926EJ-S)", 321: vab_init, 322: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.