1
2
3
4
5
6
7
8
9
10#include "qemu/osdep.h"
11#include "qapi/error.h"
12#include "cpu.h"
13#include "hw/sysbus.h"
14#include "migration/vmstate.h"
15#include "hw/arm/boot.h"
16#include "hw/net/smc91c111.h"
17#include "net/net.h"
18#include "sysemu/sysemu.h"
19#include "hw/pci/pci.h"
20#include "hw/i2c/i2c.h"
21#include "hw/i2c/arm_sbcon_i2c.h"
22#include "hw/irq.h"
23#include "hw/boards.h"
24#include "hw/block/flash.h"
25#include "qemu/error-report.h"
26#include "hw/char/pl011.h"
27#include "hw/sd/sd.h"
28#include "qom/object.h"
29
30#define VERSATILE_FLASH_ADDR 0x34000000
31#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
32#define VERSATILE_FLASH_SECT_SIZE (256 * 1024)
33
34
35
36#define TYPE_VERSATILE_PB_SIC "versatilepb_sic"
37OBJECT_DECLARE_SIMPLE_TYPE(vpb_sic_state, VERSATILE_PB_SIC)
38
39struct vpb_sic_state {
40 SysBusDevice parent_obj;
41
42 MemoryRegion iomem;
43 uint32_t level;
44 uint32_t mask;
45 uint32_t pic_enable;
46 qemu_irq parent[32];
47 int irq;
48};
49
50static const VMStateDescription vmstate_vpb_sic = {
51 .name = "versatilepb_sic",
52 .version_id = 1,
53 .minimum_version_id = 1,
54 .fields = (VMStateField[]) {
55 VMSTATE_UINT32(level, vpb_sic_state),
56 VMSTATE_UINT32(mask, vpb_sic_state),
57 VMSTATE_UINT32(pic_enable, vpb_sic_state),
58 VMSTATE_END_OF_LIST()
59 }
60};
61
62static void vpb_sic_update(vpb_sic_state *s)
63{
64 uint32_t flags;
65
66 flags = s->level & s->mask;
67 qemu_set_irq(s->parent[s->irq], flags != 0);
68}
69
70static void vpb_sic_update_pic(vpb_sic_state *s)
71{
72 int i;
73 uint32_t mask;
74
75 for (i = 21; i <= 30; i++) {
76 mask = 1u << i;
77 if (!(s->pic_enable & mask))
78 continue;
79 qemu_set_irq(s->parent[i], (s->level & mask) != 0);
80 }
81}
82
83static void vpb_sic_set_irq(void *opaque, int irq, int level)
84{
85 vpb_sic_state *s = (vpb_sic_state *)opaque;
86 if (level)
87 s->level |= 1u << irq;
88 else
89 s->level &= ~(1u << irq);
90 if (s->pic_enable & (1u << irq))
91 qemu_set_irq(s->parent[irq], level);
92 vpb_sic_update(s);
93}
94
95static uint64_t vpb_sic_read(void *opaque, hwaddr offset,
96 unsigned size)
97{
98 vpb_sic_state *s = (vpb_sic_state *)opaque;
99
100 switch (offset >> 2) {
101 case 0:
102 return s->level & s->mask;
103 case 1:
104 return s->level;
105 case 2:
106 return s->mask;
107 case 4:
108 return s->level & 1;
109 case 8:
110 return s->pic_enable;
111 default:
112 printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
113 return 0;
114 }
115}
116
117static void vpb_sic_write(void *opaque, hwaddr offset,
118 uint64_t value, unsigned size)
119{
120 vpb_sic_state *s = (vpb_sic_state *)opaque;
121
122 switch (offset >> 2) {
123 case 2:
124 s->mask |= value;
125 break;
126 case 3:
127 s->mask &= ~value;
128 break;
129 case 4:
130 if (value)
131 s->mask |= 1;
132 break;
133 case 5:
134 if (value)
135 s->mask &= ~1u;
136 break;
137 case 8:
138 s->pic_enable |= (value & 0x7fe00000);
139 vpb_sic_update_pic(s);
140 break;
141 case 9:
142 s->pic_enable &= ~value;
143 vpb_sic_update_pic(s);
144 break;
145 default:
146 printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
147 return;
148 }
149 vpb_sic_update(s);
150}
151
152static const MemoryRegionOps vpb_sic_ops = {
153 .read = vpb_sic_read,
154 .write = vpb_sic_write,
155 .endianness = DEVICE_NATIVE_ENDIAN,
156};
157
158static void vpb_sic_init(Object *obj)
159{
160 DeviceState *dev = DEVICE(obj);
161 vpb_sic_state *s = VERSATILE_PB_SIC(obj);
162 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
163 int i;
164
165 qdev_init_gpio_in(dev, vpb_sic_set_irq, 32);
166 for (i = 0; i < 32; i++) {
167 sysbus_init_irq(sbd, &s->parent[i]);
168 }
169 s->irq = 31;
170 memory_region_init_io(&s->iomem, obj, &vpb_sic_ops, s,
171 "vpb-sic", 0x1000);
172 sysbus_init_mmio(sbd, &s->iomem);
173}
174
175
176
177
178
179
180
181static struct arm_boot_info versatile_binfo;
182
183static void versatile_init(MachineState *machine, int board_id)
184{
185 Object *cpuobj;
186 ARMCPU *cpu;
187 MemoryRegion *sysmem = get_system_memory();
188 qemu_irq pic[32];
189 qemu_irq sic[32];
190 DeviceState *dev, *sysctl;
191 SysBusDevice *busdev;
192 DeviceState *pl041;
193 PCIBus *pci_bus;
194 NICInfo *nd;
195 I2CBus *i2c;
196 int n;
197 int done_smc = 0;
198 DriveInfo *dinfo;
199
200 if (machine->ram_size > 0x10000000) {
201
202
203
204
205 error_report("versatilepb: memory size must not exceed 256MB");
206 exit(1);
207 }
208
209 cpuobj = object_new(machine->cpu_type);
210
211
212
213
214
215 if (object_property_find(cpuobj, "has_el3")) {
216 object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
217 }
218
219 qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
220
221 cpu = ARM_CPU(cpuobj);
222
223
224
225 memory_region_add_subregion(sysmem, 0, machine->ram);
226
227 sysctl = qdev_new("realview_sysctl");
228 qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
229 qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
230 sysbus_realize_and_unref(SYS_BUS_DEVICE(sysctl), &error_fatal);
231 sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
232
233 dev = sysbus_create_varargs("pl190", 0x10140000,
234 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
235 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
236 NULL);
237 for (n = 0; n < 32; n++) {
238 pic[n] = qdev_get_gpio_in(dev, n);
239 }
240 dev = sysbus_create_simple(TYPE_VERSATILE_PB_SIC, 0x10003000, NULL);
241 for (n = 0; n < 32; n++) {
242 sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
243 sic[n] = qdev_get_gpio_in(dev, n);
244 }
245
246 sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
247 sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
248
249 dev = qdev_new("versatile_pci");
250 busdev = SYS_BUS_DEVICE(dev);
251 sysbus_realize_and_unref(busdev, &error_fatal);
252 sysbus_mmio_map(busdev, 0, 0x10001000);
253 sysbus_mmio_map(busdev, 1, 0x41000000);
254 sysbus_mmio_map(busdev, 2, 0x42000000);
255 sysbus_mmio_map(busdev, 3, 0x43000000);
256 sysbus_mmio_map(busdev, 4, 0x44000000);
257 sysbus_mmio_map(busdev, 5, 0x50000000);
258 sysbus_mmio_map(busdev, 6, 0x60000000);
259 sysbus_connect_irq(busdev, 0, sic[27]);
260 sysbus_connect_irq(busdev, 1, sic[28]);
261 sysbus_connect_irq(busdev, 2, sic[29]);
262 sysbus_connect_irq(busdev, 3, sic[30]);
263 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
264
265 for(n = 0; n < nb_nics; n++) {
266 nd = &nd_table[n];
267
268 if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
269 smc91c111_init(nd, 0x10010000, sic[25]);
270 done_smc = 1;
271 } else {
272 pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
273 }
274 }
275 if (machine_usb(machine)) {
276 pci_create_simple(pci_bus, -1, "pci-ohci");
277 }
278 n = drive_get_max_bus(IF_SCSI);
279 while (n >= 0) {
280 dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
281 lsi53c8xx_handle_legacy_cmdline(dev);
282 n--;
283 }
284
285 pl011_create(0x101f1000, pic[12], serial_hd(0));
286 pl011_create(0x101f2000, pic[13], serial_hd(1));
287 pl011_create(0x101f3000, pic[14], serial_hd(2));
288 pl011_create(0x10009000, sic[6], serial_hd(3));
289
290 dev = qdev_new("pl080");
291 object_property_set_link(OBJECT(dev), "downstream", OBJECT(sysmem),
292 &error_fatal);
293 busdev = SYS_BUS_DEVICE(dev);
294 sysbus_realize_and_unref(busdev, &error_fatal);
295 sysbus_mmio_map(busdev, 0, 0x10130000);
296 sysbus_connect_irq(busdev, 0, pic[17]);
297
298 sysbus_create_simple("sp804", 0x101e2000, pic[4]);
299 sysbus_create_simple("sp804", 0x101e3000, pic[5]);
300
301 sysbus_create_simple("pl061", 0x101e4000, pic[6]);
302 sysbus_create_simple("pl061", 0x101e5000, pic[7]);
303 sysbus_create_simple("pl061", 0x101e6000, pic[8]);
304 sysbus_create_simple("pl061", 0x101e7000, pic[9]);
305
306
307
308 dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
309
310 qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
311
312 dev = sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
313 dinfo = drive_get(IF_SD, 0, 0);
314 if (dinfo) {
315 DeviceState *card;
316
317 card = qdev_new(TYPE_SD_CARD);
318 qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
319 &error_fatal);
320 qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
321 &error_fatal);
322 }
323
324 dev = sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
325 dinfo = drive_get(IF_SD, 0, 1);
326 if (dinfo) {
327 DeviceState *card;
328
329 card = qdev_new(TYPE_SD_CARD);
330 qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
331 &error_fatal);
332 qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
333 &error_fatal);
334 }
335
336
337 sysbus_create_simple("pl031", 0x101e8000, pic[10]);
338
339 dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
340 i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
341 i2c_slave_create_simple(i2c, "ds1338", 0x68);
342
343
344 pl041 = qdev_new("pl041");
345 qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
346 sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal);
347 sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
348 sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 dinfo = drive_get(IF_PFLASH, 0, 0);
388 if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
389 VERSATILE_FLASH_SIZE,
390 dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
391 VERSATILE_FLASH_SECT_SIZE,
392 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
393 fprintf(stderr, "qemu: Error registering flash memory.\n");
394 }
395
396 versatile_binfo.ram_size = machine->ram_size;
397 versatile_binfo.board_id = board_id;
398 arm_load_kernel(cpu, machine, &versatile_binfo);
399}
400
401static void vpb_init(MachineState *machine)
402{
403 versatile_init(machine, 0x183);
404}
405
406static void vab_init(MachineState *machine)
407{
408 versatile_init(machine, 0x25e);
409}
410
411static void versatilepb_class_init(ObjectClass *oc, void *data)
412{
413 MachineClass *mc = MACHINE_CLASS(oc);
414
415 mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
416 mc->init = vpb_init;
417 mc->block_default_type = IF_SCSI;
418 mc->ignore_memory_transaction_failures = true;
419 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
420 mc->default_ram_id = "versatile.ram";
421}
422
423static const TypeInfo versatilepb_type = {
424 .name = MACHINE_TYPE_NAME("versatilepb"),
425 .parent = TYPE_MACHINE,
426 .class_init = versatilepb_class_init,
427};
428
429static void versatileab_class_init(ObjectClass *oc, void *data)
430{
431 MachineClass *mc = MACHINE_CLASS(oc);
432
433 mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
434 mc->init = vab_init;
435 mc->block_default_type = IF_SCSI;
436 mc->ignore_memory_transaction_failures = true;
437 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
438 mc->default_ram_id = "versatile.ram";
439}
440
441static const TypeInfo versatileab_type = {
442 .name = MACHINE_TYPE_NAME("versatileab"),
443 .parent = TYPE_MACHINE,
444 .class_init = versatileab_class_init,
445};
446
447static void versatile_machine_init(void)
448{
449 type_register_static(&versatilepb_type);
450 type_register_static(&versatileab_type);
451}
452
453type_init(versatile_machine_init)
454
455static void vpb_sic_class_init(ObjectClass *klass, void *data)
456{
457 DeviceClass *dc = DEVICE_CLASS(klass);
458
459 dc->vmsd = &vmstate_vpb_sic;
460}
461
462static const TypeInfo vpb_sic_info = {
463 .name = TYPE_VERSATILE_PB_SIC,
464 .parent = TYPE_SYS_BUS_DEVICE,
465 .instance_size = sizeof(vpb_sic_state),
466 .instance_init = vpb_sic_init,
467 .class_init = vpb_sic_class_init,
468};
469
470static void versatilepb_register_types(void)
471{
472 type_register_static(&vpb_sic_info);
473}
474
475type_init(versatilepb_register_types)
476