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 "hw/arm/boot.h"
15#include "hw/net/smc91c111.h"
16#include "net/net.h"
17#include "sysemu/sysemu.h"
18#include "hw/pci/pci.h"
19#include "hw/i2c/i2c.h"
20#include "hw/boards.h"
21#include "exec/address-spaces.h"
22#include "hw/block/flash.h"
23#include "qemu/error-report.h"
24#include "hw/char/pl011.h"
25
26#define VERSATILE_FLASH_ADDR 0x34000000
27#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
28#define VERSATILE_FLASH_SECT_SIZE (256 * 1024)
29
30
31
32#define TYPE_VERSATILE_PB_SIC "versatilepb_sic"
33#define VERSATILE_PB_SIC(obj) \
34 OBJECT_CHECK(vpb_sic_state, (obj), TYPE_VERSATILE_PB_SIC)
35
36typedef struct vpb_sic_state {
37 SysBusDevice parent_obj;
38
39 MemoryRegion iomem;
40 uint32_t level;
41 uint32_t mask;
42 uint32_t pic_enable;
43 qemu_irq parent[32];
44 int irq;
45} vpb_sic_state;
46
47static const VMStateDescription vmstate_vpb_sic = {
48 .name = "versatilepb_sic",
49 .version_id = 1,
50 .minimum_version_id = 1,
51 .fields = (VMStateField[]) {
52 VMSTATE_UINT32(level, vpb_sic_state),
53 VMSTATE_UINT32(mask, vpb_sic_state),
54 VMSTATE_UINT32(pic_enable, vpb_sic_state),
55 VMSTATE_END_OF_LIST()
56 }
57};
58
59static void vpb_sic_update(vpb_sic_state *s)
60{
61 uint32_t flags;
62
63 flags = s->level & s->mask;
64 qemu_set_irq(s->parent[s->irq], flags != 0);
65}
66
67static void vpb_sic_update_pic(vpb_sic_state *s)
68{
69 int i;
70 uint32_t mask;
71
72 for (i = 21; i <= 30; i++) {
73 mask = 1u << i;
74 if (!(s->pic_enable & mask))
75 continue;
76 qemu_set_irq(s->parent[i], (s->level & mask) != 0);
77 }
78}
79
80static void vpb_sic_set_irq(void *opaque, int irq, int level)
81{
82 vpb_sic_state *s = (vpb_sic_state *)opaque;
83 if (level)
84 s->level |= 1u << irq;
85 else
86 s->level &= ~(1u << irq);
87 if (s->pic_enable & (1u << irq))
88 qemu_set_irq(s->parent[irq], level);
89 vpb_sic_update(s);
90}
91
92static uint64_t vpb_sic_read(void *opaque, hwaddr offset,
93 unsigned size)
94{
95 vpb_sic_state *s = (vpb_sic_state *)opaque;
96
97 switch (offset >> 2) {
98 case 0:
99 return s->level & s->mask;
100 case 1:
101 return s->level;
102 case 2:
103 return s->mask;
104 case 4:
105 return s->level & 1;
106 case 8:
107 return s->pic_enable;
108 default:
109 printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
110 return 0;
111 }
112}
113
114static void vpb_sic_write(void *opaque, hwaddr offset,
115 uint64_t value, unsigned size)
116{
117 vpb_sic_state *s = (vpb_sic_state *)opaque;
118
119 switch (offset >> 2) {
120 case 2:
121 s->mask |= value;
122 break;
123 case 3:
124 s->mask &= ~value;
125 break;
126 case 4:
127 if (value)
128 s->mask |= 1;
129 break;
130 case 5:
131 if (value)
132 s->mask &= ~1u;
133 break;
134 case 8:
135 s->pic_enable |= (value & 0x7fe00000);
136 vpb_sic_update_pic(s);
137 break;
138 case 9:
139 s->pic_enable &= ~value;
140 vpb_sic_update_pic(s);
141 break;
142 default:
143 printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
144 return;
145 }
146 vpb_sic_update(s);
147}
148
149static const MemoryRegionOps vpb_sic_ops = {
150 .read = vpb_sic_read,
151 .write = vpb_sic_write,
152 .endianness = DEVICE_NATIVE_ENDIAN,
153};
154
155static void vpb_sic_init(Object *obj)
156{
157 DeviceState *dev = DEVICE(obj);
158 vpb_sic_state *s = VERSATILE_PB_SIC(obj);
159 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
160 int i;
161
162 qdev_init_gpio_in(dev, vpb_sic_set_irq, 32);
163 for (i = 0; i < 32; i++) {
164 sysbus_init_irq(sbd, &s->parent[i]);
165 }
166 s->irq = 31;
167 memory_region_init_io(&s->iomem, obj, &vpb_sic_ops, s,
168 "vpb-sic", 0x1000);
169 sysbus_init_mmio(sbd, &s->iomem);
170}
171
172
173
174
175
176
177
178static struct arm_boot_info versatile_binfo;
179
180static void versatile_init(MachineState *machine, int board_id)
181{
182 Object *cpuobj;
183 ARMCPU *cpu;
184 MemoryRegion *sysmem = get_system_memory();
185 MemoryRegion *ram = g_new(MemoryRegion, 1);
186 qemu_irq pic[32];
187 qemu_irq sic[32];
188 DeviceState *dev, *sysctl;
189 SysBusDevice *busdev;
190 DeviceState *pl041;
191 PCIBus *pci_bus;
192 NICInfo *nd;
193 I2CBus *i2c;
194 int n;
195 int done_smc = 0;
196 DriveInfo *dinfo;
197
198 if (machine->ram_size > 0x10000000) {
199
200
201
202
203 error_report("versatilepb: memory size must not exceed 256MB");
204 exit(1);
205 }
206
207 cpuobj = object_new(machine->cpu_type);
208
209
210
211
212
213 if (object_property_find(cpuobj, "has_el3", NULL)) {
214 object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
215 }
216
217 object_property_set_bool(cpuobj, true, "realized", &error_fatal);
218
219 cpu = ARM_CPU(cpuobj);
220
221 memory_region_allocate_system_memory(ram, NULL, "versatile.ram",
222 machine->ram_size);
223
224
225 memory_region_add_subregion(sysmem, 0, ram);
226
227 sysctl = qdev_create(NULL, "realview_sysctl");
228 qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
229 qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
230 qdev_init_nofail(sysctl);
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_create(NULL, "versatile_pci");
250 busdev = SYS_BUS_DEVICE(dev);
251 qdev_init_nofail(dev);
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_create(NULL, "pl080");
291 object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
292 &error_fatal);
293 qdev_init_nofail(dev);
294 busdev = SYS_BUS_DEVICE(dev);
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 sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
313 sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
314
315
316 sysbus_create_simple("pl031", 0x101e8000, pic[10]);
317
318 dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
319 i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
320 i2c_create_slave(i2c, "ds1338", 0x68);
321
322
323 pl041 = qdev_create(NULL, "pl041");
324 qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
325 qdev_init_nofail(pl041);
326 sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
327 sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
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
361
362
363
364
365
366 dinfo = drive_get(IF_PFLASH, 0, 0);
367 if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
368 VERSATILE_FLASH_SIZE,
369 dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
370 VERSATILE_FLASH_SECT_SIZE,
371 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
372 fprintf(stderr, "qemu: Error registering flash memory.\n");
373 }
374
375 versatile_binfo.ram_size = machine->ram_size;
376 versatile_binfo.kernel_filename = machine->kernel_filename;
377 versatile_binfo.kernel_cmdline = machine->kernel_cmdline;
378 versatile_binfo.initrd_filename = machine->initrd_filename;
379 versatile_binfo.board_id = board_id;
380 arm_load_kernel(cpu, &versatile_binfo);
381}
382
383static void vpb_init(MachineState *machine)
384{
385 versatile_init(machine, 0x183);
386}
387
388static void vab_init(MachineState *machine)
389{
390 versatile_init(machine, 0x25e);
391}
392
393static void versatilepb_class_init(ObjectClass *oc, void *data)
394{
395 MachineClass *mc = MACHINE_CLASS(oc);
396
397 mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
398 mc->init = vpb_init;
399 mc->block_default_type = IF_SCSI;
400 mc->ignore_memory_transaction_failures = true;
401 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
402}
403
404static const TypeInfo versatilepb_type = {
405 .name = MACHINE_TYPE_NAME("versatilepb"),
406 .parent = TYPE_MACHINE,
407 .class_init = versatilepb_class_init,
408};
409
410static void versatileab_class_init(ObjectClass *oc, void *data)
411{
412 MachineClass *mc = MACHINE_CLASS(oc);
413
414 mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
415 mc->init = vab_init;
416 mc->block_default_type = IF_SCSI;
417 mc->ignore_memory_transaction_failures = true;
418 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
419}
420
421static const TypeInfo versatileab_type = {
422 .name = MACHINE_TYPE_NAME("versatileab"),
423 .parent = TYPE_MACHINE,
424 .class_init = versatileab_class_init,
425};
426
427static void versatile_machine_init(void)
428{
429 type_register_static(&versatilepb_type);
430 type_register_static(&versatileab_type);
431}
432
433type_init(versatile_machine_init)
434
435static void vpb_sic_class_init(ObjectClass *klass, void *data)
436{
437 DeviceClass *dc = DEVICE_CLASS(klass);
438
439 dc->vmsd = &vmstate_vpb_sic;
440}
441
442static const TypeInfo vpb_sic_info = {
443 .name = TYPE_VERSATILE_PB_SIC,
444 .parent = TYPE_SYS_BUS_DEVICE,
445 .instance_size = sizeof(vpb_sic_state),
446 .instance_init = vpb_sic_init,
447 .class_init = vpb_sic_class_init,
448};
449
450static void versatilepb_register_types(void)
451{
452 type_register_static(&vpb_sic_info);
453}
454
455type_init(versatilepb_register_types)
456