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