Merge branch 'v3.19-next/non-critical-fixes' into v3.19-next/mach-exynos
[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 320 if (of_machine_is_compatible("samsung,exynos4210") ||
42d5dc37
BZ
321 of_machine_is_compatible("samsung,exynos4212") ||
322 (of_machine_is_compatible("samsung,exynos4412") &&
323 of_machine_is_compatible("samsung,trats2")) ||
324 of_machine_is_compatible("samsung,exynos5250"))
6887d9e5 325 platform_device_register(&exynos_cpuidle);
b5a296cd 326
6887d9e5 327 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
cbf08b9e
SK
328
329 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 330}
cbf08b9e
SK
331
332static char const *exynos_dt_compat[] __initconst = {
940bc58d
CC
333 "samsung,exynos3",
334 "samsung,exynos3250",
4868123c 335 "samsung,exynos4",
cbf08b9e
SK
336 "samsung,exynos4210",
337 "samsung,exynos4212",
338 "samsung,exynos4412",
4868123c 339 "samsung,exynos5",
cbf08b9e 340 "samsung,exynos5250",
ed08f103 341 "samsung,exynos5260",
cbf08b9e
SK
342 "samsung,exynos5420",
343 "samsung,exynos5440",
344 NULL
345};
346
347static void __init exynos_reserve(void)
348{
349#ifdef CONFIG_S5P_DEV_MFC
350 int i;
351 char *mfc_mem[] = {
352 "samsung,mfc-v5",
353 "samsung,mfc-v6",
354 "samsung,mfc-v7",
355 };
356
357 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
358 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
359 break;
360#endif
361}
362
5a12a597
LA
363static void __init exynos_dt_fixup(void)
364{
365 /*
366 * Some versions of uboot pass garbage entries in the memory node,
367 * use the old CONFIG_ARM_NR_BANKS
368 */
369 of_fdt_limit_memory(8);
370}
371
cbf08b9e
SK
372DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
373 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
374 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
15b0bc40
RK
375 .l2c_aux_val = 0x3c400001,
376 .l2c_aux_mask = 0xc20fffff,
cbf08b9e
SK
377 .smp = smp_ops(exynos_smp_ops),
378 .map_io = exynos_init_io,
379 .init_early = exynos_firmware_init,
fce9e5bb 380 .init_irq = exynos_init_irq,
cbf08b9e
SK
381 .init_machine = exynos_dt_machine_init,
382 .init_late = exynos_init_late,
383 .dt_compat = exynos_dt_compat,
384 .restart = exynos_restart,
385 .reserve = exynos_reserve,
5a12a597 386 .dt_fixup = exynos_dt_fixup,
cbf08b9e 387MACHINE_END
This page took 0.190554 seconds and 5 git commands to generate.