]> Git Repo - qemu.git/blob - hw/integratorcp.c
integratorcp: convert to memory API (RAM/flash only)
[qemu.git] / hw / integratorcp.c
1 /*
2  * ARM Integrator CP System emulation.
3  *
4  * Copyright (c) 2005-2007 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the GPL
8  */
9
10 #include "sysbus.h"
11 #include "primecell.h"
12 #include "devices.h"
13 #include "boards.h"
14 #include "arm-misc.h"
15 #include "net.h"
16 #include "exec-memory.h"
17
18 typedef struct {
19     SysBusDevice busdev;
20     uint32_t memsz;
21     MemoryRegion flash;
22     bool flash_mapped;
23     uint32_t cm_osc;
24     uint32_t cm_ctrl;
25     uint32_t cm_lock;
26     uint32_t cm_auxosc;
27     uint32_t cm_sdram;
28     uint32_t cm_init;
29     uint32_t cm_flags;
30     uint32_t cm_nvflags;
31     uint32_t int_level;
32     uint32_t irq_enabled;
33     uint32_t fiq_enabled;
34 } integratorcm_state;
35
36 static uint8_t integrator_spd[128] = {
37    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
38    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
39 };
40
41 static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
42 {
43     integratorcm_state *s = (integratorcm_state *)opaque;
44     if (offset >= 0x100 && offset < 0x200) {
45         /* CM_SPD */
46         if (offset >= 0x180)
47             return 0;
48         return integrator_spd[offset >> 2];
49     }
50     switch (offset >> 2) {
51     case 0: /* CM_ID */
52         return 0x411a3001;
53     case 1: /* CM_PROC */
54         return 0;
55     case 2: /* CM_OSC */
56         return s->cm_osc;
57     case 3: /* CM_CTRL */
58         return s->cm_ctrl;
59     case 4: /* CM_STAT */
60         return 0x00100000;
61     case 5: /* CM_LOCK */
62         if (s->cm_lock == 0xa05f) {
63             return 0x1a05f;
64         } else {
65             return s->cm_lock;
66         }
67     case 6: /* CM_LMBUSCNT */
68         /* ??? High frequency timer.  */
69         hw_error("integratorcm_read: CM_LMBUSCNT");
70     case 7: /* CM_AUXOSC */
71         return s->cm_auxosc;
72     case 8: /* CM_SDRAM */
73         return s->cm_sdram;
74     case 9: /* CM_INIT */
75         return s->cm_init;
76     case 10: /* CM_REFCT */
77         /* ??? High frequency timer.  */
78         hw_error("integratorcm_read: CM_REFCT");
79     case 12: /* CM_FLAGS */
80         return s->cm_flags;
81     case 14: /* CM_NVFLAGS */
82         return s->cm_nvflags;
83     case 16: /* CM_IRQ_STAT */
84         return s->int_level & s->irq_enabled;
85     case 17: /* CM_IRQ_RSTAT */
86         return s->int_level;
87     case 18: /* CM_IRQ_ENSET */
88         return s->irq_enabled;
89     case 20: /* CM_SOFT_INTSET */
90         return s->int_level & 1;
91     case 24: /* CM_FIQ_STAT */
92         return s->int_level & s->fiq_enabled;
93     case 25: /* CM_FIQ_RSTAT */
94         return s->int_level;
95     case 26: /* CM_FIQ_ENSET */
96         return s->fiq_enabled;
97     case 32: /* CM_VOLTAGE_CTL0 */
98     case 33: /* CM_VOLTAGE_CTL1 */
99     case 34: /* CM_VOLTAGE_CTL2 */
100     case 35: /* CM_VOLTAGE_CTL3 */
101         /* ??? Voltage control unimplemented.  */
102         return 0;
103     default:
104         hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
105                  (int)offset);
106         return 0;
107     }
108 }
109
110 static void integratorcm_do_remap(integratorcm_state *s, int flash)
111 {
112     if (flash) {
113         if (s->flash_mapped) {
114             sysbus_del_memory(&s->busdev, &s->flash);
115             s->flash_mapped = false;
116         }
117     } else {
118         if (!s->flash_mapped) {
119             sysbus_add_memory_overlap(&s->busdev, 0, &s->flash, 1);
120             s->flash_mapped = true;
121         }
122     }
123     //??? tlb_flush (cpu_single_env, 1);
124 }
125
126 static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
127 {
128     if (value & 8) {
129         hw_error("Board reset\n");
130     }
131     if ((s->cm_init ^ value) & 4) {
132         integratorcm_do_remap(s, (value & 4) == 0);
133     }
134     if ((s->cm_init ^ value) & 1) {
135         printf("Green LED %s\n", (value & 1) ? "on" : "off");
136     }
137     s->cm_init = (s->cm_init & ~ 5) | (value ^ 5);
138 }
139
140 static void integratorcm_update(integratorcm_state *s)
141 {
142     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
143        are active.  */
144     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
145         hw_error("Core module interrupt\n");
146 }
147
148 static void integratorcm_write(void *opaque, target_phys_addr_t offset,
149                                uint32_t value)
150 {
151     integratorcm_state *s = (integratorcm_state *)opaque;
152     switch (offset >> 2) {
153     case 2: /* CM_OSC */
154         if (s->cm_lock == 0xa05f)
155             s->cm_osc = value;
156         break;
157     case 3: /* CM_CTRL */
158         integratorcm_set_ctrl(s, value);
159         break;
160     case 5: /* CM_LOCK */
161         s->cm_lock = value & 0xffff;
162         break;
163     case 7: /* CM_AUXOSC */
164         if (s->cm_lock == 0xa05f)
165             s->cm_auxosc = value;
166         break;
167     case 8: /* CM_SDRAM */
168         s->cm_sdram = value;
169         break;
170     case 9: /* CM_INIT */
171         /* ??? This can change the memory bus frequency.  */
172         s->cm_init = value;
173         break;
174     case 12: /* CM_FLAGSS */
175         s->cm_flags |= value;
176         break;
177     case 13: /* CM_FLAGSC */
178         s->cm_flags &= ~value;
179         break;
180     case 14: /* CM_NVFLAGSS */
181         s->cm_nvflags |= value;
182         break;
183     case 15: /* CM_NVFLAGSS */
184         s->cm_nvflags &= ~value;
185         break;
186     case 18: /* CM_IRQ_ENSET */
187         s->irq_enabled |= value;
188         integratorcm_update(s);
189         break;
190     case 19: /* CM_IRQ_ENCLR */
191         s->irq_enabled &= ~value;
192         integratorcm_update(s);
193         break;
194     case 20: /* CM_SOFT_INTSET */
195         s->int_level |= (value & 1);
196         integratorcm_update(s);
197         break;
198     case 21: /* CM_SOFT_INTCLR */
199         s->int_level &= ~(value & 1);
200         integratorcm_update(s);
201         break;
202     case 26: /* CM_FIQ_ENSET */
203         s->fiq_enabled |= value;
204         integratorcm_update(s);
205         break;
206     case 27: /* CM_FIQ_ENCLR */
207         s->fiq_enabled &= ~value;
208         integratorcm_update(s);
209         break;
210     case 32: /* CM_VOLTAGE_CTL0 */
211     case 33: /* CM_VOLTAGE_CTL1 */
212     case 34: /* CM_VOLTAGE_CTL2 */
213     case 35: /* CM_VOLTAGE_CTL3 */
214         /* ??? Voltage control unimplemented.  */
215         break;
216     default:
217         hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
218                  (int)offset);
219         break;
220     }
221 }
222
223 /* Integrator/CM control registers.  */
224
225 static CPUReadMemoryFunc * const integratorcm_readfn[] = {
226    integratorcm_read,
227    integratorcm_read,
228    integratorcm_read
229 };
230
231 static CPUWriteMemoryFunc * const integratorcm_writefn[] = {
232    integratorcm_write,
233    integratorcm_write,
234    integratorcm_write
235 };
236
237 static int integratorcm_init(SysBusDevice *dev)
238 {
239     int iomemtype;
240     integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
241
242     s->cm_osc = 0x01000048;
243     /* ??? What should the high bits of this value be?  */
244     s->cm_auxosc = 0x0007feff;
245     s->cm_sdram = 0x00011122;
246     if (s->memsz >= 256) {
247         integrator_spd[31] = 64;
248         s->cm_sdram |= 0x10;
249     } else if (s->memsz >= 128) {
250         integrator_spd[31] = 32;
251         s->cm_sdram |= 0x0c;
252     } else if (s->memsz >= 64) {
253         integrator_spd[31] = 16;
254         s->cm_sdram |= 0x08;
255     } else if (s->memsz >= 32) {
256         integrator_spd[31] = 4;
257         s->cm_sdram |= 0x04;
258     } else {
259         integrator_spd[31] = 2;
260     }
261     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
262     s->cm_init = 0x00000112;
263     memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
264     s->flash_mapped = false;
265
266     iomemtype = cpu_register_io_memory(integratorcm_readfn,
267                                        integratorcm_writefn, s,
268                                        DEVICE_NATIVE_ENDIAN);
269     sysbus_init_mmio(dev, 0x00800000, iomemtype);
270     integratorcm_do_remap(s, 1);
271     /* ??? Save/restore.  */
272     return 0;
273 }
274
275 /* Integrator/CP hardware emulation.  */
276 /* Primary interrupt controller.  */
277
278 typedef struct icp_pic_state
279 {
280   SysBusDevice busdev;
281   uint32_t level;
282   uint32_t irq_enabled;
283   uint32_t fiq_enabled;
284   qemu_irq parent_irq;
285   qemu_irq parent_fiq;
286 } icp_pic_state;
287
288 static void icp_pic_update(icp_pic_state *s)
289 {
290     uint32_t flags;
291
292     flags = (s->level & s->irq_enabled);
293     qemu_set_irq(s->parent_irq, flags != 0);
294     flags = (s->level & s->fiq_enabled);
295     qemu_set_irq(s->parent_fiq, flags != 0);
296 }
297
298 static void icp_pic_set_irq(void *opaque, int irq, int level)
299 {
300     icp_pic_state *s = (icp_pic_state *)opaque;
301     if (level)
302         s->level |= 1 << irq;
303     else
304         s->level &= ~(1 << irq);
305     icp_pic_update(s);
306 }
307
308 static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
309 {
310     icp_pic_state *s = (icp_pic_state *)opaque;
311
312     switch (offset >> 2) {
313     case 0: /* IRQ_STATUS */
314         return s->level & s->irq_enabled;
315     case 1: /* IRQ_RAWSTAT */
316         return s->level;
317     case 2: /* IRQ_ENABLESET */
318         return s->irq_enabled;
319     case 4: /* INT_SOFTSET */
320         return s->level & 1;
321     case 8: /* FRQ_STATUS */
322         return s->level & s->fiq_enabled;
323     case 9: /* FRQ_RAWSTAT */
324         return s->level;
325     case 10: /* FRQ_ENABLESET */
326         return s->fiq_enabled;
327     case 3: /* IRQ_ENABLECLR */
328     case 5: /* INT_SOFTCLR */
329     case 11: /* FRQ_ENABLECLR */
330     default:
331         printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
332         return 0;
333     }
334 }
335
336 static void icp_pic_write(void *opaque, target_phys_addr_t offset,
337                           uint32_t value)
338 {
339     icp_pic_state *s = (icp_pic_state *)opaque;
340
341     switch (offset >> 2) {
342     case 2: /* IRQ_ENABLESET */
343         s->irq_enabled |= value;
344         break;
345     case 3: /* IRQ_ENABLECLR */
346         s->irq_enabled &= ~value;
347         break;
348     case 4: /* INT_SOFTSET */
349         if (value & 1)
350             icp_pic_set_irq(s, 0, 1);
351         break;
352     case 5: /* INT_SOFTCLR */
353         if (value & 1)
354             icp_pic_set_irq(s, 0, 0);
355         break;
356     case 10: /* FRQ_ENABLESET */
357         s->fiq_enabled |= value;
358         break;
359     case 11: /* FRQ_ENABLECLR */
360         s->fiq_enabled &= ~value;
361         break;
362     case 0: /* IRQ_STATUS */
363     case 1: /* IRQ_RAWSTAT */
364     case 8: /* FRQ_STATUS */
365     case 9: /* FRQ_RAWSTAT */
366     default:
367         printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
368         return;
369     }
370     icp_pic_update(s);
371 }
372
373 static CPUReadMemoryFunc * const icp_pic_readfn[] = {
374    icp_pic_read,
375    icp_pic_read,
376    icp_pic_read
377 };
378
379 static CPUWriteMemoryFunc * const icp_pic_writefn[] = {
380    icp_pic_write,
381    icp_pic_write,
382    icp_pic_write
383 };
384
385 static int icp_pic_init(SysBusDevice *dev)
386 {
387     icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
388     int iomemtype;
389
390     qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
391     sysbus_init_irq(dev, &s->parent_irq);
392     sysbus_init_irq(dev, &s->parent_fiq);
393     iomemtype = cpu_register_io_memory(icp_pic_readfn,
394                                        icp_pic_writefn, s,
395                                        DEVICE_NATIVE_ENDIAN);
396     sysbus_init_mmio(dev, 0x00800000, iomemtype);
397     return 0;
398 }
399
400 /* CP control registers.  */
401 static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
402 {
403     switch (offset >> 2) {
404     case 0: /* CP_IDFIELD */
405         return 0x41034003;
406     case 1: /* CP_FLASHPROG */
407         return 0;
408     case 2: /* CP_INTREG */
409         return 0;
410     case 3: /* CP_DECODE */
411         return 0x11;
412     default:
413         hw_error("icp_control_read: Bad offset %x\n", (int)offset);
414         return 0;
415     }
416 }
417
418 static void icp_control_write(void *opaque, target_phys_addr_t offset,
419                           uint32_t value)
420 {
421     switch (offset >> 2) {
422     case 1: /* CP_FLASHPROG */
423     case 2: /* CP_INTREG */
424     case 3: /* CP_DECODE */
425         /* Nothing interesting implemented yet.  */
426         break;
427     default:
428         hw_error("icp_control_write: Bad offset %x\n", (int)offset);
429     }
430 }
431 static CPUReadMemoryFunc * const icp_control_readfn[] = {
432    icp_control_read,
433    icp_control_read,
434    icp_control_read
435 };
436
437 static CPUWriteMemoryFunc * const icp_control_writefn[] = {
438    icp_control_write,
439    icp_control_write,
440    icp_control_write
441 };
442
443 static void icp_control_init(uint32_t base)
444 {
445     int iomemtype;
446
447     iomemtype = cpu_register_io_memory(icp_control_readfn,
448                                        icp_control_writefn, NULL,
449                                        DEVICE_NATIVE_ENDIAN);
450     cpu_register_physical_memory(base, 0x00800000, iomemtype);
451     /* ??? Save/restore.  */
452 }
453
454
455 /* Board init.  */
456
457 static struct arm_boot_info integrator_binfo = {
458     .loader_start = 0x0,
459     .board_id = 0x113,
460 };
461
462 static void integratorcp_init(ram_addr_t ram_size,
463                      const char *boot_device,
464                      const char *kernel_filename, const char *kernel_cmdline,
465                      const char *initrd_filename, const char *cpu_model)
466 {
467     CPUState *env;
468     MemoryRegion *address_space_mem = get_system_memory();
469     MemoryRegion *ram = g_new(MemoryRegion, 1);
470     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
471     qemu_irq pic[32];
472     qemu_irq *cpu_pic;
473     DeviceState *dev;
474     int i;
475
476     if (!cpu_model)
477         cpu_model = "arm926";
478     env = cpu_init(cpu_model);
479     if (!env) {
480         fprintf(stderr, "Unable to find CPU definition\n");
481         exit(1);
482     }
483     memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
484     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
485     /* ??? RAM should repeat to fill physical memory space.  */
486     /* SDRAM at address zero*/
487     memory_region_add_subregion(address_space_mem, 0, ram);
488     /* And again at address 0x80000000 */
489     memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
490     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
491
492     dev = qdev_create(NULL, "integrator_core");
493     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
494     qdev_init_nofail(dev);
495     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
496
497     cpu_pic = arm_pic_init_cpu(env);
498     dev = sysbus_create_varargs("integrator_pic", 0x14000000,
499                                 cpu_pic[ARM_PIC_CPU_IRQ],
500                                 cpu_pic[ARM_PIC_CPU_FIQ], NULL);
501     for (i = 0; i < 32; i++) {
502         pic[i] = qdev_get_gpio_in(dev, i);
503     }
504     sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
505     sysbus_create_varargs("integrator_pit", 0x13000000,
506                           pic[5], pic[6], pic[7], NULL);
507     sysbus_create_simple("pl031", 0x15000000, pic[8]);
508     sysbus_create_simple("pl011", 0x16000000, pic[1]);
509     sysbus_create_simple("pl011", 0x17000000, pic[2]);
510     icp_control_init(0xcb000000);
511     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
512     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
513     sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
514     if (nd_table[0].vlan)
515         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
516
517     sysbus_create_simple("pl110", 0xc0000000, pic[22]);
518
519     integrator_binfo.ram_size = ram_size;
520     integrator_binfo.kernel_filename = kernel_filename;
521     integrator_binfo.kernel_cmdline = kernel_cmdline;
522     integrator_binfo.initrd_filename = initrd_filename;
523     arm_load_kernel(env, &integrator_binfo);
524 }
525
526 static QEMUMachine integratorcp_machine = {
527     .name = "integratorcp",
528     .desc = "ARM Integrator/CP (ARM926EJ-S)",
529     .init = integratorcp_init,
530     .is_default = 1,
531 };
532
533 static void integratorcp_machine_init(void)
534 {
535     qemu_register_machine(&integratorcp_machine);
536 }
537
538 machine_init(integratorcp_machine_init);
539
540 static SysBusDeviceInfo core_info = {
541     .init = integratorcm_init,
542     .qdev.name  = "integrator_core",
543     .qdev.size  = sizeof(integratorcm_state),
544     .qdev.props = (Property[]) {
545         DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
546         DEFINE_PROP_END_OF_LIST(),
547     }
548 };
549
550 static void integratorcp_register_devices(void)
551 {
552     sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init);
553     sysbus_register_withprop(&core_info);
554 }
555
556 device_init(integratorcp_register_devices)
This page took 0.053521 seconds and 4 git commands to generate.