|
1 /* |
|
2 * Generic ARM Programmable Interrupt Controller support. |
|
3 * |
|
4 * Copyright (c) 2006 CodeSourcery. |
|
5 * Written by Paul Brook |
|
6 * |
|
7 * This code is licenced under the LGPL |
|
8 */ |
|
9 |
|
10 #include "hw.h" |
|
11 #include "arm-misc.h" |
|
12 #include "devtree.h" |
|
13 |
|
14 /* Stub functions for hardware that doesn't exist. */ |
|
15 void pic_info(void) |
|
16 { |
|
17 } |
|
18 |
|
19 void irq_info(void) |
|
20 { |
|
21 } |
|
22 |
|
23 |
|
24 /* Input 0 is IRQ and input 1 is FIQ. */ |
|
25 static void arm_pic_cpu_handler(void *opaque, int irq, int level) |
|
26 { |
|
27 CPUState *env = (CPUState *)opaque; |
|
28 switch (irq) { |
|
29 case ARM_PIC_CPU_IRQ: |
|
30 if (level) |
|
31 cpu_interrupt(env, CPU_INTERRUPT_HARD); |
|
32 else |
|
33 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
|
34 break; |
|
35 case ARM_PIC_CPU_FIQ: |
|
36 if (level) |
|
37 cpu_interrupt(env, CPU_INTERRUPT_FIQ); |
|
38 else |
|
39 cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ); |
|
40 break; |
|
41 default: |
|
42 cpu_abort(env, "arm_pic_cpu_handler: Bad interrput line %d\n", irq); |
|
43 } |
|
44 } |
|
45 |
|
46 /* FIXME: This is obsolete. */ |
|
47 qemu_irq *arm_pic_init_cpu(CPUState *env) |
|
48 { |
|
49 return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2); |
|
50 } |
|
51 |
|
52 /* Override default CPU settings with user supplied values. */ |
|
53 void arm_cpu_reset_dev(CPUState *env) |
|
54 { |
|
55 QEMUDevice *dev = env->qdev; |
|
56 char buf[64]; |
|
57 uint32_t v; |
|
58 int i; |
|
59 |
|
60 if (!dev) |
|
61 return; |
|
62 |
|
63 v = qdev_get_property_int(dev, "cp15,ctr"); |
|
64 if (v != 0xffffffffu) |
|
65 env->cp15.c0_cachetype = v; |
|
66 v = qdev_get_property_int(dev, "cp15,clid"); |
|
67 if (v != 0xffffffffu) |
|
68 env->cp15.c0_clid = v; |
|
69 for (i = 0; i < 7; i++) { |
|
70 sprintf(buf, "cp15,ccsid%d", i); |
|
71 v = qdev_get_property_int(dev, buf); |
|
72 if (v != 0xffffffffu) |
|
73 env->cp15.c0_ccsid[i << 1] = v; |
|
74 sprintf(buf, "cp15,ccsid%di", i); |
|
75 v = qdev_get_property_int(dev, buf); |
|
76 if (v != 0xffffffffu) |
|
77 env->cp15.c0_ccsid[(i << 1) + 1] = v; |
|
78 } |
|
79 |
|
80 } |
|
81 |
|
82 static void arm_cpu_create(QEMUDevice *dev) |
|
83 { |
|
84 CPUState *env; |
|
85 const char *name; |
|
86 char model[64]; |
|
87 int i; |
|
88 |
|
89 name = qdev_get_name(dev); |
|
90 if (strncmp(name, "ARM,", 4) == 0) |
|
91 name += 4; |
|
92 |
|
93 i = 0; |
|
94 while (name[i] && name[i] != '@' && i < 63) { |
|
95 model[i] = tolower(name[i]); |
|
96 i++; |
|
97 } |
|
98 model[i] = 0; |
|
99 |
|
100 env = cpu_arm_init(model, dev); |
|
101 |
|
102 if (!env) { |
|
103 fprintf(stderr, "Unable to find CPU definition %s\n", model); |
|
104 exit(1); |
|
105 } |
|
106 |
|
107 qdev_create_interrupts(dev, arm_pic_cpu_handler, env, 2); |
|
108 } |
|
109 |
|
110 void cpu_device_register(void) |
|
111 { |
|
112 int i; |
|
113 char buf[13]; |
|
114 |
|
115 cpu_device_class = qdev_new("cpu", arm_cpu_create, 0); |
|
116 qdev_add_property_int(cpu_device_class, "cp15,ctr", 0xffffffffu); |
|
117 qdev_add_property_int(cpu_device_class, "cp15,clid", 0xffffffffu); |
|
118 for (i = 0; i < 7; i++) { |
|
119 sprintf(buf, "cp15,ccsid%d", i); |
|
120 qdev_add_property_int(cpu_device_class, buf, 0xffffffffu); |
|
121 sprintf(buf, "cp15,ccsid%di", i); |
|
122 qdev_add_property_int(cpu_device_class, buf, 0xffffffffu); |
|
123 } |
|
124 } |