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