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