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