1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu/osdep.h"
25#include "qapi/error.h"
26#include "qemu-common.h"
27#include "cpu.h"
28#include "hw/boards.h"
29#include "sysemu/sysemu.h"
30#include "hw/sysbus.h"
31#include "hw/arm/arm.h"
32#include "hw/loader.h"
33#include "hw/arm/exynos4210.h"
34#include "hw/usb/hcd-ehci.h"
35
36#define EXYNOS4210_CHIPID_ADDR 0x10000000
37
38
39#define EXYNOS4210_PWM_BASE_ADDR 0x139D0000
40
41
42#define EXYNOS4210_RTC_BASE_ADDR 0x10070000
43
44
45#define EXYNOS4210_MCT_BASE_ADDR 0x10050000
46
47
48#define EXYNOS4210_I2C_SHIFT 0x00010000
49#define EXYNOS4210_I2C_BASE_ADDR 0x13860000
50
51#define EXYNOS4210_I2C_INTG 27
52#define EXYNOS4210_HDMI_INTG 16
53
54
55#define EXYNOS4210_UART0_BASE_ADDR 0x13800000
56#define EXYNOS4210_UART1_BASE_ADDR 0x13810000
57#define EXYNOS4210_UART2_BASE_ADDR 0x13820000
58#define EXYNOS4210_UART3_BASE_ADDR 0x13830000
59#define EXYNOS4210_UART0_FIFO_SIZE 256
60#define EXYNOS4210_UART1_FIFO_SIZE 64
61#define EXYNOS4210_UART2_FIFO_SIZE 16
62#define EXYNOS4210_UART3_FIFO_SIZE 16
63
64#define EXYNOS4210_UART_INT_GRP 26
65
66
67#define EXYNOS4210_EXT_GIC_CPU_BASE_ADDR 0x10480000
68#define EXYNOS4210_EXT_GIC_DIST_BASE_ADDR 0x10490000
69
70
71#define EXYNOS4210_EXT_COMBINER_BASE_ADDR 0x10440000
72#define EXYNOS4210_INT_COMBINER_BASE_ADDR 0x10448000
73
74
75#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
76
77
78#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
79
80
81#define EXYNOS4210_EHCI_BASE_ADDR 0x12580000
82
83static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
84 0x09, 0x00, 0x00, 0x00 };
85
86static uint64_t exynos4210_chipid_and_omr_read(void *opaque, hwaddr offset,
87 unsigned size)
88{
89 assert(offset < sizeof(chipid_and_omr));
90 return chipid_and_omr[offset];
91}
92
93static void exynos4210_chipid_and_omr_write(void *opaque, hwaddr offset,
94 uint64_t value, unsigned size)
95{
96 return;
97}
98
99static const MemoryRegionOps exynos4210_chipid_and_omr_ops = {
100 .read = exynos4210_chipid_and_omr_read,
101 .write = exynos4210_chipid_and_omr_write,
102 .endianness = DEVICE_NATIVE_ENDIAN,
103 .impl = {
104 .max_access_size = 1,
105 }
106};
107
108void exynos4210_write_secondary(ARMCPU *cpu,
109 const struct arm_boot_info *info)
110{
111 int n;
112 uint32_t smpboot[] = {
113 0xe59f3034,
114 0xe59f2034,
115 0xe59f0034,
116 0xe3a01001,
117 0xe5821000,
118 0xe5831000,
119 0xe3a010ff,
120 0xe5821004,
121 0xe5831004,
122 0xf57ff04f,
123 0xe320f003,
124 0xe5901000,
125 0xe1110001,
126 0x0afffffb,
127 0xe12fff11,
128 EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
129 0,
130 0
131 };
132 smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
133 smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
134 for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
135 smpboot[n] = tswap32(smpboot[n]);
136 }
137 rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
138 info->smp_loader_start);
139}
140
141Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
142 unsigned long ram_size)
143{
144 int i, n;
145 Exynos4210State *s = g_new(Exynos4210State, 1);
146 qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
147 unsigned long mem_size;
148 DeviceState *dev;
149 SysBusDevice *busdev;
150 ObjectClass *cpu_oc;
151
152 cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9");
153 assert(cpu_oc);
154
155 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
156 Object *cpuobj = object_new(object_class_get_name(cpu_oc));
157
158
159
160
161 if (object_property_find(cpuobj, "has_el3", NULL)) {
162 object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
163 }
164
165 s->cpu[n] = ARM_CPU(cpuobj);
166 object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
167 "reset-cbar", &error_abort);
168 object_property_set_bool(cpuobj, true, "realized", &error_fatal);
169 }
170
171
172
173 s->irq_table = exynos4210_init_irq(&s->irqs);
174
175
176 for (i = 0; i < EXYNOS4210_NCPUS; i++) {
177 dev = qdev_create(NULL, "exynos4210.irq_gate");
178 qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
179 qdev_init_nofail(dev);
180
181 for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
182 gate_irq[i][n] = qdev_get_gpio_in(dev, n);
183 }
184 busdev = SYS_BUS_DEVICE(dev);
185
186
187 sysbus_connect_irq(busdev, 0,
188 qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
189 }
190
191
192 dev = qdev_create(NULL, "a9mpcore_priv");
193 qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
194 qdev_init_nofail(dev);
195 busdev = SYS_BUS_DEVICE(dev);
196 sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
197 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
198 sysbus_connect_irq(busdev, n, gate_irq[n][0]);
199 }
200 for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
201 s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
202 }
203
204
205 sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
206
207
208 dev = qdev_create(NULL, "exynos4210.gic");
209 qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
210 qdev_init_nofail(dev);
211 busdev = SYS_BUS_DEVICE(dev);
212
213 sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
214
215 sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
216 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
217 sysbus_connect_irq(busdev, n, gate_irq[n][1]);
218 }
219 for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
220 s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
221 }
222
223
224 dev = qdev_create(NULL, "exynos4210.combiner");
225 qdev_init_nofail(dev);
226 busdev = SYS_BUS_DEVICE(dev);
227 for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
228 sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
229 }
230 exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
231 sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
232
233
234 dev = qdev_create(NULL, "exynos4210.combiner");
235 qdev_prop_set_uint32(dev, "external", 1);
236 qdev_init_nofail(dev);
237 busdev = SYS_BUS_DEVICE(dev);
238 for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
239 sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
240 }
241 exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
242 sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
243
244
245 exynos4210_init_board_irqs(&s->irqs);
246
247
248
249
250 memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops,
251 NULL, "exynos4210.chipid", sizeof(chipid_and_omr));
252 memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
253 &s->chipid_mem);
254
255
256 memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom",
257 EXYNOS4210_IROM_SIZE, &error_fatal);
258 vmstate_register_ram_global(&s->irom_mem);
259 memory_region_set_readonly(&s->irom_mem, true);
260 memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
261 &s->irom_mem);
262
263 memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias",
264 &s->irom_mem,
265 0,
266 EXYNOS4210_IROM_SIZE);
267 memory_region_set_readonly(&s->irom_alias_mem, true);
268 memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
269 &s->irom_alias_mem);
270
271
272 memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram",
273 EXYNOS4210_IRAM_SIZE, &error_fatal);
274 vmstate_register_ram_global(&s->iram_mem);
275 memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
276 &s->iram_mem);
277
278
279 mem_size = ram_size;
280 if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
281 memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
282 mem_size - EXYNOS4210_DRAM_MAX_SIZE, &error_fatal);
283 vmstate_register_ram_global(&s->dram1_mem);
284 memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
285 &s->dram1_mem);
286 mem_size = EXYNOS4210_DRAM_MAX_SIZE;
287 }
288 memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size,
289 &error_fatal);
290 vmstate_register_ram_global(&s->dram0_mem);
291 memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
292 &s->dram0_mem);
293
294
295
296
297
298 sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
299
300
301 sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
302 s->irq_table[exynos4210_get_irq(22, 0)],
303 s->irq_table[exynos4210_get_irq(22, 1)],
304 s->irq_table[exynos4210_get_irq(22, 2)],
305 s->irq_table[exynos4210_get_irq(22, 3)],
306 s->irq_table[exynos4210_get_irq(22, 4)],
307 NULL);
308
309 sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
310 s->irq_table[exynos4210_get_irq(23, 0)],
311 s->irq_table[exynos4210_get_irq(23, 1)],
312 NULL);
313
314
315 dev = qdev_create(NULL, "exynos4210.mct");
316 qdev_init_nofail(dev);
317 busdev = SYS_BUS_DEVICE(dev);
318 for (n = 0; n < 4; n++) {
319
320 sysbus_connect_irq(busdev, n,
321 s->irq_table[exynos4210_get_irq(1, 4 + n)]);
322 }
323
324 sysbus_connect_irq(busdev, 4,
325 s->irq_table[exynos4210_get_irq(51, 0)]);
326 sysbus_connect_irq(busdev, 5,
327 s->irq_table[exynos4210_get_irq(35, 3)]);
328 sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
329
330
331 for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
332 uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
333 qemu_irq i2c_irq;
334
335 if (n < 8) {
336 i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
337 } else {
338 i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
339 }
340
341 dev = qdev_create(NULL, "exynos4210.i2c");
342 qdev_init_nofail(dev);
343 busdev = SYS_BUS_DEVICE(dev);
344 sysbus_connect_irq(busdev, 0, i2c_irq);
345 sysbus_mmio_map(busdev, 0, addr);
346 s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c");
347 }
348
349
350
351 exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
352 EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
353 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
354
355 exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
356 EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
357 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
358
359 exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
360 EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
361 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
362
363 exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
364 EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
365 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
366
367
368 sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
369 s->irq_table[exynos4210_get_irq(11, 0)],
370 s->irq_table[exynos4210_get_irq(11, 1)],
371 s->irq_table[exynos4210_get_irq(11, 2)],
372 NULL);
373
374 sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
375 s->irq_table[exynos4210_get_irq(28, 3)]);
376
377 return s;
378}
379