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