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