ARM: EXYNOS: Add 5800 SoC support
[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>
cc511b8d 22
cbf08b9e 23#include <asm/cacheflush.h>
cc511b8d 24#include <asm/hardware/cache-l2x0.h>
cbf08b9e 25#include <asm/mach/arch.h>
cc511b8d 26#include <asm/mach/map.h>
cbf08b9e 27#include <asm/memory.h>
cc511b8d 28
cc511b8d 29#include "common.h"
cbf08b9e 30#include "mfc.h"
65c9a853
KK
31#include "regs-pmu.h"
32
6cdeddcc
ADK
33#define L2_AUX_VAL 0x7C470001
34#define L2_AUX_MASK 0xC200ffff
cc511b8d 35
94c7ca71
KK
36static struct map_desc exynos4_iodesc[] __initdata = {
37 {
cc511b8d
KK
38 .virtual = (unsigned long)S3C_VA_SYS,
39 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
40 .length = SZ_64K,
41 .type = MT_DEVICE,
42 }, {
43 .virtual = (unsigned long)S3C_VA_TIMER,
44 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
45 .length = SZ_16K,
46 .type = MT_DEVICE,
47 }, {
48 .virtual = (unsigned long)S3C_VA_WATCHDOG,
49 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
50 .length = SZ_4K,
51 .type = MT_DEVICE,
52 }, {
53 .virtual = (unsigned long)S5P_VA_SROMC,
54 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
55 .length = SZ_4K,
56 .type = MT_DEVICE,
57 }, {
58 .virtual = (unsigned long)S5P_VA_SYSTIMER,
59 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
60 .length = SZ_4K,
61 .type = MT_DEVICE,
62 }, {
63 .virtual = (unsigned long)S5P_VA_PMU,
64 .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
65 .length = SZ_64K,
66 .type = MT_DEVICE,
67 }, {
68 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
69 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
70 .length = SZ_4K,
71 .type = MT_DEVICE,
72 }, {
73 .virtual = (unsigned long)S5P_VA_GIC_CPU,
74 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
75 .length = SZ_64K,
76 .type = MT_DEVICE,
77 }, {
78 .virtual = (unsigned long)S5P_VA_GIC_DIST,
79 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
80 .length = SZ_64K,
81 .type = MT_DEVICE,
94c7ca71 82 }, {
cc511b8d
KK
83 .virtual = (unsigned long)S5P_VA_CMU,
84 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
85 .length = SZ_128K,
86 .type = MT_DEVICE,
87 }, {
88 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
89 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
90 .length = SZ_8K,
91 .type = MT_DEVICE,
92 }, {
93 .virtual = (unsigned long)S5P_VA_L2CC,
94 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
95 .length = SZ_4K,
96 .type = MT_DEVICE,
cc511b8d
KK
97 }, {
98 .virtual = (unsigned long)S5P_VA_DMC0,
99 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
2bde0b08
MH
100 .length = SZ_64K,
101 .type = MT_DEVICE,
102 }, {
103 .virtual = (unsigned long)S5P_VA_DMC1,
104 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
105 .length = SZ_64K,
cc511b8d 106 .type = MT_DEVICE,
cc511b8d
KK
107 }, {
108 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
109 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
110 .length = SZ_4K,
111 .type = MT_DEVICE,
112 },
113};
114
115static struct map_desc exynos4_iodesc0[] __initdata = {
116 {
117 .virtual = (unsigned long)S5P_VA_SYSRAM,
118 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
119 .length = SZ_4K,
120 .type = MT_DEVICE,
121 },
122};
123
124static struct map_desc exynos4_iodesc1[] __initdata = {
125 {
126 .virtual = (unsigned long)S5P_VA_SYSRAM,
127 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
128 .length = SZ_4K,
129 .type = MT_DEVICE,
130 },
131};
132
41de8986
TF
133static struct map_desc exynos4210_iodesc[] __initdata = {
134 {
135 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
136 .pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
137 .length = SZ_4K,
138 .type = MT_DEVICE,
139 },
140};
141
142static struct map_desc exynos4x12_iodesc[] __initdata = {
143 {
144 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
145 .pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
146 .length = SZ_4K,
147 .type = MT_DEVICE,
148 },
149};
150
151static struct map_desc exynos5250_iodesc[] __initdata = {
152 {
153 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
154 .pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
155 .length = SZ_4K,
156 .type = MT_DEVICE,
157 },
158};
159
94c7ca71
KK
160static struct map_desc exynos5_iodesc[] __initdata = {
161 {
162 .virtual = (unsigned long)S3C_VA_SYS,
163 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
164 .length = SZ_64K,
165 .type = MT_DEVICE,
166 }, {
167 .virtual = (unsigned long)S3C_VA_TIMER,
168 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
169 .length = SZ_16K,
170 .type = MT_DEVICE,
171 }, {
172 .virtual = (unsigned long)S3C_VA_WATCHDOG,
173 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
174 .length = SZ_4K,
175 .type = MT_DEVICE,
176 }, {
177 .virtual = (unsigned long)S5P_VA_SROMC,
178 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
179 .length = SZ_4K,
180 .type = MT_DEVICE,
94c7ca71
KK
181 }, {
182 .virtual = (unsigned long)S5P_VA_SYSRAM,
183 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
184 .length = SZ_4K,
185 .type = MT_DEVICE,
186 }, {
187 .virtual = (unsigned long)S5P_VA_CMU,
188 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
189 .length = 144 * SZ_1K,
190 .type = MT_DEVICE,
191 }, {
192 .virtual = (unsigned long)S5P_VA_PMU,
193 .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
194 .length = SZ_64K,
195 .type = MT_DEVICE,
2edb36c4
KK
196 },
197};
198
cbf08b9e 199void exynos_restart(enum reboot_mode mode, const char *cmd)
94c7ca71 200{
60db7e5f 201 struct device_node *np;
cbf08b9e
SK
202 u32 val = 0x1;
203 void __iomem *addr = EXYNOS_SWRESET;
eff4e7c7
CK
204
205 if (of_machine_is_compatible("samsung,exynos5440")) {
1ba830c9 206 u32 status;
60db7e5f 207 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
1ba830c9
JL
208
209 addr = of_iomap(np, 0) + 0xbc;
210 status = __raw_readl(addr);
211
60db7e5f 212 addr = of_iomap(np, 0) + 0xcc;
1ba830c9
JL
213 val = __raw_readl(addr);
214
215 val = (val & 0xffff0000) | (status & 0xffff);
2edb36c4
KK
216 }
217
218 __raw_writel(val, addr);
94c7ca71
KK
219}
220
35baa336
BZ
221static struct platform_device exynos_cpuidle = {
222 .name = "exynos_cpuidle",
223 .id = -1,
224};
225
226void __init exynos_cpuidle_init(void)
227{
228 platform_device_register(&exynos_cpuidle);
229}
230
d568b6f7
LM
231void __init exynos_cpufreq_init(void)
232{
233 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
234}
235
bb13fabc
SG
236void __init exynos_init_late(void)
237{
2edb36c4
KK
238 if (of_machine_is_compatible("samsung,exynos5440"))
239 /* to be supported later */
240 return;
241
1fd3cbcc 242 pm_genpd_poweroff_unused();
559ba237 243 exynos_pm_init();
bb13fabc
SG
244}
245
564d06b1 246static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
f5f83c71
TA
247 int depth, void *data)
248{
249 struct map_desc iodesc;
250 __be32 *reg;
251 unsigned long len;
252
253 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
254 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
255 return 0;
256
257 reg = of_get_flat_dt_prop(node, "reg", &len);
258 if (reg == NULL || len != (sizeof(unsigned long) * 2))
259 return 0;
260
261 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
262 iodesc.length = be32_to_cpu(reg[1]) - 1;
263 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
264 iodesc.type = MT_DEVICE;
265 iotable_init(&iodesc, 1);
266 return 1;
267}
f5f83c71 268
cc511b8d
KK
269/*
270 * exynos_map_io
271 *
272 * register the standard cpu IO areas
273 */
6eb84669
SK
274static void __init exynos_map_io(void)
275{
cbf08b9e 276 if (soc_is_exynos4())
6eb84669
SK
277 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
278
cbf08b9e 279 if (soc_is_exynos5())
6eb84669
SK
280 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
281
282 if (soc_is_exynos4210()) {
283 if (samsung_rev() == EXYNOS4210_REV_0)
284 iotable_init(exynos4_iodesc0,
285 ARRAY_SIZE(exynos4_iodesc0));
286 else
287 iotable_init(exynos4_iodesc1,
288 ARRAY_SIZE(exynos4_iodesc1));
289 iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
290 }
291 if (soc_is_exynos4212() || soc_is_exynos4412())
292 iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
293 if (soc_is_exynos5250())
294 iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
295}
cc511b8d 296
0e2238ec 297void __init exynos_init_io(void)
cc511b8d 298{
9c1fcdcc
DA
299 debug_ll_io_init();
300
04fae596 301 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
2edb36c4 302
cc511b8d
KK
303 /* detect cpu id and rev. */
304 s5p_init_cpu(S5P_VA_CHIPID);
305
6eb84669 306 exynos_map_io();
94c7ca71
KK
307}
308
cc511b8d
KK
309static int __init exynos4_l2x0_cache_init(void)
310{
e1b1994e
IH
311 int ret;
312
6cdeddcc 313 ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
87107d89
AB
314 if (ret)
315 return ret;
cc511b8d 316
39378e41
AB
317 if (IS_ENABLED(CONFIG_S5P_SLEEP)) {
318 l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
319 clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
320 }
cc511b8d
KK
321 return 0;
322}
cc511b8d 323early_initcall(exynos4_l2x0_cache_init);
cc511b8d 324
cbf08b9e 325static void __init exynos_dt_machine_init(void)
cc511b8d 326{
cbf08b9e
SK
327 struct device_node *i2c_np;
328 const char *i2c_compat = "samsung,s3c2440-i2c";
329 unsigned int tmp;
330 int id;
331
332 /*
333 * Exynos5's legacy i2c controller and new high speed i2c
334 * controller have muxed interrupt sources. By default the
335 * interrupts for 4-channel HS-I2C controller are enabled.
336 * If node for first four channels of legacy i2c controller
337 * are available then re-configure the interrupts via the
338 * system register.
339 */
340 if (soc_is_exynos5()) {
341 for_each_compatible_node(i2c_np, NULL, i2c_compat) {
342 if (of_device_is_available(i2c_np)) {
343 id = of_alias_get_id(i2c_np, "i2c");
344 if (id < 4) {
345 tmp = readl(EXYNOS5_SYS_I2C_CFG);
346 writel(tmp & ~(0x1 << id),
347 EXYNOS5_SYS_I2C_CFG);
348 }
349 }
350 }
351 }
94c7ca71 352
cbf08b9e
SK
353 exynos_cpuidle_init();
354 exynos_cpufreq_init();
355
356 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 357}
cbf08b9e
SK
358
359static char const *exynos_dt_compat[] __initconst = {
4868123c 360 "samsung,exynos4",
cbf08b9e
SK
361 "samsung,exynos4210",
362 "samsung,exynos4212",
363 "samsung,exynos4412",
4868123c 364 "samsung,exynos5",
cbf08b9e 365 "samsung,exynos5250",
ed08f103 366 "samsung,exynos5260",
cbf08b9e
SK
367 "samsung,exynos5420",
368 "samsung,exynos5440",
369 NULL
370};
371
372static void __init exynos_reserve(void)
373{
374#ifdef CONFIG_S5P_DEV_MFC
375 int i;
376 char *mfc_mem[] = {
377 "samsung,mfc-v5",
378 "samsung,mfc-v6",
379 "samsung,mfc-v7",
380 };
381
382 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
383 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
384 break;
385#endif
386}
387
388DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
389 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
390 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
391 .smp = smp_ops(exynos_smp_ops),
392 .map_io = exynos_init_io,
393 .init_early = exynos_firmware_init,
394 .init_machine = exynos_dt_machine_init,
395 .init_late = exynos_init_late,
396 .dt_compat = exynos_dt_compat,
397 .restart = exynos_restart,
398 .reserve = exynos_reserve,
399MACHINE_END
This page took 0.227459 seconds and 5 git commands to generate.