1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include "sysbus.h" |
11 | #include "arm-misc.h" |
12 | #include "primecell.h" |
13 | #include "devices.h" |
14 | #include "pci.h" |
15 | #include "net.h" |
16 | #include "sysemu.h" |
17 | #include "boards.h" |
18 | #include "i2c.h" |
19 | #include "blockdev.h" |
20 | #include "exec-memory.h" |
21 | |
22 | #define SMP_BOOT_ADDR0xe0000000 0xe0000000 |
23 | #define SMP_BOOTREG_ADDR0x10000030 0x10000030 |
24 | |
25 | |
26 | |
27 | static struct arm_boot_info realview_binfo = { |
28 | .smp_loader_start = SMP_BOOT_ADDR0xe0000000, |
29 | .smp_bootreg_addr = SMP_BOOTREG_ADDR0x10000030, |
30 | }; |
31 | |
32 | |
33 | enum realview_board_type { |
34 | BOARD_EB, |
35 | BOARD_EB_MPCORE, |
36 | BOARD_PB_A8, |
37 | BOARD_PBX_A9, |
38 | }; |
39 | |
40 | static const int realview_board_id[] = { |
41 | 0x33b, |
42 | 0x33b, |
43 | 0x769, |
44 | 0x76d |
45 | }; |
46 | |
47 | static void realview_init(ram_addr_t ram_size, |
48 | const char *boot_device, |
49 | const char *kernel_filename, const char *kernel_cmdline, |
50 | const char *initrd_filename, const char *cpu_model, |
51 | enum realview_board_type board_type) |
52 | { |
53 | ARMCPU *cpu = NULL((void*)0); |
54 | CPUARMState *env; |
55 | MemoryRegion *sysmem = get_system_memory(); |
56 | MemoryRegion *ram_lo = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
57 | MemoryRegion *ram_hi = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
58 | MemoryRegion *ram_alias = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
59 | MemoryRegion *ram_hack = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
60 | DeviceState *dev, *sysctl, *gpio2, *pl041; |
61 | SysBusDevice *busdev; |
62 | qemu_irq *irqp; |
63 | qemu_irq pic[64]; |
64 | qemu_irq mmc_irq[2]; |
65 | PCIBus *pci_bus; |
66 | NICInfo *nd; |
67 | i2c_bus *i2c; |
68 | int n; |
69 | int done_nic = 0; |
70 | qemu_irq cpu_irq[4]; |
71 | int is_mpcore = 0; |
72 | int is_pb = 0; |
73 | uint32_t proc_id = 0; |
74 | uint32_t sys_id; |
75 | ram_addr_t low_ram_size; |
76 | |
77 | switch (board_type) { |
| 1 | 'Default' branch taken. Execution continues on line 91 |
|
78 | case BOARD_EB: |
79 | break; |
80 | case BOARD_EB_MPCORE: |
81 | is_mpcore = 1; |
82 | break; |
83 | case BOARD_PB_A8: |
84 | is_pb = 1; |
85 | break; |
86 | case BOARD_PBX_A9: |
87 | is_mpcore = 1; |
88 | is_pb = 1; |
89 | break; |
90 | } |
91 | for (n = 0; n < smp_cpus; n++) { |
| 2 | Loop condition is false. Execution continues on line 100 |
|
92 | cpu = cpu_arm_init(cpu_model); |
93 | if (!cpu) { |
94 | fprintf(stderrstderr, "Unable to find CPU definition\n"); |
95 | exit(1); |
96 | } |
97 | irqp = arm_pic_init_cpu(cpu); |
98 | cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ0]; |
99 | } |
100 | env = &cpu->env; |
101 | if (arm_feature(env, ARM_FEATURE_V7)) { |
| |
102 | if (is_mpcore) { |
| |
103 | proc_id = 0x0c000000; |
104 | } else { |
105 | proc_id = 0x0e000000; |
106 | } |
107 | } else if (arm_feature(env, ARM_FEATURE_V6K)) { |
108 | proc_id = 0x06000000; |
109 | } else if (arm_feature(env, ARM_FEATURE_V6)) { |
110 | proc_id = 0x04000000; |
111 | } else { |
112 | proc_id = 0x02000000; |
113 | } |
114 | |
115 | if (is_pb && ram_size > 0x20000000) { |
| |
116 | |
117 | low_ram_size = ram_size - 0x20000000; |
118 | ram_size = 0x20000000; |
119 | memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size); |
120 | vmstate_register_ram_global(ram_lo); |
121 | memory_region_add_subregion(sysmem, 0x20000000, ram_lo); |
122 | } |
123 | |
124 | memory_region_init_ram(ram_hi, "realview.highmem", ram_size); |
125 | vmstate_register_ram_global(ram_hi); |
126 | low_ram_size = ram_size; |
127 | if (low_ram_size > 0x10000000) |
| |
128 | low_ram_size = 0x10000000; |
129 | |
130 | memory_region_init_alias(ram_alias, "realview.alias", |
131 | ram_hi, 0, low_ram_size); |
132 | memory_region_add_subregion(sysmem, 0, ram_alias); |
133 | if (is_pb) { |
| |
134 | |
135 | memory_region_add_subregion(sysmem, 0x70000000, ram_hi); |
136 | } else { |
137 | ram_size = low_ram_size; |
138 | } |
139 | |
140 | sys_id = is_pb ? 0x01780500 : 0xc1400400; |
| |
141 | sysctl = qdev_create(NULL((void*)0), "realview_sysctl"); |
142 | qdev_prop_set_uint32(sysctl, "sys_id", sys_id); |
143 | qdev_prop_set_uint32(sysctl, "proc_id", proc_id); |
144 | qdev_init_nofail(sysctl); |
145 | sysbus_mmio_map(sysbus_from_qdev(sysctl)((SysBusDevice *)(sysctl)), 0, 0x10000000); |
146 | |
147 | if (is_mpcore) { |
| |
148 | target_phys_addr_t periphbase; |
149 | dev = qdev_create(NULL((void*)0), is_pb ? "a9mpcore_priv": "realview_mpcore"); |
150 | qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
151 | qdev_init_nofail(dev); |
152 | busdev = sysbus_from_qdev(dev)((SysBusDevice *)(dev)); |
153 | if (is_pb) { |
154 | periphbase = 0x1f000000; |
155 | } else { |
156 | periphbase = 0x10100000; |
157 | } |
158 | sysbus_mmio_map(busdev, 0, periphbase); |
159 | for (n = 0; n < smp_cpus; n++) { |
160 | sysbus_connect_irq(busdev, n, cpu_irq[n]); |
161 | } |
162 | sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL((void*)0)); |
163 | |
164 | realview_binfo.gic_cpu_if_addr = periphbase + 0x100; |
165 | } else { |
166 | uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000; |
| |
167 | |
168 | dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]); |
| 11 | Pass-by-value argument in function call is undefined |
|
169 | } |
170 | for (n = 0; n < 64; n++) { |
171 | pic[n] = qdev_get_gpio_in(dev, n); |
172 | } |
173 | |
174 | pl041 = qdev_create(NULL((void*)0), "pl041"); |
175 | qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); |
176 | qdev_init_nofail(pl041); |
177 | sysbus_mmio_map(sysbus_from_qdev(pl041)((SysBusDevice *)(pl041)), 0, 0x10004000); |
178 | sysbus_connect_irq(sysbus_from_qdev(pl041)((SysBusDevice *)(pl041)), 0, pic[19]); |
179 | |
180 | sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]); |
181 | sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]); |
182 | |
183 | sysbus_create_simple("pl011", 0x10009000, pic[12]); |
184 | sysbus_create_simple("pl011", 0x1000a000, pic[13]); |
185 | sysbus_create_simple("pl011", 0x1000b000, pic[14]); |
186 | sysbus_create_simple("pl011", 0x1000c000, pic[15]); |
187 | |
188 | |
189 | sysbus_create_simple("pl081", 0x10030000, pic[24]); |
190 | |
191 | sysbus_create_simple("sp804", 0x10011000, pic[4]); |
192 | sysbus_create_simple("sp804", 0x10012000, pic[5]); |
193 | |
194 | sysbus_create_simple("pl061", 0x10013000, pic[6]); |
195 | sysbus_create_simple("pl061", 0x10014000, pic[7]); |
196 | gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]); |
197 | |
198 | sysbus_create_simple("pl111", 0x10020000, pic[23]); |
199 | |
200 | dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL((void*)0)); |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | mmc_irq[0] = qemu_irq_split( |
208 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT0), |
209 | qdev_get_gpio_in(gpio2, 1)); |
210 | mmc_irq[1] = qemu_irq_split( |
211 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN1), |
212 | qemu_irq_invert(qdev_get_gpio_in(gpio2, 0))); |
213 | qdev_connect_gpio_out(dev, 0, mmc_irq[0]); |
214 | qdev_connect_gpio_out(dev, 1, mmc_irq[1]); |
215 | |
216 | sysbus_create_simple("pl031", 0x10017000, pic[10]); |
217 | |
218 | if (!is_pb) { |
219 | dev = qdev_create(NULL((void*)0), "realview_pci"); |
220 | busdev = sysbus_from_qdev(dev)((SysBusDevice *)(dev)); |
221 | qdev_init_nofail(dev); |
222 | sysbus_mmio_map(busdev, 0, 0x61000000); |
223 | sysbus_mmio_map(busdev, 1, 0x62000000); |
224 | sysbus_mmio_map(busdev, 2, 0x63000000); |
225 | sysbus_connect_irq(busdev, 0, pic[48]); |
226 | sysbus_connect_irq(busdev, 1, pic[49]); |
227 | sysbus_connect_irq(busdev, 2, pic[50]); |
228 | sysbus_connect_irq(busdev, 3, pic[51]); |
229 | pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); |
230 | if (usb_enabled) { |
231 | pci_create_simple(pci_bus, -1, "pci-ohci"); |
232 | } |
233 | n = drive_get_max_bus(IF_SCSI); |
234 | while (n >= 0) { |
235 | pci_create_simple(pci_bus, -1, "lsi53c895a"); |
236 | n--; |
237 | } |
238 | } |
239 | for(n = 0; n < nb_nics; n++) { |
240 | nd = &nd_table[n]; |
241 | |
242 | if (!done_nic && (!nd->model || |
243 | strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) { |
244 | if (is_pb) { |
245 | lan9118_init(nd, 0x4e000000, pic[28]); |
246 | } else { |
247 | smc91c111_init(nd, 0x4e000000, pic[28]); |
248 | } |
249 | done_nic = 1; |
250 | } else { |
251 | pci_nic_init_nofail(nd, "rtl8139", NULL((void*)0)); |
252 | } |
253 | } |
254 | |
255 | dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL((void*)0)); |
256 | i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); |
257 | i2c_create_slave(i2c, "ds1338", 0x68); |
258 | |
259 | |
260 | |
261 | |
262 | |
263 | |
264 | |
265 | |
266 | |
267 | |
268 | |
269 | |
270 | |
271 | |
272 | |
273 | |
274 | |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | |
282 | |
283 | |
284 | |
285 | |
286 | |
287 | |
288 | |
289 | |
290 | |
291 | |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | |
317 | |
318 | |
319 | memory_region_init_ram(ram_hack, "realview.hack", 0x1000); |
320 | vmstate_register_ram_global(ram_hack); |
321 | memory_region_add_subregion(sysmem, SMP_BOOT_ADDR0xe0000000, ram_hack); |
322 | |
323 | realview_binfo.ram_size = ram_size; |
324 | realview_binfo.kernel_filename = kernel_filename; |
325 | realview_binfo.kernel_cmdline = kernel_cmdline; |
326 | realview_binfo.initrd_filename = initrd_filename; |
327 | realview_binfo.nb_cpus = smp_cpus; |
328 | realview_binfo.board_id = realview_board_id[board_type]; |
329 | realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); |
330 | arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo); |
331 | } |
332 | |
333 | static void realview_eb_init(ram_addr_t ram_size, |
334 | const char *boot_device, |
335 | const char *kernel_filename, const char *kernel_cmdline, |
336 | const char *initrd_filename, const char *cpu_model) |
337 | { |
338 | if (!cpu_model) { |
339 | cpu_model = "arm926"; |
340 | } |
341 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
342 | initrd_filename, cpu_model, BOARD_EB); |
343 | } |
344 | |
345 | static void realview_eb_mpcore_init(ram_addr_t ram_size, |
346 | const char *boot_device, |
347 | const char *kernel_filename, const char *kernel_cmdline, |
348 | const char *initrd_filename, const char *cpu_model) |
349 | { |
350 | if (!cpu_model) { |
351 | cpu_model = "arm11mpcore"; |
352 | } |
353 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
354 | initrd_filename, cpu_model, BOARD_EB_MPCORE); |
355 | } |
356 | |
357 | static void realview_pb_a8_init(ram_addr_t ram_size, |
358 | const char *boot_device, |
359 | const char *kernel_filename, const char *kernel_cmdline, |
360 | const char *initrd_filename, const char *cpu_model) |
361 | { |
362 | if (!cpu_model) { |
363 | cpu_model = "cortex-a8"; |
364 | } |
365 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
366 | initrd_filename, cpu_model, BOARD_PB_A8); |
367 | } |
368 | |
369 | static void realview_pbx_a9_init(ram_addr_t ram_size, |
370 | const char *boot_device, |
371 | const char *kernel_filename, const char *kernel_cmdline, |
372 | const char *initrd_filename, const char *cpu_model) |
373 | { |
374 | if (!cpu_model) { |
375 | cpu_model = "cortex-a9"; |
376 | } |
377 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
378 | initrd_filename, cpu_model, BOARD_PBX_A9); |
379 | } |
380 | |
381 | static QEMUMachine realview_eb_machine = { |
382 | .name = "realview-eb", |
383 | .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)", |
384 | .init = realview_eb_init, |
385 | .use_scsi = 1, |
386 | }; |
387 | |
388 | static QEMUMachine realview_eb_mpcore_machine = { |
389 | .name = "realview-eb-mpcore", |
390 | .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)", |
391 | .init = realview_eb_mpcore_init, |
392 | .use_scsi = 1, |
393 | .max_cpus = 4, |
394 | }; |
395 | |
396 | static QEMUMachine realview_pb_a8_machine = { |
397 | .name = "realview-pb-a8", |
398 | .desc = "ARM RealView Platform Baseboard for Cortex-A8", |
399 | .init = realview_pb_a8_init, |
400 | }; |
401 | |
402 | static QEMUMachine realview_pbx_a9_machine = { |
403 | .name = "realview-pbx-a9", |
404 | .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9", |
405 | .init = realview_pbx_a9_init, |
406 | .use_scsi = 1, |
407 | .max_cpus = 4, |
408 | }; |
409 | |
410 | static void realview_machine_init(void) |
411 | { |
412 | qemu_register_machine(&realview_eb_machine); |
413 | qemu_register_machine(&realview_eb_mpcore_machine); |
414 | qemu_register_machine(&realview_pb_a8_machine); |
415 | qemu_register_machine(&realview_pbx_a9_machine); |
416 | } |
417 | |
418 | machine_init(realview_machine_init)static void __attribute__((constructor)) do_qemu_init_realview_machine_init (void) { register_module_init(realview_machine_init, MODULE_INIT_MACHINE ); }; |