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