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 "usb-ohci.h"
16#include "net.h"
17#include "sysemu.h"
18#include "boards.h"
19#include "bitbang_i2c.h"
20#include "sysbus.h"
21
22#define SMP_BOOT_ADDR 0xe0000000
23
24typedef struct {
25 SysBusDevice busdev;
26 bitbang_i2c_interface *bitbang;
27 int out;
28 int in;
29} RealViewI2CState;
30
31static uint32_t realview_i2c_read(void *opaque, target_phys_addr_t offset)
32{
33 RealViewI2CState *s = (RealViewI2CState *)opaque;
34
35 if (offset == 0) {
36 return (s->out & 1) | (s->in << 1);
37 } else {
38 hw_error("realview_i2c_read: Bad offset 0x%x\n", (int)offset);
39 return -1;
40 }
41}
42
43static void realview_i2c_write(void *opaque, target_phys_addr_t offset,
44 uint32_t value)
45{
46 RealViewI2CState *s = (RealViewI2CState *)opaque;
47
48 switch (offset) {
49 case 0:
50 s->out |= value & 3;
51 break;
52 case 4:
53 s->out &= ~value;
54 break;
55 default:
56 hw_error("realview_i2c_write: Bad offset 0x%x\n", (int)offset);
57 }
58 bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
59 s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
60}
61
62static CPUReadMemoryFunc * const realview_i2c_readfn[] = {
63 realview_i2c_read,
64 realview_i2c_read,
65 realview_i2c_read
66};
67
68static CPUWriteMemoryFunc * const realview_i2c_writefn[] = {
69 realview_i2c_write,
70 realview_i2c_write,
71 realview_i2c_write
72};
73
74static int realview_i2c_init(SysBusDevice *dev)
75{
76 RealViewI2CState *s = FROM_SYSBUS(RealViewI2CState, dev);
77 i2c_bus *bus;
78 int iomemtype;
79
80 bus = i2c_init_bus(&dev->qdev, "i2c");
81 s->bitbang = bitbang_i2c_init(bus);
82 iomemtype = cpu_register_io_memory(realview_i2c_readfn,
83 realview_i2c_writefn, s);
84 sysbus_init_mmio(dev, 0x1000, iomemtype);
85 return 0;
86}
87
88static SysBusDeviceInfo realview_i2c_info = {
89 .init = realview_i2c_init,
90 .qdev.name = "realview_i2c",
91 .qdev.size = sizeof(RealViewI2CState),
92};
93
94static void realview_register_devices(void)
95{
96 sysbus_register_withprop(&realview_i2c_info);
97}
98
99
100
101static struct arm_boot_info realview_binfo = {
102 .smp_loader_start = SMP_BOOT_ADDR,
103};
104
105static void secondary_cpu_reset(void *opaque)
106{
107 CPUState *env = opaque;
108
109 cpu_reset(env);
110
111
112
113 env->regs[15] = SMP_BOOT_ADDR;
114}
115
116
117enum realview_board_type {
118 BOARD_EB,
119 BOARD_EB_MPCORE,
120 BOARD_PB_A8,
121 BOARD_PBX_A9,
122};
123
124static const int realview_board_id[] = {
125 0x33b,
126 0x33b,
127 0x769,
128 0x76d
129};
130
131static void realview_init(ram_addr_t ram_size,
132 const char *boot_device,
133 const char *kernel_filename, const char *kernel_cmdline,
134 const char *initrd_filename, const char *cpu_model,
135 enum realview_board_type board_type)
136{
137 CPUState *env = NULL;
138 ram_addr_t ram_offset;
139 DeviceState *dev;
140 SysBusDevice *busdev;
141 qemu_irq *irqp;
142 qemu_irq pic[64];
143 PCIBus *pci_bus;
144 NICInfo *nd;
145 i2c_bus *i2c;
146 int n;
147 int done_nic = 0;
148 qemu_irq cpu_irq[4];
149 int is_mpcore = 0;
150 int is_pb = 0;
151 uint32_t proc_id = 0;
152 uint32_t sys_id;
153 ram_addr_t low_ram_size;
154
155 switch (board_type) {
156 case BOARD_EB:
157 break;
158 case BOARD_EB_MPCORE:
159 is_mpcore = 1;
160 break;
161 case BOARD_PB_A8:
162 is_pb = 1;
163 break;
164 case BOARD_PBX_A9:
165 is_mpcore = 1;
166 is_pb = 1;
167 break;
168 }
169 for (n = 0; n < smp_cpus; n++) {
170 env = cpu_init(cpu_model);
171 if (!env) {
172 fprintf(stderr, "Unable to find CPU definition\n");
173 exit(1);
174 }
175 irqp = arm_pic_init_cpu(env);
176 cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
177 if (n > 0) {
178 qemu_register_reset(secondary_cpu_reset, env);
179 }
180 }
181 if (arm_feature(env, ARM_FEATURE_V7)) {
182 if (is_mpcore) {
183 proc_id = 0x0c000000;
184 } else {
185 proc_id = 0x0e000000;
186 }
187 } else if (arm_feature(env, ARM_FEATURE_V6K)) {
188 proc_id = 0x06000000;
189 } else if (arm_feature(env, ARM_FEATURE_V6)) {
190 proc_id = 0x04000000;
191 } else {
192 proc_id = 0x02000000;
193 }
194
195 ram_offset = qemu_ram_alloc(ram_size);
196 low_ram_size = ram_size;
197 if (low_ram_size > 0x10000000)
198 low_ram_size = 0x10000000;
199
200
201 cpu_register_physical_memory(0, low_ram_size, ram_offset | IO_MEM_RAM);
202 if (is_pb) {
203
204 cpu_register_physical_memory(0x70000000, ram_size,
205 ram_offset | IO_MEM_RAM);
206 } else {
207 ram_size = low_ram_size;
208 }
209
210 sys_id = is_pb ? 0x01780500 : 0xc1400400;
211 arm_sysctl_init(0x10000000, sys_id, proc_id);
212
213 if (is_mpcore) {
214 dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
215 qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
216 qdev_init_nofail(dev);
217 busdev = sysbus_from_qdev(dev);
218 if (is_pb) {
219 realview_binfo.smp_priv_base = 0x1f000000;
220 } else {
221 realview_binfo.smp_priv_base = 0x10100000;
222 }
223 sysbus_mmio_map(busdev, 0, realview_binfo.smp_priv_base);
224 for (n = 0; n < smp_cpus; n++) {
225 sysbus_connect_irq(busdev, n, cpu_irq[n]);
226 }
227 } else {
228 uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
229
230 dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
231 }
232 for (n = 0; n < 64; n++) {
233 pic[n] = qdev_get_gpio_in(dev, n);
234 }
235
236 sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
237 sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
238
239 sysbus_create_simple("pl011", 0x10009000, pic[12]);
240 sysbus_create_simple("pl011", 0x1000a000, pic[13]);
241 sysbus_create_simple("pl011", 0x1000b000, pic[14]);
242 sysbus_create_simple("pl011", 0x1000c000, pic[15]);
243
244
245 sysbus_create_simple("pl081", 0x10030000, pic[24]);
246
247 sysbus_create_simple("sp804", 0x10011000, pic[4]);
248 sysbus_create_simple("sp804", 0x10012000, pic[5]);
249
250 sysbus_create_simple("pl110_versatile", 0x10020000, pic[23]);
251
252 sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL);
253
254 sysbus_create_simple("pl031", 0x10017000, pic[10]);
255
256 if (!is_pb) {
257 dev = sysbus_create_varargs("realview_pci", 0x60000000,
258 pic[48], pic[49], pic[50], pic[51], NULL);
259 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
260 if (usb_enabled) {
261 usb_ohci_init_pci(pci_bus, -1);
262 }
263 n = drive_get_max_bus(IF_SCSI);
264 while (n >= 0) {
265 pci_create_simple(pci_bus, -1, "lsi53c895a");
266 n--;
267 }
268 }
269 for(n = 0; n < nb_nics; n++) {
270 nd = &nd_table[n];
271
272 if ((!nd->model && !done_nic)
273 || strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0) {
274 if (is_pb) {
275 lan9118_init(nd, 0x4e000000, pic[28]);
276 } else {
277 smc91c111_init(nd, 0x4e000000, pic[28]);
278 }
279 done_nic = 1;
280 } else {
281 pci_nic_init_nofail(nd, "rtl8139", NULL);
282 }
283 }
284
285 dev = sysbus_create_simple("realview_i2c", 0x10002000, NULL);
286 i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
287 i2c_create_slave(i2c, "ds1338", 0x68);
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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 ram_offset = qemu_ram_alloc(0x1000);
350 cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
351 ram_offset | IO_MEM_RAM);
352
353 realview_binfo.ram_size = ram_size;
354 realview_binfo.kernel_filename = kernel_filename;
355 realview_binfo.kernel_cmdline = kernel_cmdline;
356 realview_binfo.initrd_filename = initrd_filename;
357 realview_binfo.nb_cpus = smp_cpus;
358 realview_binfo.board_id = realview_board_id[board_type];
359 realview_binfo.loader_start = is_pb ? 0x70000000 : 0;
360 arm_load_kernel(first_cpu, &realview_binfo);
361}
362
363static void realview_eb_init(ram_addr_t ram_size,
364 const char *boot_device,
365 const char *kernel_filename, const char *kernel_cmdline,
366 const char *initrd_filename, const char *cpu_model)
367{
368 if (!cpu_model) {
369 cpu_model = "arm926";
370 }
371 realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
372 initrd_filename, cpu_model, BOARD_EB);
373}
374
375static void realview_eb_mpcore_init(ram_addr_t ram_size,
376 const char *boot_device,
377 const char *kernel_filename, const char *kernel_cmdline,
378 const char *initrd_filename, const char *cpu_model)
379{
380 if (!cpu_model) {
381 cpu_model = "arm11mpcore";
382 }
383 realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
384 initrd_filename, cpu_model, BOARD_EB_MPCORE);
385}
386
387static void realview_pb_a8_init(ram_addr_t ram_size,
388 const char *boot_device,
389 const char *kernel_filename, const char *kernel_cmdline,
390 const char *initrd_filename, const char *cpu_model)
391{
392 if (!cpu_model) {
393 cpu_model = "cortex-a8";
394 }
395 realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
396 initrd_filename, cpu_model, BOARD_PB_A8);
397}
398
399static void realview_pbx_a9_init(ram_addr_t ram_size,
400 const char *boot_device,
401 const char *kernel_filename, const char *kernel_cmdline,
402 const char *initrd_filename, const char *cpu_model)
403{
404 if (!cpu_model) {
405 cpu_model = "cortex-a9";
406 }
407 realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
408 initrd_filename, cpu_model, BOARD_PBX_A9);
409}
410
411static QEMUMachine realview_eb_machine = {
412 .name = "realview-eb",
413 .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
414 .init = realview_eb_init,
415 .use_scsi = 1,
416};
417
418static QEMUMachine realview_eb_mpcore_machine = {
419 .name = "realview-eb-mpcore",
420 .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
421 .init = realview_eb_mpcore_init,
422 .use_scsi = 1,
423 .max_cpus = 4,
424};
425
426static QEMUMachine realview_pb_a8_machine = {
427 .name = "realview-pb-a8",
428 .desc = "ARM RealView Platform Baseboard for Cortex-A8",
429 .init = realview_pb_a8_init,
430};
431
432static QEMUMachine realview_pbx_a9_machine = {
433 .name = "realview-pbx-a9",
434 .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
435 .init = realview_pbx_a9_init,
436 .use_scsi = 1,
437 .max_cpus = 4,
438};
439
440static void realview_machine_init(void)
441{
442 qemu_register_machine(&realview_eb_machine);
443 qemu_register_machine(&realview_eb_mpcore_machine);
444 qemu_register_machine(&realview_pb_a8_machine);
445 qemu_register_machine(&realview_pbx_a9_machine);
446}
447
448machine_init(realview_machine_init);
449device_init(realview_register_devices)
450