Merge branch 'x86-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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
32b0aa9a
PD
30#include <mach/map.h>
31
cc511b8d 32#include "common.h"
cbf08b9e 33#include "mfc.h"
65c9a853
KK
34#include "regs-pmu.h"
35
fce9e5bb 36void __iomem *pmu_base_addr;
65c9a853 37
94c7ca71
KK
38static struct map_desc exynos4_iodesc[] __initdata = {
39 {
cc511b8d
KK
40 .virtual = (unsigned long)S5P_VA_SROMC,
41 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
42 .length = SZ_4K,
43 .type = MT_DEVICE,
94c7ca71 44 }, {
cc511b8d
KK
45 .virtual = (unsigned long)S5P_VA_CMU,
46 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
47 .length = SZ_128K,
48 .type = MT_DEVICE,
49 }, {
50 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
51 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
52 .length = SZ_8K,
53 .type = MT_DEVICE,
cc511b8d
KK
54 }, {
55 .virtual = (unsigned long)S5P_VA_DMC0,
56 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
2bde0b08
MH
57 .length = SZ_64K,
58 .type = MT_DEVICE,
59 }, {
60 .virtual = (unsigned long)S5P_VA_DMC1,
61 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
62 .length = SZ_64K,
cc511b8d 63 .type = MT_DEVICE,
cc511b8d
KK
64 },
65};
66
94c7ca71
KK
67static struct map_desc exynos5_iodesc[] __initdata = {
68 {
94c7ca71
KK
69 .virtual = (unsigned long)S5P_VA_SROMC,
70 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
71 .length = SZ_4K,
72 .type = MT_DEVICE,
94c7ca71
KK
73 }, {
74 .virtual = (unsigned long)S5P_VA_CMU,
75 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
76 .length = 144 * SZ_1K,
77 .type = MT_DEVICE,
2edb36c4
KK
78 },
79};
80
35baa336 81static struct platform_device exynos_cpuidle = {
277f5046 82 .name = "exynos_cpuidle",
658cff0d 83#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
277f5046 84 .dev.platform_data = exynos_enter_aftr,
658cff0d 85#endif
277f5046 86 .id = -1,
35baa336
BZ
87};
88
1754c42e
OJ
89void __iomem *sysram_base_addr;
90void __iomem *sysram_ns_base_addr;
91
92void __init exynos_sysram_init(void)
93{
94 struct device_node *node;
95
96 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
97 if (!of_device_is_available(node))
98 continue;
99 sysram_base_addr = of_iomap(node, 0);
100 break;
101 }
102
103 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
104 if (!of_device_is_available(node))
105 continue;
106 sysram_ns_base_addr = of_iomap(node, 0);
107 break;
108 }
109}
110
5e299f65 111static void __init exynos_init_late(void)
bb13fabc 112{
2edb36c4
KK
113 if (of_machine_is_compatible("samsung,exynos5440"))
114 /* to be supported later */
115 return;
116
559ba237 117 exynos_pm_init();
bb13fabc
SG
118}
119
564d06b1 120static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
f5f83c71
TA
121 int depth, void *data)
122{
123 struct map_desc iodesc;
3eb93646 124 const __be32 *reg;
9d0c4dfe 125 int len;
f5f83c71
TA
126
127 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
128 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
129 return 0;
130
131 reg = of_get_flat_dt_prop(node, "reg", &len);
132 if (reg == NULL || len != (sizeof(unsigned long) * 2))
133 return 0;
134
135 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
136 iodesc.length = be32_to_cpu(reg[1]) - 1;
137 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
138 iodesc.type = MT_DEVICE;
139 iotable_init(&iodesc, 1);
140 return 1;
141}
f5f83c71 142
cc511b8d
KK
143/*
144 * exynos_map_io
145 *
146 * register the standard cpu IO areas
147 */
6eb84669
SK
148static void __init exynos_map_io(void)
149{
cbf08b9e 150 if (soc_is_exynos4())
6eb84669
SK
151 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
152
cbf08b9e 153 if (soc_is_exynos5())
6eb84669 154 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
6eb84669 155}
cc511b8d 156
5e299f65 157static void __init exynos_init_io(void)
cc511b8d 158{
9c1fcdcc
DA
159 debug_ll_io_init();
160
04fae596 161 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
2edb36c4 162
cc511b8d
KK
163 /* detect cpu id and rev. */
164 s5p_init_cpu(S5P_VA_CHIPID);
165
6eb84669 166 exynos_map_io();
94c7ca71
KK
167}
168
6f024978
KK
169/*
170 * Set or clear the USE_DELAYED_RESET_ASSERTION option. Used by smp code
171 * and suspend.
172 *
173 * This is necessary only on Exynos4 SoCs. When system is running
174 * USE_DELAYED_RESET_ASSERTION should be set so the ARM CLK clock down
175 * feature could properly detect global idle state when secondary CPU is
176 * powered down.
177 *
178 * However this should not be set when such system is going into suspend.
179 */
180void exynos_set_delayed_reset_assertion(bool enable)
181{
c1f0ecff 182 if (of_machine_is_compatible("samsung,exynos4")) {
6f024978
KK
183 unsigned int tmp, core_id;
184
185 for (core_id = 0; core_id < num_possible_cpus(); core_id++) {
186 tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
187 if (enable)
188 tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
189 else
190 tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
191 pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
192 }
193 }
194}
195
8b283c02
MZ
196/*
197 * Apparently, these SoCs are not able to wake-up from suspend using
198 * the PMU. Too bad. Should they suddenly become capable of such a
199 * feat, the matches below should be moved to suspend.c.
200 */
fce9e5bb 201static const struct of_device_id exynos_dt_pmu_match[] = {
22ead0d7 202 { .compatible = "samsung,exynos5260-pmu" },
98504def 203 { .compatible = "samsung,exynos5410-pmu" },
fce9e5bb
PD
204 { /*sentinel*/ },
205};
206
207static void exynos_map_pmu(void)
208{
209 struct device_node *np;
210
211 np = of_find_matching_node(NULL, exynos_dt_pmu_match);
212 if (np)
213 pmu_base_addr = of_iomap(np, 0);
fce9e5bb
PD
214}
215
216static void __init exynos_init_irq(void)
217{
218 irqchip_init();
219 /*
220 * Since platsmp.c needs pmu base address by the time
221 * DT is not unflatten so we can't use DT APIs before
222 * init_irq
223 */
224 exynos_map_pmu();
225}
226
131323cd
TA
227static const struct of_device_id exynos_cpufreq_matches[] = {
228 { .compatible = "samsung,exynos4210", .data = "cpufreq-dt" },
229 { /* sentinel */ }
230};
231
232static void __init exynos_cpufreq_init(void)
233{
234 struct device_node *root = of_find_node_by_path("/");
235 const struct of_device_id *match;
236
237 match = of_match_node(exynos_cpufreq_matches, root);
238 if (!match) {
239 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
240 return;
241 }
242
243 platform_device_register_simple(match->data, -1, NULL, 0);
244}
245
cbf08b9e 246static void __init exynos_dt_machine_init(void)
cc511b8d 247{
1754c42e
OJ
248 /*
249 * This is called from smp_prepare_cpus if we've built for SMP, but
250 * we still need to set it up for PM and firmware ops if not.
251 */
73ea6ec6 252 if (!IS_ENABLED(CONFIG_SMP))
1754c42e
OJ
253 exynos_sysram_init();
254
cfdda353 255#if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
af997114
BZ
256 if (of_machine_is_compatible("samsung,exynos4210") ||
257 of_machine_is_compatible("samsung,exynos3250"))
712eddf7
BZ
258 exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
259#endif
6887d9e5 260 if (of_machine_is_compatible("samsung,exynos4210") ||
42d5dc37
BZ
261 of_machine_is_compatible("samsung,exynos4212") ||
262 (of_machine_is_compatible("samsung,exynos4412") &&
263 of_machine_is_compatible("samsung,trats2")) ||
bd0d888c 264 of_machine_is_compatible("samsung,exynos3250") ||
42d5dc37 265 of_machine_is_compatible("samsung,exynos5250"))
6887d9e5 266 platform_device_register(&exynos_cpuidle);
b5a296cd 267
131323cd 268 exynos_cpufreq_init();
cbf08b9e
SK
269
270 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 271}
cbf08b9e 272
543c5040 273static char const *const exynos_dt_compat[] __initconst = {
940bc58d
CC
274 "samsung,exynos3",
275 "samsung,exynos3250",
4868123c 276 "samsung,exynos4",
cbf08b9e
SK
277 "samsung,exynos4210",
278 "samsung,exynos4212",
279 "samsung,exynos4412",
c0adae9e 280 "samsung,exynos4415",
4868123c 281 "samsung,exynos5",
cbf08b9e 282 "samsung,exynos5250",
ed08f103 283 "samsung,exynos5260",
cbf08b9e
SK
284 "samsung,exynos5420",
285 "samsung,exynos5440",
286 NULL
287};
288
289static void __init exynos_reserve(void)
290{
291#ifdef CONFIG_S5P_DEV_MFC
292 int i;
293 char *mfc_mem[] = {
294 "samsung,mfc-v5",
295 "samsung,mfc-v6",
296 "samsung,mfc-v7",
adacba58 297 "samsung,mfc-v8",
cbf08b9e
SK
298 };
299
300 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
301 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
302 break;
303#endif
304}
305
5a12a597
LA
306static void __init exynos_dt_fixup(void)
307{
308 /*
309 * Some versions of uboot pass garbage entries in the memory node,
310 * use the old CONFIG_ARM_NR_BANKS
311 */
312 of_fdt_limit_memory(8);
313}
314
cbf08b9e
SK
315DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
316 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
317 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
15b0bc40
RK
318 .l2c_aux_val = 0x3c400001,
319 .l2c_aux_mask = 0xc20fffff,
cbf08b9e
SK
320 .smp = smp_ops(exynos_smp_ops),
321 .map_io = exynos_init_io,
322 .init_early = exynos_firmware_init,
fce9e5bb 323 .init_irq = exynos_init_irq,
cbf08b9e
SK
324 .init_machine = exynos_dt_machine_init,
325 .init_late = exynos_init_late,
326 .dt_compat = exynos_dt_compat,
cbf08b9e 327 .reserve = exynos_reserve,
5a12a597 328 .dt_fixup = exynos_dt_fixup,
cbf08b9e 329MACHINE_END
This page took 0.221004 seconds and 5 git commands to generate.