|
|
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:
76: printf ("vpb_sic_read: Bad register offset 0x%x\n", offset);
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:
111: printf ("vpb_sic_write: Bad register offset 0x%x\n", offset);
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;
162:
163: env = cpu_init();
164: cpu_arm_set_model(env, ARM_CPUID_ARM926);
165: /* ??? RAM shoud repeat to fill physical memory space. */
166: /* SDRAM at address zero. */
167: cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
168:
169: pic = arm_pic_init_cpu(env);
170: pic = pl190_init(0x10140000, pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
171: sic = vpb_sic_init(0x10003000, pic, 31);
172: pl050_init(0x10006000, sic, 3, 0);
173: pl050_init(0x10007000, sic, 4, 1);
174:
175: /* TODO: Init PCI NICs. */
176: if (nd_table[0].vlan) {
177: if (nd_table[0].model == NULL
178: || strcmp(nd_table[0].model, "smc91c111") == 0) {
179: smc91c111_init(&nd_table[0], 0x10010000, sic, 25);
180: } else {
181: fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
182: exit (1);
183: }
184: }
185:
186: pl011_init(0x101f1000, pic, 12, serial_hds[0]);
187: pl011_init(0x101f2000, pic, 13, serial_hds[1]);
188: pl011_init(0x101f3000, pic, 14, serial_hds[2]);
189: pl011_init(0x10009000, sic, 6, serial_hds[3]);
190:
191: pl080_init(0x10130000, pic, 17);
192: sp804_init(0x101e2000, pic, 4);
193: sp804_init(0x101e3000, pic, 5);
194:
195: /* The versatile/PB actually has a modified Color LCD controller
196: that includes hardware cursor support from the PL111. */
197: pl110_init(ds, 0x10120000, pic, 16, 1);
198:
199: /* Memory map for Versatile/PB: */
200: /* 0x10000000 System registers. */
201: /* 0x10001000 PCI controller config registers. */
202: /* 0x10002000 Serial bus interface. */
203: /* 0x10003000 Secondary interrupt controller. */
204: /* 0x10004000 AACI (audio). */
205: /* 0x10005000 MMCI0. */
206: /* 0x10006000 KMI0 (keyboard). */
207: /* 0x10007000 KMI1 (mouse). */
208: /* 0x10008000 Character LCD Interface. */
209: /* 0x10009000 UART3. */
210: /* 0x1000a000 Smart card 1. */
211: /* 0x1000b000 MMCI1. */
212: /* 0x10010000 Ethernet. */
213: /* 0x10020000 USB. */
214: /* 0x10100000 SSMC. */
215: /* 0x10110000 MPMC. */
216: /* 0x10120000 CLCD Controller. */
217: /* 0x10130000 DMA Controller. */
218: /* 0x10140000 Vectored interrupt controller. */
219: /* 0x101d0000 AHB Monitor Interface. */
220: /* 0x101e0000 System Controller. */
221: /* 0x101e1000 Watchdog Interface. */
222: /* 0x101e2000 Timer 0/1. */
223: /* 0x101e3000 Timer 2/3. */
224: /* 0x101e4000 GPIO port 0. */
225: /* 0x101e5000 GPIO port 1. */
226: /* 0x101e6000 GPIO port 2. */
227: /* 0x101e7000 GPIO port 3. */
228: /* 0x101e8000 RTC. */
229: /* 0x101f0000 Smart card 0. */
230: /* 0x101f1000 UART0. */
231: /* 0x101f2000 UART1. */
232: /* 0x101f3000 UART2. */
233: /* 0x101f4000 SSPI. */
234:
235: arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
236: initrd_filename, board_id);
237: }
238:
239: static void vpb_init(int ram_size, int vga_ram_size, int boot_device,
240: DisplayState *ds, const char **fd_filename, int snapshot,
241: const char *kernel_filename, const char *kernel_cmdline,
242: const char *initrd_filename)
243: {
244: versatile_init(ram_size, vga_ram_size, boot_device,
245: ds, fd_filename, snapshot,
246: kernel_filename, kernel_cmdline,
247: initrd_filename, 0x183);
248: }
249:
250: static void vab_init(int ram_size, int vga_ram_size, int boot_device,
251: DisplayState *ds, const char **fd_filename, int snapshot,
252: const char *kernel_filename, const char *kernel_cmdline,
253: const char *initrd_filename)
254: {
255: versatile_init(ram_size, vga_ram_size, boot_device,
256: ds, fd_filename, snapshot,
257: kernel_filename, kernel_cmdline,
258: initrd_filename, 0x25e);
259: }
260:
261: QEMUMachine versatilepb_machine = {
262: "versatilepb",
263: "ARM Versatile/PB (ARM926EJ-S)",
264: vpb_init,
265: };
266:
267: QEMUMachine versatileab_machine = {
268: "versatileab",
269: "ARM Versatile/AB (ARM926EJ-S)",
270: vab_init,
271: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.