|
|
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.6 ! root 10: #include "sysbus.h"
1.1.1.4 root 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: {
1.1.1.6 ! root 23: SysBusDevice busdev;
1.1 root 24: uint32_t level;
25: uint32_t mask;
26: uint32_t pic_enable;
1.1.1.6 ! root 27: qemu_irq parent[32];
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: switch (offset >> 2) {
69: case 0: /* STATUS */
70: return s->level & s->mask;
71: case 1: /* RAWSTAT */
72: return s->level;
73: case 2: /* ENABLE */
74: return s->mask;
75: case 4: /* SOFTINT */
76: return s->level & 1;
77: case 8: /* PICENABLE */
78: return s->pic_enable;
79: default:
1.1.1.3 root 80: printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
1.1 root 81: return 0;
82: }
83: }
84:
85: static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
86: uint32_t value)
87: {
88: vpb_sic_state *s = (vpb_sic_state *)opaque;
89:
90: switch (offset >> 2) {
91: case 2: /* ENSET */
92: s->mask |= value;
93: break;
94: case 3: /* ENCLR */
95: s->mask &= ~value;
96: break;
97: case 4: /* SOFTINTSET */
98: if (value)
99: s->mask |= 1;
100: break;
101: case 5: /* SOFTINTCLR */
102: if (value)
103: s->mask &= ~1u;
104: break;
105: case 8: /* PICENSET */
106: s->pic_enable |= (value & 0x7fe00000);
107: vpb_sic_update_pic(s);
108: break;
109: case 9: /* PICENCLR */
110: s->pic_enable &= ~value;
111: vpb_sic_update_pic(s);
112: break;
113: default:
1.1.1.3 root 114: printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
1.1 root 115: return;
116: }
117: vpb_sic_update(s);
118: }
119:
120: static CPUReadMemoryFunc *vpb_sic_readfn[] = {
121: vpb_sic_read,
122: vpb_sic_read,
123: vpb_sic_read
124: };
125:
126: static CPUWriteMemoryFunc *vpb_sic_writefn[] = {
127: vpb_sic_write,
128: vpb_sic_write,
129: vpb_sic_write
130: };
131:
1.1.1.6 ! root 132: static void vpb_sic_init(SysBusDevice *dev)
1.1 root 133: {
1.1.1.6 ! root 134: vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
1.1 root 135: int iomemtype;
1.1.1.6 ! root 136: int i;
1.1 root 137:
1.1.1.6 ! root 138: qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
! 139: for (i = 0; i < 32; i++) {
! 140: sysbus_init_irq(dev, &s->parent[i]);
! 141: }
! 142: s->irq = 31;
! 143: iomemtype = cpu_register_io_memory(vpb_sic_readfn,
1.1 root 144: vpb_sic_writefn, s);
1.1.1.6 ! root 145: sysbus_init_mmio(dev, 0x1000, iomemtype);
1.1 root 146: /* ??? Save/restore. */
147: }
148:
149: /* Board init. */
150:
151: /* The AB and PB boards both use the same core, just with different
152: peripherans and expansion busses. For now we emulate a subset of the
153: PB peripherals and just change the board ID. */
154:
1.1.1.5 root 155: static struct arm_boot_info versatile_binfo;
156:
1.1.1.6 ! root 157: static void versatile_init(ram_addr_t ram_size,
1.1.1.5 root 158: const char *boot_device,
1.1 root 159: const char *kernel_filename, const char *kernel_cmdline,
1.1.1.4 root 160: const char *initrd_filename, const char *cpu_model,
161: int board_id)
1.1 root 162: {
163: CPUState *env;
1.1.1.6 ! root 164: ram_addr_t ram_offset;
! 165: qemu_irq *cpu_pic;
! 166: qemu_irq pic[32];
! 167: qemu_irq sic[32];
! 168: DeviceState *dev;
1.1.1.2 root 169: PCIBus *pci_bus;
170: NICInfo *nd;
171: int n;
172: int done_smc = 0;
1.1 root 173:
1.1.1.4 root 174: if (!cpu_model)
175: cpu_model = "arm926";
176: env = cpu_init(cpu_model);
177: if (!env) {
178: fprintf(stderr, "Unable to find CPU definition\n");
179: exit(1);
180: }
1.1.1.6 ! root 181: ram_offset = qemu_ram_alloc(ram_size);
1.1.1.5 root 182: /* ??? RAM should repeat to fill physical memory space. */
1.1 root 183: /* SDRAM at address zero. */
1.1.1.6 ! root 184: cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
1.1 root 185:
1.1.1.3 root 186: arm_sysctl_init(0x10000000, 0x41007004);
1.1.1.6 ! root 187: cpu_pic = arm_pic_init_cpu(env);
! 188: dev = sysbus_create_varargs("pl190", 0x10140000,
! 189: cpu_pic[0], cpu_pic[1], NULL);
! 190: for (n = 0; n < 32; n++) {
! 191: pic[n] = qdev_get_gpio_in(dev, n);
! 192: }
! 193: dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
! 194: for (n = 0; n < 32; n++) {
! 195: sysbus_connect_irq(sysbus_from_qdev(dev), n, pic[n]);
! 196: sic[n] = qdev_get_gpio_in(dev, n);
! 197: }
! 198:
! 199: sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
! 200: sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
! 201:
! 202: dev = sysbus_create_varargs("versatile_pci", 0x40000000,
! 203: sic[27], sic[28], sic[29], sic[30], NULL);
! 204: pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
1.1 root 205:
1.1.1.2 root 206: /* The Versatile PCI bridge does not provide access to PCI IO space,
207: so many of the qemu PCI devices are not useable. */
208: for(n = 0; n < nb_nics; n++) {
209: nd = &nd_table[n];
1.1.1.5 root 210:
211: if ((!nd->model && !done_smc) || strcmp(nd->model, "smc91c111") == 0) {
1.1.1.4 root 212: smc91c111_init(nd, 0x10010000, sic[25]);
1.1.1.5 root 213: done_smc = 1;
1.1 root 214: } else {
1.1.1.6 ! root 215: pci_nic_init(nd, "rtl8139", NULL);
1.1.1.2 root 216: }
217: }
218: if (usb_enabled) {
1.1.1.4 root 219: usb_ohci_init_pci(pci_bus, 3, -1);
220: }
1.1.1.6 ! root 221: n = drive_get_max_bus(IF_SCSI);
! 222: while (n >= 0) {
! 223: pci_create_simple(pci_bus, -1, "lsi53c895a");
! 224: n--;
1.1 root 225: }
226:
1.1.1.6 ! root 227: sysbus_create_simple("pl011", 0x101f1000, pic[12]);
! 228: sysbus_create_simple("pl011", 0x101f2000, pic[13]);
! 229: sysbus_create_simple("pl011", 0x101f3000, pic[14]);
! 230: sysbus_create_simple("pl011", 0x10009000, sic[6]);
! 231:
! 232: sysbus_create_simple("pl080", 0x10130000, pic[17]);
! 233: sysbus_create_simple("sp804", 0x101e2000, pic[4]);
! 234: sysbus_create_simple("sp804", 0x101e3000, pic[5]);
1.1 root 235:
236: /* The versatile/PB actually has a modified Color LCD controller
237: that includes hardware cursor support from the PL111. */
1.1.1.6 ! root 238: sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
1.1.1.4 root 239:
1.1.1.6 ! root 240: sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
! 241: sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
1.1.1.4 root 242:
243: /* Add PL031 Real Time Clock. */
1.1.1.6 ! root 244: sysbus_create_simple("pl031", 0x101e8000, pic[10]);
1.1 root 245:
246: /* Memory map for Versatile/PB: */
247: /* 0x10000000 System registers. */
248: /* 0x10001000 PCI controller config registers. */
249: /* 0x10002000 Serial bus interface. */
250: /* 0x10003000 Secondary interrupt controller. */
251: /* 0x10004000 AACI (audio). */
1.1.1.4 root 252: /* 0x10005000 MMCI0. */
1.1 root 253: /* 0x10006000 KMI0 (keyboard). */
254: /* 0x10007000 KMI1 (mouse). */
255: /* 0x10008000 Character LCD Interface. */
256: /* 0x10009000 UART3. */
257: /* 0x1000a000 Smart card 1. */
1.1.1.4 root 258: /* 0x1000b000 MMCI1. */
1.1 root 259: /* 0x10010000 Ethernet. */
260: /* 0x10020000 USB. */
261: /* 0x10100000 SSMC. */
262: /* 0x10110000 MPMC. */
263: /* 0x10120000 CLCD Controller. */
264: /* 0x10130000 DMA Controller. */
265: /* 0x10140000 Vectored interrupt controller. */
266: /* 0x101d0000 AHB Monitor Interface. */
267: /* 0x101e0000 System Controller. */
268: /* 0x101e1000 Watchdog Interface. */
269: /* 0x101e2000 Timer 0/1. */
270: /* 0x101e3000 Timer 2/3. */
271: /* 0x101e4000 GPIO port 0. */
272: /* 0x101e5000 GPIO port 1. */
273: /* 0x101e6000 GPIO port 2. */
274: /* 0x101e7000 GPIO port 3. */
275: /* 0x101e8000 RTC. */
276: /* 0x101f0000 Smart card 0. */
277: /* 0x101f1000 UART0. */
278: /* 0x101f2000 UART1. */
279: /* 0x101f3000 UART2. */
280: /* 0x101f4000 SSPI. */
281:
1.1.1.5 root 282: versatile_binfo.ram_size = ram_size;
283: versatile_binfo.kernel_filename = kernel_filename;
284: versatile_binfo.kernel_cmdline = kernel_cmdline;
285: versatile_binfo.initrd_filename = initrd_filename;
286: versatile_binfo.board_id = board_id;
287: arm_load_kernel(env, &versatile_binfo);
1.1 root 288: }
289:
1.1.1.6 ! root 290: static void vpb_init(ram_addr_t ram_size,
1.1.1.5 root 291: const char *boot_device,
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.6 ! root 295: versatile_init(ram_size,
1.1.1.5 root 296: boot_device,
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.6 ! root 301: static void vab_init(ram_addr_t ram_size,
1.1.1.5 root 302: const char *boot_device,
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.6 ! root 306: versatile_init(ram_size,
1.1.1.5 root 307: boot_device,
1.1 root 308: kernel_filename, kernel_cmdline,
1.1.1.4 root 309: initrd_filename, cpu_model, 0x25e);
1.1 root 310: }
311:
1.1.1.6 ! root 312: static QEMUMachine versatilepb_machine = {
1.1.1.5 root 313: .name = "versatilepb",
314: .desc = "ARM Versatile/PB (ARM926EJ-S)",
315: .init = vpb_init,
316: .use_scsi = 1,
1.1 root 317: };
318:
1.1.1.6 ! root 319: static QEMUMachine versatileab_machine = {
1.1.1.5 root 320: .name = "versatileab",
321: .desc = "ARM Versatile/AB (ARM926EJ-S)",
322: .init = vab_init,
323: .use_scsi = 1,
1.1 root 324: };
1.1.1.6 ! root 325:
! 326: static void versatile_machine_init(void)
! 327: {
! 328: qemu_register_machine(&versatilepb_machine);
! 329: qemu_register_machine(&versatileab_machine);
! 330: }
! 331:
! 332: machine_init(versatile_machine_init);
! 333:
! 334: static void versatilepb_register_devices(void)
! 335: {
! 336: sysbus_register_dev("versatilepb_sic", sizeof(vpb_sic_state),
! 337: vpb_sic_init);
! 338: }
! 339:
! 340: device_init(versatilepb_register_devices)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.