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