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 Object *cpuobj;
185 ARMCPU *cpu;
186 MemoryRegion *sysmem = get_system_memory();
187 MemoryRegion *ram = g_new(MemoryRegion, 1);
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", NULL)) {
216 object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
217 }
218
219 object_property_set_bool(cpuobj, true, "realized", &error_fatal);
220
221 cpu = ARM_CPU(cpuobj);
222
223 memory_region_allocate_system_memory(ram, NULL, "versatile.ram",
224 machine->ram_size);
225
226
227 memory_region_add_subregion(sysmem, 0, ram);
228
229 sysctl = qdev_create(NULL, "realview_sysctl");
230 qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
231 qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
232 qdev_init_nofail(sysctl);
233 sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
234
235 dev = sysbus_create_varargs("pl190", 0x10140000,
236 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
237 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
238 NULL);
239 for (n = 0; n < 32; n++) {
240 pic[n] = qdev_get_gpio_in(dev, n);
241 }
242 dev = sysbus_create_simple(TYPE_VERSATILE_PB_SIC, 0x10003000, NULL);
243 for (n = 0; n < 32; n++) {
244 sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
245 sic[n] = qdev_get_gpio_in(dev, n);
246 }
247
248 sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
249 sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
250
251 dev = qdev_create(NULL, "versatile_pci");
252 busdev = SYS_BUS_DEVICE(dev);
253 qdev_init_nofail(dev);
254 sysbus_mmio_map(busdev, 0, 0x10001000);
255 sysbus_mmio_map(busdev, 1, 0x41000000);
256 sysbus_mmio_map(busdev, 2, 0x42000000);
257 sysbus_mmio_map(busdev, 3, 0x43000000);
258 sysbus_mmio_map(busdev, 4, 0x44000000);
259 sysbus_mmio_map(busdev, 5, 0x50000000);
260 sysbus_mmio_map(busdev, 6, 0x60000000);
261 sysbus_connect_irq(busdev, 0, sic[27]);
262 sysbus_connect_irq(busdev, 1, sic[28]);
263 sysbus_connect_irq(busdev, 2, sic[29]);
264 sysbus_connect_irq(busdev, 3, sic[30]);
265 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
266
267 for(n = 0; n < nb_nics; n++) {
268 nd = &nd_table[n];
269
270 if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
271 smc91c111_init(nd, 0x10010000, sic[25]);
272 done_smc = 1;
273 } else {
274 pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
275 }
276 }
277 if (machine_usb(machine)) {
278 pci_create_simple(pci_bus, -1, "pci-ohci");
279 }
280 n = drive_get_max_bus(IF_SCSI);
281 while (n >= 0) {
282 lsi53c895a_create(pci_bus);
283 n--;
284 }
285
286 pl011_create(0x101f1000, pic[12], serial_hds[0]);
287 pl011_create(0x101f2000, pic[13], serial_hds[1]);
288 pl011_create(0x101f3000, pic[14], serial_hds[2]);
289 pl011_create(0x10009000, sic[6], serial_hds[3]);
290
291 sysbus_create_simple("pl080", 0x10130000, pic[17]);
292 sysbus_create_simple("sp804", 0x101e2000, pic[4]);
293 sysbus_create_simple("sp804", 0x101e3000, pic[5]);
294
295 sysbus_create_simple("pl061", 0x101e4000, pic[6]);
296 sysbus_create_simple("pl061", 0x101e5000, pic[7]);
297 sysbus_create_simple("pl061", 0x101e6000, pic[8]);
298 sysbus_create_simple("pl061", 0x101e7000, pic[9]);
299
300
301
302 dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
303
304 qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
305
306 sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
307 sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
308
309
310 sysbus_create_simple("pl031", 0x101e8000, pic[10]);
311
312 dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
313 i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
314 i2c_create_slave(i2c, "ds1338", 0x68);
315
316
317 pl041 = qdev_create(NULL, "pl041");
318 qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
319 qdev_init_nofail(pl041);
320 sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
321 sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
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
350
351
352
353
354
355
356
357
358
359
360 dinfo = drive_get(IF_PFLASH, 0, 0);
361 if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
362 VERSATILE_FLASH_SIZE,
363 dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
364 VERSATILE_FLASH_SECT_SIZE,
365 VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
366 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
367 fprintf(stderr, "qemu: Error registering flash memory.\n");
368 }
369
370 versatile_binfo.ram_size = machine->ram_size;
371 versatile_binfo.kernel_filename = machine->kernel_filename;
372 versatile_binfo.kernel_cmdline = machine->kernel_cmdline;
373 versatile_binfo.initrd_filename = machine->initrd_filename;
374 versatile_binfo.board_id = board_id;
375 arm_load_kernel(cpu, &versatile_binfo);
376}
377
378static void vpb_init(MachineState *machine)
379{
380 versatile_init(machine, 0x183);
381}
382
383static void vab_init(MachineState *machine)
384{
385 versatile_init(machine, 0x25e);
386}
387
388static void versatilepb_class_init(ObjectClass *oc, void *data)
389{
390 MachineClass *mc = MACHINE_CLASS(oc);
391
392 mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
393 mc->init = vpb_init;
394 mc->block_default_type = IF_SCSI;
395 mc->ignore_memory_transaction_failures = true;
396 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
397}
398
399static const TypeInfo versatilepb_type = {
400 .name = MACHINE_TYPE_NAME("versatilepb"),
401 .parent = TYPE_MACHINE,
402 .class_init = versatilepb_class_init,
403};
404
405static void versatileab_class_init(ObjectClass *oc, void *data)
406{
407 MachineClass *mc = MACHINE_CLASS(oc);
408
409 mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
410 mc->init = vab_init;
411 mc->block_default_type = IF_SCSI;
412 mc->ignore_memory_transaction_failures = true;
413 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
414}
415
416static const TypeInfo versatileab_type = {
417 .name = MACHINE_TYPE_NAME("versatileab"),
418 .parent = TYPE_MACHINE,
419 .class_init = versatileab_class_init,
420};
421
422static void versatile_machine_init(void)
423{
424 type_register_static(&versatilepb_type);
425 type_register_static(&versatileab_type);
426}
427
428type_init(versatile_machine_init)
429
430static void vpb_sic_class_init(ObjectClass *klass, void *data)
431{
432 DeviceClass *dc = DEVICE_CLASS(klass);
433
434 dc->vmsd = &vmstate_vpb_sic;
435}
436
437static const TypeInfo vpb_sic_info = {
438 .name = TYPE_VERSATILE_PB_SIC,
439 .parent = TYPE_SYS_BUS_DEVICE,
440 .instance_size = sizeof(vpb_sic_state),
441 .instance_init = vpb_sic_init,
442 .class_init = vpb_sic_class_init,
443};
444
445static void versatilepb_register_types(void)
446{
447 type_register_static(&vpb_sic_info);
448}
449
450type_init(versatilepb_register_types)
451