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/log.h"
27#include "cpu.h"
28#include "hw/cpu/a9mpcore.h"
29#include "hw/boards.h"
30#include "sysemu/sysemu.h"
31#include "hw/sysbus.h"
32#include "hw/arm/boot.h"
33#include "hw/loader.h"
34#include "hw/arm/exynos4210.h"
35#include "hw/sd/sdhci.h"
36#include "hw/usb/hcd-ehci.h"
37
38#define EXYNOS4210_CHIPID_ADDR 0x10000000
39
40
41#define EXYNOS4210_PWM_BASE_ADDR 0x139D0000
42
43
44#define EXYNOS4210_RTC_BASE_ADDR 0x10070000
45
46
47#define EXYNOS4210_MCT_BASE_ADDR 0x10050000
48
49
50#define EXYNOS4210_I2C_SHIFT 0x00010000
51#define EXYNOS4210_I2C_BASE_ADDR 0x13860000
52
53#define EXYNOS4210_I2C_INTG 27
54#define EXYNOS4210_HDMI_INTG 16
55
56
57#define EXYNOS4210_UART0_BASE_ADDR 0x13800000
58#define EXYNOS4210_UART1_BASE_ADDR 0x13810000
59#define EXYNOS4210_UART2_BASE_ADDR 0x13820000
60#define EXYNOS4210_UART3_BASE_ADDR 0x13830000
61#define EXYNOS4210_UART0_FIFO_SIZE 256
62#define EXYNOS4210_UART1_FIFO_SIZE 64
63#define EXYNOS4210_UART2_FIFO_SIZE 16
64#define EXYNOS4210_UART3_FIFO_SIZE 16
65
66#define EXYNOS4210_UART_INT_GRP 26
67
68
69#define EXYNOS4210_EXT_GIC_CPU_BASE_ADDR 0x10480000
70#define EXYNOS4210_EXT_GIC_DIST_BASE_ADDR 0x10490000
71
72
73#define EXYNOS4210_EXT_COMBINER_BASE_ADDR 0x10440000
74#define EXYNOS4210_INT_COMBINER_BASE_ADDR 0x10448000
75
76
77#define EXYNOS4210_SDHCI_CAPABILITIES 0x05E80080
78#define EXYNOS4210_SDHCI_BASE_ADDR 0x12510000
79#define EXYNOS4210_SDHCI_ADDR(n) (EXYNOS4210_SDHCI_BASE_ADDR + \
80 0x00010000 * (n))
81#define EXYNOS4210_SDHCI_NUMBER 4
82
83
84#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
85
86
87#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
88
89
90#define EXYNOS4210_RNG_BASE_ADDR 0x10830400
91
92
93#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
94
95
96#define EXYNOS4210_EHCI_BASE_ADDR 0x12580000
97
98
99#define EXYNOS4210_PL330_BASE0_ADDR 0x12680000
100#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
101#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
102
103static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
104 0x09, 0x00, 0x00, 0x00 };
105
106static uint64_t exynos4210_chipid_and_omr_read(void *opaque, hwaddr offset,
107 unsigned size)
108{
109 assert(offset < sizeof(chipid_and_omr));
110 return chipid_and_omr[offset];
111}
112
113static void exynos4210_chipid_and_omr_write(void *opaque, hwaddr offset,
114 uint64_t value, unsigned size)
115{
116 return;
117}
118
119static const MemoryRegionOps exynos4210_chipid_and_omr_ops = {
120 .read = exynos4210_chipid_and_omr_read,
121 .write = exynos4210_chipid_and_omr_write,
122 .endianness = DEVICE_NATIVE_ENDIAN,
123 .impl = {
124 .max_access_size = 1,
125 }
126};
127
128void exynos4210_write_secondary(ARMCPU *cpu,
129 const struct arm_boot_info *info)
130{
131 int n;
132 uint32_t smpboot[] = {
133 0xe59f3034,
134 0xe59f2034,
135 0xe59f0034,
136 0xe3a01001,
137 0xe5821000,
138 0xe5831000,
139 0xe3a010ff,
140 0xe5821004,
141 0xe5831004,
142 0xf57ff04f,
143 0xe320f003,
144 0xe5901000,
145 0xe1110001,
146 0x0afffffb,
147 0xe12fff11,
148 EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
149 0,
150 0
151 };
152 smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
153 smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
154 for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
155 smpboot[n] = tswap32(smpboot[n]);
156 }
157 rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
158 info->smp_loader_start);
159}
160
161static uint64_t exynos4210_calc_affinity(int cpu)
162{
163
164 return (0x9 << ARM_AFF1_SHIFT) | cpu;
165}
166
167static void pl330_create(uint32_t base, qemu_irq irq, int nreq)
168{
169 SysBusDevice *busdev;
170 DeviceState *dev;
171
172 dev = qdev_create(NULL, "pl330");
173 qdev_prop_set_uint8(dev, "num_periph_req", nreq);
174 qdev_init_nofail(dev);
175 busdev = SYS_BUS_DEVICE(dev);
176 sysbus_mmio_map(busdev, 0, base);
177 sysbus_connect_irq(busdev, 0, irq);
178}
179
180static void exynos4210_realize(DeviceState *socdev, Error **errp)
181{
182 Exynos4210State *s = EXYNOS4210_SOC(socdev);
183 MemoryRegion *system_mem = get_system_memory();
184 qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
185 SysBusDevice *busdev;
186 DeviceState *dev;
187 int i, n;
188
189 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
190 Object *cpuobj = object_new(ARM_CPU_TYPE_NAME("cortex-a9"));
191
192
193
194
195 if (object_property_find(cpuobj, "has_el3", NULL)) {
196 object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
197 }
198
199 s->cpu[n] = ARM_CPU(cpuobj);
200 object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
201 "mp-affinity", &error_abort);
202 object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
203 "reset-cbar", &error_abort);
204 object_property_set_bool(cpuobj, true, "realized", &error_fatal);
205 }
206
207
208
209 s->irq_table = exynos4210_init_irq(&s->irqs);
210
211
212 for (i = 0; i < EXYNOS4210_NCPUS; i++) {
213 dev = qdev_create(NULL, "exynos4210.irq_gate");
214 qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
215 qdev_init_nofail(dev);
216
217 for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
218 gate_irq[i][n] = qdev_get_gpio_in(dev, n);
219 }
220 busdev = SYS_BUS_DEVICE(dev);
221
222
223 sysbus_connect_irq(busdev, 0,
224 qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
225 }
226
227
228 dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
229 qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
230 qdev_init_nofail(dev);
231 busdev = SYS_BUS_DEVICE(dev);
232 sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
233 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
234 sysbus_connect_irq(busdev, n, gate_irq[n][0]);
235 }
236 for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
237 s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
238 }
239
240
241 sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
242
243
244 dev = qdev_create(NULL, "exynos4210.gic");
245 qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
246 qdev_init_nofail(dev);
247 busdev = SYS_BUS_DEVICE(dev);
248
249 sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
250
251 sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
252 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
253 sysbus_connect_irq(busdev, n, gate_irq[n][1]);
254 }
255 for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
256 s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
257 }
258
259
260 dev = qdev_create(NULL, "exynos4210.combiner");
261 qdev_init_nofail(dev);
262 busdev = SYS_BUS_DEVICE(dev);
263 for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
264 sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
265 }
266 exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
267 sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
268
269
270 dev = qdev_create(NULL, "exynos4210.combiner");
271 qdev_prop_set_uint32(dev, "external", 1);
272 qdev_init_nofail(dev);
273 busdev = SYS_BUS_DEVICE(dev);
274 for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
275 sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
276 }
277 exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
278 sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
279
280
281 exynos4210_init_board_irqs(&s->irqs);
282
283
284
285
286 memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops,
287 NULL, "exynos4210.chipid", sizeof(chipid_and_omr));
288 memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
289 &s->chipid_mem);
290
291
292 memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom",
293 EXYNOS4210_IROM_SIZE, &error_fatal);
294 memory_region_set_readonly(&s->irom_mem, true);
295 memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
296 &s->irom_mem);
297
298 memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias",
299 &s->irom_mem,
300 0,
301 EXYNOS4210_IROM_SIZE);
302 memory_region_set_readonly(&s->irom_alias_mem, true);
303 memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
304 &s->irom_alias_mem);
305
306
307 memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram",
308 EXYNOS4210_IRAM_SIZE, &error_fatal);
309 memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
310 &s->iram_mem);
311
312
313
314
315
316 sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
317
318 sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
319 sysbus_create_simple("exynos4210.rng", EXYNOS4210_RNG_BASE_ADDR, NULL);
320
321
322 sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
323 s->irq_table[exynos4210_get_irq(22, 0)],
324 s->irq_table[exynos4210_get_irq(22, 1)],
325 s->irq_table[exynos4210_get_irq(22, 2)],
326 s->irq_table[exynos4210_get_irq(22, 3)],
327 s->irq_table[exynos4210_get_irq(22, 4)],
328 NULL);
329
330 sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
331 s->irq_table[exynos4210_get_irq(23, 0)],
332 s->irq_table[exynos4210_get_irq(23, 1)],
333 NULL);
334
335
336 dev = qdev_create(NULL, "exynos4210.mct");
337 qdev_init_nofail(dev);
338 busdev = SYS_BUS_DEVICE(dev);
339 for (n = 0; n < 4; n++) {
340
341 sysbus_connect_irq(busdev, n,
342 s->irq_table[exynos4210_get_irq(1, 4 + n)]);
343 }
344
345 sysbus_connect_irq(busdev, 4,
346 s->irq_table[exynos4210_get_irq(51, 0)]);
347 sysbus_connect_irq(busdev, 5,
348 s->irq_table[exynos4210_get_irq(35, 3)]);
349 sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
350
351
352 for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
353 uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
354 qemu_irq i2c_irq;
355
356 if (n < 8) {
357 i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
358 } else {
359 i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
360 }
361
362 dev = qdev_create(NULL, "exynos4210.i2c");
363 qdev_init_nofail(dev);
364 busdev = SYS_BUS_DEVICE(dev);
365 sysbus_connect_irq(busdev, 0, i2c_irq);
366 sysbus_mmio_map(busdev, 0, addr);
367 s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c");
368 }
369
370
371
372 exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
373 EXYNOS4210_UART0_FIFO_SIZE, 0, serial_hd(0),
374 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
375
376 exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
377 EXYNOS4210_UART1_FIFO_SIZE, 1, serial_hd(1),
378 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
379
380 exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
381 EXYNOS4210_UART2_FIFO_SIZE, 2, serial_hd(2),
382 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
383
384 exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
385 EXYNOS4210_UART3_FIFO_SIZE, 3, serial_hd(3),
386 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
387
388
389 for (n = 0; n < EXYNOS4210_SDHCI_NUMBER; n++) {
390 DeviceState *carddev;
391 BlockBackend *blk;
392 DriveInfo *di;
393
394
395
396
397
398
399
400
401
402
403
404
405
406 dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
407 qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
408 qdev_init_nofail(dev);
409
410 busdev = SYS_BUS_DEVICE(dev);
411 sysbus_mmio_map(busdev, 0, EXYNOS4210_SDHCI_ADDR(n));
412 sysbus_connect_irq(busdev, 0, s->irq_table[exynos4210_get_irq(29, n)]);
413
414 di = drive_get(IF_SD, 0, n);
415 blk = di ? blk_by_legacy_dinfo(di) : NULL;
416 carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
417 qdev_prop_set_drive(carddev, "drive", blk, &error_abort);
418 qdev_init_nofail(carddev);
419 }
420
421
422 sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
423 s->irq_table[exynos4210_get_irq(11, 0)],
424 s->irq_table[exynos4210_get_irq(11, 1)],
425 s->irq_table[exynos4210_get_irq(11, 2)],
426 NULL);
427
428 sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
429 s->irq_table[exynos4210_get_irq(28, 3)]);
430
431
432 pl330_create(EXYNOS4210_PL330_BASE0_ADDR,
433 qemu_irq_invert(s->irq_table[exynos4210_get_irq(35, 1)]), 32);
434 pl330_create(EXYNOS4210_PL330_BASE1_ADDR,
435 qemu_irq_invert(s->irq_table[exynos4210_get_irq(36, 1)]), 32);
436 pl330_create(EXYNOS4210_PL330_BASE2_ADDR,
437 qemu_irq_invert(s->irq_table[exynos4210_get_irq(34, 1)]), 1);
438}
439
440static void exynos4210_class_init(ObjectClass *klass, void *data)
441{
442 DeviceClass *dc = DEVICE_CLASS(klass);
443
444 dc->realize = exynos4210_realize;
445}
446
447static const TypeInfo exynos4210_info = {
448 .name = TYPE_EXYNOS4210_SOC,
449 .parent = TYPE_SYS_BUS_DEVICE,
450 .instance_size = sizeof(Exynos4210State),
451 .class_init = exynos4210_class_init,
452};
453
454static void exynos4210_register_types(void)
455{
456 type_register_static(&exynos4210_info);
457}
458
459type_init(exynos4210_register_types)
460