ARM: EXYNOS: fix register setup for AFTR mode code
[deliverable/linux.git] / arch / arm / mach-exynos / exynos.c
CommitLineData
cc511b8d 1/*
cbf08b9e 2 * SAMSUNG EXYNOS Flattened Device Tree enabled machine
cc511b8d 3 *
cbf08b9e
SK
4 * Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
cc511b8d
KK
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
cbf08b9e 12#include <linux/init.h>
cc511b8d 13#include <linux/io.h>
cbf08b9e 14#include <linux/kernel.h>
334a1c70 15#include <linux/serial_s3c.h>
237c78be 16#include <linux/of.h>
e873a47c 17#include <linux/of_address.h>
cbf08b9e
SK
18#include <linux/of_fdt.h>
19#include <linux/of_platform.h>
35baa336 20#include <linux/platform_device.h>
cbf08b9e 21#include <linux/pm_domain.h>
fce9e5bb 22#include <linux/irqchip.h>
cc511b8d 23
cbf08b9e 24#include <asm/cacheflush.h>
cc511b8d 25#include <asm/hardware/cache-l2x0.h>
cbf08b9e 26#include <asm/mach/arch.h>
cc511b8d 27#include <asm/mach/map.h>
cbf08b9e 28#include <asm/memory.h>
cc511b8d 29
cc511b8d 30#include "common.h"
cbf08b9e 31#include "mfc.h"
65c9a853 32#include "regs-pmu.h"
318fd20b 33#include "regs-sys.h"
65c9a853 34
fce9e5bb 35void __iomem *pmu_base_addr;
65c9a853 36
94c7ca71
KK
37static struct map_desc exynos4_iodesc[] __initdata = {
38 {
cc511b8d
KK
39 .virtual = (unsigned long)S3C_VA_SYS,
40 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
41 .length = SZ_64K,
42 .type = MT_DEVICE,
43 }, {
44 .virtual = (unsigned long)S3C_VA_TIMER,
45 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
46 .length = SZ_16K,
47 .type = MT_DEVICE,
48 }, {
49 .virtual = (unsigned long)S3C_VA_WATCHDOG,
50 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
51 .length = SZ_4K,
52 .type = MT_DEVICE,
53 }, {
54 .virtual = (unsigned long)S5P_VA_SROMC,
55 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
56 .length = SZ_4K,
57 .type = MT_DEVICE,
58 }, {
59 .virtual = (unsigned long)S5P_VA_SYSTIMER,
60 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
61 .length = SZ_4K,
62 .type = MT_DEVICE,
cc511b8d
KK
63 }, {
64 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
65 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
66 .length = SZ_4K,
67 .type = MT_DEVICE,
68 }, {
69 .virtual = (unsigned long)S5P_VA_GIC_CPU,
70 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
71 .length = SZ_64K,
72 .type = MT_DEVICE,
73 }, {
74 .virtual = (unsigned long)S5P_VA_GIC_DIST,
75 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
76 .length = SZ_64K,
77 .type = MT_DEVICE,
94c7ca71 78 }, {
cc511b8d
KK
79 .virtual = (unsigned long)S5P_VA_CMU,
80 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
81 .length = SZ_128K,
82 .type = MT_DEVICE,
83 }, {
84 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
85 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
86 .length = SZ_8K,
87 .type = MT_DEVICE,
88 }, {
89 .virtual = (unsigned long)S5P_VA_L2CC,
90 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
91 .length = SZ_4K,
92 .type = MT_DEVICE,
cc511b8d
KK
93 }, {
94 .virtual = (unsigned long)S5P_VA_DMC0,
95 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
2bde0b08
MH
96 .length = SZ_64K,
97 .type = MT_DEVICE,
98 }, {
99 .virtual = (unsigned long)S5P_VA_DMC1,
100 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
101 .length = SZ_64K,
cc511b8d 102 .type = MT_DEVICE,
cc511b8d
KK
103 }, {
104 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
105 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
106 .length = SZ_4K,
107 .type = MT_DEVICE,
108 },
109};
110
94c7ca71
KK
111static struct map_desc exynos5_iodesc[] __initdata = {
112 {
113 .virtual = (unsigned long)S3C_VA_SYS,
114 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
115 .length = SZ_64K,
116 .type = MT_DEVICE,
117 }, {
118 .virtual = (unsigned long)S3C_VA_TIMER,
119 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
120 .length = SZ_16K,
121 .type = MT_DEVICE,
122 }, {
123 .virtual = (unsigned long)S3C_VA_WATCHDOG,
124 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
125 .length = SZ_4K,
126 .type = MT_DEVICE,
127 }, {
128 .virtual = (unsigned long)S5P_VA_SROMC,
129 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
130 .length = SZ_4K,
131 .type = MT_DEVICE,
94c7ca71
KK
132 }, {
133 .virtual = (unsigned long)S5P_VA_CMU,
134 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
135 .length = 144 * SZ_1K,
136 .type = MT_DEVICE,
2edb36c4
KK
137 },
138};
139
5e299f65 140static void exynos_restart(enum reboot_mode mode, const char *cmd)
94c7ca71 141{
60db7e5f 142 struct device_node *np;
cbf08b9e 143 u32 val = 0x1;
2e94ac42 144 void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
eff4e7c7
CK
145
146 if (of_machine_is_compatible("samsung,exynos5440")) {
1ba830c9 147 u32 status;
60db7e5f 148 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
1ba830c9
JL
149
150 addr = of_iomap(np, 0) + 0xbc;
151 status = __raw_readl(addr);
152
60db7e5f 153 addr = of_iomap(np, 0) + 0xcc;
1ba830c9
JL
154 val = __raw_readl(addr);
155
156 val = (val & 0xffff0000) | (status & 0xffff);
2edb36c4
KK
157 }
158
159 __raw_writel(val, addr);
94c7ca71
KK
160}
161
35baa336 162static struct platform_device exynos_cpuidle = {
277f5046 163 .name = "exynos_cpuidle",
658cff0d 164#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
277f5046 165 .dev.platform_data = exynos_enter_aftr,
658cff0d 166#endif
277f5046 167 .id = -1,
35baa336
BZ
168};
169
1754c42e
OJ
170void __iomem *sysram_base_addr;
171void __iomem *sysram_ns_base_addr;
172
173void __init exynos_sysram_init(void)
174{
175 struct device_node *node;
176
177 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
178 if (!of_device_is_available(node))
179 continue;
180 sysram_base_addr = of_iomap(node, 0);
181 break;
182 }
183
184 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
185 if (!of_device_is_available(node))
186 continue;
187 sysram_ns_base_addr = of_iomap(node, 0);
188 break;
189 }
190}
191
5e299f65 192static void __init exynos_init_late(void)
bb13fabc 193{
2edb36c4
KK
194 if (of_machine_is_compatible("samsung,exynos5440"))
195 /* to be supported later */
196 return;
197
559ba237 198 exynos_pm_init();
bb13fabc
SG
199}
200
564d06b1 201static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
f5f83c71
TA
202 int depth, void *data)
203{
204 struct map_desc iodesc;
3eb93646 205 const __be32 *reg;
9d0c4dfe 206 int len;
f5f83c71
TA
207
208 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
209 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
210 return 0;
211
212 reg = of_get_flat_dt_prop(node, "reg", &len);
213 if (reg == NULL || len != (sizeof(unsigned long) * 2))
214 return 0;
215
216 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
217 iodesc.length = be32_to_cpu(reg[1]) - 1;
218 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
219 iodesc.type = MT_DEVICE;
220 iotable_init(&iodesc, 1);
221 return 1;
222}
f5f83c71 223
cc511b8d
KK
224/*
225 * exynos_map_io
226 *
227 * register the standard cpu IO areas
228 */
6eb84669
SK
229static void __init exynos_map_io(void)
230{
cbf08b9e 231 if (soc_is_exynos4())
6eb84669
SK
232 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
233
cbf08b9e 234 if (soc_is_exynos5())
6eb84669 235 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
6eb84669 236}
cc511b8d 237
5e299f65 238static void __init exynos_init_io(void)
cc511b8d 239{
9c1fcdcc
DA
240 debug_ll_io_init();
241
04fae596 242 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
2edb36c4 243
cc511b8d
KK
244 /* detect cpu id and rev. */
245 s5p_init_cpu(S5P_VA_CHIPID);
246
6eb84669 247 exynos_map_io();
94c7ca71
KK
248}
249
fce9e5bb
PD
250static const struct of_device_id exynos_dt_pmu_match[] = {
251 { .compatible = "samsung,exynos3250-pmu" },
252 { .compatible = "samsung,exynos4210-pmu" },
253 { .compatible = "samsung,exynos4212-pmu" },
254 { .compatible = "samsung,exynos4412-pmu" },
255 { .compatible = "samsung,exynos5250-pmu" },
22ead0d7 256 { .compatible = "samsung,exynos5260-pmu" },
98504def 257 { .compatible = "samsung,exynos5410-pmu" },
fce9e5bb
PD
258 { .compatible = "samsung,exynos5420-pmu" },
259 { /*sentinel*/ },
260};
261
262static void exynos_map_pmu(void)
263{
264 struct device_node *np;
265
266 np = of_find_matching_node(NULL, exynos_dt_pmu_match);
267 if (np)
268 pmu_base_addr = of_iomap(np, 0);
269
270 if (!pmu_base_addr)
271 panic("failed to find exynos pmu register\n");
272}
273
274static void __init exynos_init_irq(void)
275{
276 irqchip_init();
277 /*
278 * Since platsmp.c needs pmu base address by the time
279 * DT is not unflatten so we can't use DT APIs before
280 * init_irq
281 */
282 exynos_map_pmu();
283}
284
cbf08b9e 285static void __init exynos_dt_machine_init(void)
cc511b8d 286{
cbf08b9e
SK
287 struct device_node *i2c_np;
288 const char *i2c_compat = "samsung,s3c2440-i2c";
289 unsigned int tmp;
290 int id;
291
292 /*
293 * Exynos5's legacy i2c controller and new high speed i2c
294 * controller have muxed interrupt sources. By default the
295 * interrupts for 4-channel HS-I2C controller are enabled.
296 * If node for first four channels of legacy i2c controller
297 * are available then re-configure the interrupts via the
298 * system register.
299 */
300 if (soc_is_exynos5()) {
301 for_each_compatible_node(i2c_np, NULL, i2c_compat) {
302 if (of_device_is_available(i2c_np)) {
303 id = of_alias_get_id(i2c_np, "i2c");
304 if (id < 4) {
305 tmp = readl(EXYNOS5_SYS_I2C_CFG);
306 writel(tmp & ~(0x1 << id),
307 EXYNOS5_SYS_I2C_CFG);
308 }
309 }
310 }
311 }
94c7ca71 312
1754c42e
OJ
313 /*
314 * This is called from smp_prepare_cpus if we've built for SMP, but
315 * we still need to set it up for PM and firmware ops if not.
316 */
73ea6ec6 317 if (!IS_ENABLED(CONFIG_SMP))
1754c42e
OJ
318 exynos_sysram_init();
319
6887d9e5
PD
320 if (of_machine_is_compatible("samsung,exynos4210") ||
321 of_machine_is_compatible("samsung,exynos5250"))
322 platform_device_register(&exynos_cpuidle);
b5a296cd 323
6887d9e5 324 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
cbf08b9e
SK
325
326 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 327}
cbf08b9e
SK
328
329static char const *exynos_dt_compat[] __initconst = {
940bc58d
CC
330 "samsung,exynos3",
331 "samsung,exynos3250",
4868123c 332 "samsung,exynos4",
cbf08b9e
SK
333 "samsung,exynos4210",
334 "samsung,exynos4212",
335 "samsung,exynos4412",
4868123c 336 "samsung,exynos5",
cbf08b9e 337 "samsung,exynos5250",
ed08f103 338 "samsung,exynos5260",
cbf08b9e
SK
339 "samsung,exynos5420",
340 "samsung,exynos5440",
341 NULL
342};
343
344static void __init exynos_reserve(void)
345{
346#ifdef CONFIG_S5P_DEV_MFC
347 int i;
348 char *mfc_mem[] = {
349 "samsung,mfc-v5",
350 "samsung,mfc-v6",
351 "samsung,mfc-v7",
352 };
353
354 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
355 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
356 break;
357#endif
358}
359
5a12a597
LA
360static void __init exynos_dt_fixup(void)
361{
362 /*
363 * Some versions of uboot pass garbage entries in the memory node,
364 * use the old CONFIG_ARM_NR_BANKS
365 */
366 of_fdt_limit_memory(8);
367}
368
cbf08b9e
SK
369DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
370 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
371 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
15b0bc40
RK
372 .l2c_aux_val = 0x3c400001,
373 .l2c_aux_mask = 0xc20fffff,
cbf08b9e
SK
374 .smp = smp_ops(exynos_smp_ops),
375 .map_io = exynos_init_io,
376 .init_early = exynos_firmware_init,
fce9e5bb 377 .init_irq = exynos_init_irq,
cbf08b9e
SK
378 .init_machine = exynos_dt_machine_init,
379 .init_late = exynos_init_late,
380 .dt_compat = exynos_dt_compat,
381 .restart = exynos_restart,
382 .reserve = exynos_reserve,
5a12a597 383 .dt_fixup = exynos_dt_fixup,
cbf08b9e 384MACHINE_END
This page took 0.186627 seconds and 5 git commands to generate.