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