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 void pl330_create(uint32_t base, qemu_irq irq, int nreq)
170{
171 SysBusDevice *busdev;
172 DeviceState *dev;
173
174 dev = qdev_create(NULL, "pl330");
175 qdev_prop_set_uint8(dev, "num_periph_req", nreq);
176 qdev_init_nofail(dev);
177 busdev = SYS_BUS_DEVICE(dev);
178 sysbus_mmio_map(busdev, 0, base);
179 sysbus_connect_irq(busdev, 0, irq);
180}
181
182static void exynos4210_realize(DeviceState *socdev, Error **errp)
183{
184 Exynos4210State *s = EXYNOS4210_SOC(socdev);
185 MemoryRegion *system_mem = get_system_memory();
186 qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
187 SysBusDevice *busdev;
188 DeviceState *dev;
189 int i, n;
190
191 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
192 Object *cpuobj = object_new(ARM_CPU_TYPE_NAME("cortex-a9"));
193
194
195
196
197 if (object_property_find(cpuobj, "has_el3", NULL)) {
198 object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
199 }
200
201 s->cpu[n] = ARM_CPU(cpuobj);
202 object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
203 "mp-affinity", &error_abort);
204 object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
205 "reset-cbar", &error_abort);
206 object_property_set_bool(cpuobj, true, "realized", &error_fatal);
207 }
208
209
210
211 s->irq_table = exynos4210_init_irq(&s->irqs);
212
213
214 for (i = 0; i < EXYNOS4210_NCPUS; i++) {
215 dev = qdev_create(NULL, "exynos4210.irq_gate");
216 qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
217 qdev_init_nofail(dev);
218
219 for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
220 gate_irq[i][n] = qdev_get_gpio_in(dev, n);
221 }
222 busdev = SYS_BUS_DEVICE(dev);
223
224
225 sysbus_connect_irq(busdev, 0,
226 qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
227 }
228
229
230 dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
231 qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
232 qdev_init_nofail(dev);
233 busdev = SYS_BUS_DEVICE(dev);
234 sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
235 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
236 sysbus_connect_irq(busdev, n, gate_irq[n][0]);
237 }
238 for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
239 s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
240 }
241
242
243 sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
244
245
246 dev = qdev_create(NULL, "exynos4210.gic");
247 qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
248 qdev_init_nofail(dev);
249 busdev = SYS_BUS_DEVICE(dev);
250
251 sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
252
253 sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
254 for (n = 0; n < EXYNOS4210_NCPUS; n++) {
255 sysbus_connect_irq(busdev, n, gate_irq[n][1]);
256 }
257 for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
258 s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
259 }
260
261
262 dev = qdev_create(NULL, "exynos4210.combiner");
263 qdev_init_nofail(dev);
264 busdev = SYS_BUS_DEVICE(dev);
265 for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
266 sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
267 }
268 exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
269 sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
270
271
272 dev = qdev_create(NULL, "exynos4210.combiner");
273 qdev_prop_set_uint32(dev, "external", 1);
274 qdev_init_nofail(dev);
275 busdev = SYS_BUS_DEVICE(dev);
276 for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
277 sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
278 }
279 exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
280 sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
281
282
283 exynos4210_init_board_irqs(&s->irqs);
284
285
286
287
288 memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops,
289 NULL, "exynos4210.chipid", sizeof(chipid_and_omr));
290 memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
291 &s->chipid_mem);
292
293
294 memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom",
295 EXYNOS4210_IROM_SIZE, &error_fatal);
296 memory_region_set_readonly(&s->irom_mem, true);
297 memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
298 &s->irom_mem);
299
300 memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias",
301 &s->irom_mem,
302 0,
303 EXYNOS4210_IROM_SIZE);
304 memory_region_set_readonly(&s->irom_alias_mem, true);
305 memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
306 &s->irom_alias_mem);
307
308
309 memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram",
310 EXYNOS4210_IRAM_SIZE, &error_fatal);
311 memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
312 &s->iram_mem);
313
314
315
316
317
318 sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
319
320 sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
321 sysbus_create_simple("exynos4210.rng", EXYNOS4210_RNG_BASE_ADDR, NULL);
322
323
324 sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
325 s->irq_table[exynos4210_get_irq(22, 0)],
326 s->irq_table[exynos4210_get_irq(22, 1)],
327 s->irq_table[exynos4210_get_irq(22, 2)],
328 s->irq_table[exynos4210_get_irq(22, 3)],
329 s->irq_table[exynos4210_get_irq(22, 4)],
330 NULL);
331
332 sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
333 s->irq_table[exynos4210_get_irq(23, 0)],
334 s->irq_table[exynos4210_get_irq(23, 1)],
335 NULL);
336
337
338 dev = qdev_create(NULL, "exynos4210.mct");
339 qdev_init_nofail(dev);
340 busdev = SYS_BUS_DEVICE(dev);
341 for (n = 0; n < 4; n++) {
342
343 sysbus_connect_irq(busdev, n,
344 s->irq_table[exynos4210_get_irq(1, 4 + n)]);
345 }
346
347 sysbus_connect_irq(busdev, 4,
348 s->irq_table[exynos4210_get_irq(51, 0)]);
349 sysbus_connect_irq(busdev, 5,
350 s->irq_table[exynos4210_get_irq(35, 3)]);
351 sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
352
353
354 for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
355 uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
356 qemu_irq i2c_irq;
357
358 if (n < 8) {
359 i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
360 } else {
361 i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
362 }
363
364 dev = qdev_create(NULL, "exynos4210.i2c");
365 qdev_init_nofail(dev);
366 busdev = SYS_BUS_DEVICE(dev);
367 sysbus_connect_irq(busdev, 0, i2c_irq);
368 sysbus_mmio_map(busdev, 0, addr);
369 s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c");
370 }
371
372
373
374 exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
375 EXYNOS4210_UART0_FIFO_SIZE, 0, serial_hd(0),
376 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
377
378 exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
379 EXYNOS4210_UART1_FIFO_SIZE, 1, serial_hd(1),
380 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
381
382 exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
383 EXYNOS4210_UART2_FIFO_SIZE, 2, serial_hd(2),
384 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
385
386 exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
387 EXYNOS4210_UART3_FIFO_SIZE, 3, serial_hd(3),
388 s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
389
390
391 for (n = 0; n < EXYNOS4210_SDHCI_NUMBER; n++) {
392 DeviceState *carddev;
393 BlockBackend *blk;
394 DriveInfo *di;
395
396
397
398
399
400
401
402
403
404
405
406
407
408 dev = qdev_create(NULL, TYPE_S3C_SDHCI);
409 qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
410 qdev_init_nofail(dev);
411
412 busdev = SYS_BUS_DEVICE(dev);
413 sysbus_mmio_map(busdev, 0, EXYNOS4210_SDHCI_ADDR(n));
414 sysbus_connect_irq(busdev, 0, s->irq_table[exynos4210_get_irq(29, n)]);
415
416 di = drive_get(IF_SD, 0, n);
417 blk = di ? blk_by_legacy_dinfo(di) : NULL;
418 carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
419 qdev_prop_set_drive(carddev, "drive", blk, &error_abort);
420 qdev_init_nofail(carddev);
421 }
422
423
424 sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
425 s->irq_table[exynos4210_get_irq(11, 0)],
426 s->irq_table[exynos4210_get_irq(11, 1)],
427 s->irq_table[exynos4210_get_irq(11, 2)],
428 NULL);
429
430 sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
431 s->irq_table[exynos4210_get_irq(28, 3)]);
432
433
434 pl330_create(EXYNOS4210_PL330_BASE0_ADDR,
435 qemu_irq_invert(s->irq_table[exynos4210_get_irq(35, 1)]), 32);
436 pl330_create(EXYNOS4210_PL330_BASE1_ADDR,
437 qemu_irq_invert(s->irq_table[exynos4210_get_irq(36, 1)]), 32);
438 pl330_create(EXYNOS4210_PL330_BASE2_ADDR,
439 qemu_irq_invert(s->irq_table[exynos4210_get_irq(34, 1)]), 1);
440}
441
442static void exynos4210_class_init(ObjectClass *klass, void *data)
443{
444 DeviceClass *dc = DEVICE_CLASS(klass);
445
446 dc->realize = exynos4210_realize;
447}
448
449static const TypeInfo exynos4210_info = {
450 .name = TYPE_EXYNOS4210_SOC,
451 .parent = TYPE_SYS_BUS_DEVICE,
452 .instance_size = sizeof(Exynos4210State),
453 .class_init = exynos4210_class_init,
454};
455
456static void exynos4210_register_types(void)
457{
458 type_register_static(&exynos4210_info);
459}
460
461type_init(exynos4210_register_types)
462