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 lsi53c895a_create(pci_bus);
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 sysbus_create_simple("pl080", 0x10130000, pic[17]);
291 sysbus_create_simple("sp804", 0x101e2000, pic[4]);
292 sysbus_create_simple("sp804", 0x101e3000, pic[5]);
293
294 sysbus_create_simple("pl061", 0x101e4000, pic[6]);
295 sysbus_create_simple("pl061", 0x101e5000, pic[7]);
296 sysbus_create_simple("pl061", 0x101e6000, pic[8]);
297 sysbus_create_simple("pl061", 0x101e7000, pic[9]);
298
299
300
301 dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
302
303 qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
304
305 sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
306 sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
307
308
309 sysbus_create_simple("pl031", 0x101e8000, pic[10]);
310
311 dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
312 i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
313 i2c_create_slave(i2c, "ds1338", 0x68);
314
315
316 pl041 = qdev_create(NULL, "pl041");
317 qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
318 qdev_init_nofail(pl041);
319 sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
320 sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
321
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 dinfo = drive_get(IF_PFLASH, 0, 0);
360 if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
361 VERSATILE_FLASH_SIZE,
362 dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
363 VERSATILE_FLASH_SECT_SIZE,
364 VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
365 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
366 fprintf(stderr, "qemu: Error registering flash memory.\n");
367 }
368
369 versatile_binfo.ram_size = machine->ram_size;
370 versatile_binfo.kernel_filename = machine->kernel_filename;
371 versatile_binfo.kernel_cmdline = machine->kernel_cmdline;
372 versatile_binfo.initrd_filename = machine->initrd_filename;
373 versatile_binfo.board_id = board_id;
374 arm_load_kernel(cpu, &versatile_binfo);
375}
376
377static void vpb_init(MachineState *machine)
378{
379 versatile_init(machine, 0x183);
380}
381
382static void vab_init(MachineState *machine)
383{
384 versatile_init(machine, 0x25e);
385}
386
387static void versatilepb_class_init(ObjectClass *oc, void *data)
388{
389 MachineClass *mc = MACHINE_CLASS(oc);
390
391 mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
392 mc->init = vpb_init;
393 mc->block_default_type = IF_SCSI;
394 mc->ignore_memory_transaction_failures = true;
395 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
396}
397
398static const TypeInfo versatilepb_type = {
399 .name = MACHINE_TYPE_NAME("versatilepb"),
400 .parent = TYPE_MACHINE,
401 .class_init = versatilepb_class_init,
402};
403
404static void versatileab_class_init(ObjectClass *oc, void *data)
405{
406 MachineClass *mc = MACHINE_CLASS(oc);
407
408 mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
409 mc->init = vab_init;
410 mc->block_default_type = IF_SCSI;
411 mc->ignore_memory_transaction_failures = true;
412 mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
413}
414
415static const TypeInfo versatileab_type = {
416 .name = MACHINE_TYPE_NAME("versatileab"),
417 .parent = TYPE_MACHINE,
418 .class_init = versatileab_class_init,
419};
420
421static void versatile_machine_init(void)
422{
423 type_register_static(&versatilepb_type);
424 type_register_static(&versatileab_type);
425}
426
427type_init(versatile_machine_init)
428
429static void vpb_sic_class_init(ObjectClass *klass, void *data)
430{
431 DeviceClass *dc = DEVICE_CLASS(klass);
432
433 dc->vmsd = &vmstate_vpb_sic;
434}
435
436static const TypeInfo vpb_sic_info = {
437 .name = TYPE_VERSATILE_PB_SIC,
438 .parent = TYPE_SYS_BUS_DEVICE,
439 .instance_size = sizeof(vpb_sic_state),
440 .instance_init = vpb_sic_init,
441 .class_init = vpb_sic_class_init,
442};
443
444static void versatilepb_register_types(void)
445{
446 type_register_static(&vpb_sic_info);
447}
448
449type_init(versatilepb_register_types)
450