Merge branch 'qemu-cvs'
[qemu-kvm/fedora.git] / hw / arm_sysctl.c
blob67ca154a30054ea432b8ceaffdebcdfffd22d7e8
1 /*
2 * Status and system control registers for ARM RealView/Versatile boards.
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
8 */
10 #include "hw.h"
11 #include "primecell.h"
12 #include "sysemu.h"
14 #define LOCK_VALUE 0xa05f
16 typedef struct {
17 uint32_t base;
18 uint32_t sys_id;
19 uint32_t leds;
20 uint16_t lockval;
21 uint32_t cfgdata1;
22 uint32_t cfgdata2;
23 uint32_t flags;
24 uint32_t nvflags;
25 uint32_t resetlevel;
26 } arm_sysctl_state;
28 static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
30 arm_sysctl_state *s = (arm_sysctl_state *)opaque;
32 offset -= s->base;
33 switch (offset) {
34 case 0x00: /* ID */
35 return s->sys_id;
36 case 0x04: /* SW */
37 /* General purpose hardware switches.
38 We don't have a useful way of exposing these to the user. */
39 return 0;
40 case 0x08: /* LED */
41 return s->leds;
42 case 0x20: /* LOCK */
43 return s->lockval;
44 case 0x0c: /* OSC0 */
45 case 0x10: /* OSC1 */
46 case 0x14: /* OSC2 */
47 case 0x18: /* OSC3 */
48 case 0x1c: /* OSC4 */
49 case 0x24: /* 100HZ */
50 /* ??? Implement these. */
51 return 0;
52 case 0x28: /* CFGDATA1 */
53 return s->cfgdata1;
54 case 0x2c: /* CFGDATA2 */
55 return s->cfgdata2;
56 case 0x30: /* FLAGS */
57 return s->flags;
58 case 0x38: /* NVFLAGS */
59 return s->nvflags;
60 case 0x40: /* RESETCTL */
61 return s->resetlevel;
62 case 0x44: /* PCICTL */
63 return 1;
64 case 0x48: /* MCI */
65 return 0;
66 case 0x4c: /* FLASH */
67 return 0;
68 case 0x50: /* CLCD */
69 return 0x1000;
70 case 0x54: /* CLCDSER */
71 return 0;
72 case 0x58: /* BOOTCS */
73 return 0;
74 case 0x5c: /* 24MHz */
75 /* ??? not implemented. */
76 return 0;
77 case 0x60: /* MISC */
78 return 0;
79 case 0x84: /* PROCID0 */
80 /* ??? Don't know what the proper value for the core tile ID is. */
81 return 0x02000000;
82 case 0x88: /* PROCID1 */
83 return 0xff000000;
84 case 0x64: /* DMAPSR0 */
85 case 0x68: /* DMAPSR1 */
86 case 0x6c: /* DMAPSR2 */
87 case 0x70: /* IOSEL */
88 case 0x74: /* PLDCTL */
89 case 0x80: /* BUSID */
90 case 0x8c: /* OSCRESET0 */
91 case 0x90: /* OSCRESET1 */
92 case 0x94: /* OSCRESET2 */
93 case 0x98: /* OSCRESET3 */
94 case 0x9c: /* OSCRESET4 */
95 case 0xc0: /* SYS_TEST_OSC0 */
96 case 0xc4: /* SYS_TEST_OSC1 */
97 case 0xc8: /* SYS_TEST_OSC2 */
98 case 0xcc: /* SYS_TEST_OSC3 */
99 case 0xd0: /* SYS_TEST_OSC4 */
100 return 0;
101 default:
102 printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
103 return 0;
107 static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
108 uint32_t val)
110 arm_sysctl_state *s = (arm_sysctl_state *)opaque;
111 offset -= s->base;
113 switch (offset) {
114 case 0x08: /* LED */
115 s->leds = val;
116 case 0x0c: /* OSC0 */
117 case 0x10: /* OSC1 */
118 case 0x14: /* OSC2 */
119 case 0x18: /* OSC3 */
120 case 0x1c: /* OSC4 */
121 /* ??? */
122 break;
123 case 0x20: /* LOCK */
124 if (val == LOCK_VALUE)
125 s->lockval = val;
126 else
127 s->lockval = val & 0x7fff;
128 break;
129 case 0x28: /* CFGDATA1 */
130 /* ??? Need to implement this. */
131 s->cfgdata1 = val;
132 break;
133 case 0x2c: /* CFGDATA2 */
134 /* ??? Need to implement this. */
135 s->cfgdata2 = val;
136 break;
137 case 0x30: /* FLAGSSET */
138 s->flags |= val;
139 break;
140 case 0x34: /* FLAGSCLR */
141 s->flags &= ~val;
142 break;
143 case 0x38: /* NVFLAGSSET */
144 s->nvflags |= val;
145 break;
146 case 0x3c: /* NVFLAGSCLR */
147 s->nvflags &= ~val;
148 break;
149 case 0x40: /* RESETCTL */
150 if (s->lockval == LOCK_VALUE) {
151 s->resetlevel = val;
152 if (val & 0x100)
153 qemu_system_reset_request ();
155 break;
156 case 0x44: /* PCICTL */
157 /* nothing to do. */
158 break;
159 case 0x4c: /* FLASH */
160 case 0x50: /* CLCD */
161 case 0x54: /* CLCDSER */
162 case 0x64: /* DMAPSR0 */
163 case 0x68: /* DMAPSR1 */
164 case 0x6c: /* DMAPSR2 */
165 case 0x70: /* IOSEL */
166 case 0x74: /* PLDCTL */
167 case 0x80: /* BUSID */
168 case 0x84: /* PROCID0 */
169 case 0x88: /* PROCID1 */
170 case 0x8c: /* OSCRESET0 */
171 case 0x90: /* OSCRESET1 */
172 case 0x94: /* OSCRESET2 */
173 case 0x98: /* OSCRESET3 */
174 case 0x9c: /* OSCRESET4 */
175 break;
176 default:
177 printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
178 return;
182 static CPUReadMemoryFunc *arm_sysctl_readfn[] = {
183 arm_sysctl_read,
184 arm_sysctl_read,
185 arm_sysctl_read
188 static CPUWriteMemoryFunc *arm_sysctl_writefn[] = {
189 arm_sysctl_write,
190 arm_sysctl_write,
191 arm_sysctl_write
194 void arm_sysctl_init(uint32_t base, uint32_t sys_id)
196 arm_sysctl_state *s;
197 int iomemtype;
199 s = (arm_sysctl_state *)qemu_mallocz(sizeof(arm_sysctl_state));
200 if (!s)
201 return;
202 s->base = base;
203 s->sys_id = sys_id;
204 /* The MPcore bootloader uses these flags to start secondary CPUs.
205 We don't use a bootloader, so do this here. */
206 s->flags = 3;
207 iomemtype = cpu_register_io_memory(0, arm_sysctl_readfn,
208 arm_sysctl_writefn, s);
209 cpu_register_physical_memory(base, 0x00001000, iomemtype);
210 /* ??? Save/restore. */