ARM: dts: Add PMU DT node for exynos5260 SoC
[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
PD
35void __iomem *pmu_base_addr;
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
DL
163 .name = "exynos_cpuidle",
164 .dev.platform_data = exynos_enter_aftr,
165 .id = -1,
35baa336
BZ
166};
167
1754c42e
OJ
168void __iomem *sysram_base_addr;
169void __iomem *sysram_ns_base_addr;
170
171void __init exynos_sysram_init(void)
172{
173 struct device_node *node;
174
175 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
176 if (!of_device_is_available(node))
177 continue;
178 sysram_base_addr = of_iomap(node, 0);
179 break;
180 }
181
182 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
183 if (!of_device_is_available(node))
184 continue;
185 sysram_ns_base_addr = of_iomap(node, 0);
186 break;
187 }
188}
189
5e299f65 190static void __init exynos_init_late(void)
bb13fabc 191{
2edb36c4
KK
192 if (of_machine_is_compatible("samsung,exynos5440"))
193 /* to be supported later */
194 return;
195
1fd3cbcc 196 pm_genpd_poweroff_unused();
559ba237 197 exynos_pm_init();
bb13fabc
SG
198}
199
564d06b1 200static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
f5f83c71
TA
201 int depth, void *data)
202{
203 struct map_desc iodesc;
3eb93646 204 const __be32 *reg;
9d0c4dfe 205 int len;
f5f83c71
TA
206
207 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
208 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
209 return 0;
210
211 reg = of_get_flat_dt_prop(node, "reg", &len);
212 if (reg == NULL || len != (sizeof(unsigned long) * 2))
213 return 0;
214
215 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
216 iodesc.length = be32_to_cpu(reg[1]) - 1;
217 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
218 iodesc.type = MT_DEVICE;
219 iotable_init(&iodesc, 1);
220 return 1;
221}
f5f83c71 222
cc511b8d
KK
223/*
224 * exynos_map_io
225 *
226 * register the standard cpu IO areas
227 */
6eb84669
SK
228static void __init exynos_map_io(void)
229{
cbf08b9e 230 if (soc_is_exynos4())
6eb84669
SK
231 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
232
cbf08b9e 233 if (soc_is_exynos5())
6eb84669 234 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
6eb84669 235}
cc511b8d 236
5e299f65 237static void __init exynos_init_io(void)
cc511b8d 238{
9c1fcdcc
DA
239 debug_ll_io_init();
240
04fae596 241 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
2edb36c4 242
cc511b8d
KK
243 /* detect cpu id and rev. */
244 s5p_init_cpu(S5P_VA_CHIPID);
245
6eb84669 246 exynos_map_io();
94c7ca71
KK
247}
248
fce9e5bb
PD
249static const struct of_device_id exynos_dt_pmu_match[] = {
250 { .compatible = "samsung,exynos3250-pmu" },
251 { .compatible = "samsung,exynos4210-pmu" },
252 { .compatible = "samsung,exynos4212-pmu" },
253 { .compatible = "samsung,exynos4412-pmu" },
254 { .compatible = "samsung,exynos5250-pmu" },
98504def 255 { .compatible = "samsung,exynos5410-pmu" },
fce9e5bb
PD
256 { .compatible = "samsung,exynos5420-pmu" },
257 { /*sentinel*/ },
258};
259
260static void exynos_map_pmu(void)
261{
262 struct device_node *np;
263
264 np = of_find_matching_node(NULL, exynos_dt_pmu_match);
265 if (np)
266 pmu_base_addr = of_iomap(np, 0);
267
268 if (!pmu_base_addr)
269 panic("failed to find exynos pmu register\n");
270}
271
272static void __init exynos_init_irq(void)
273{
274 irqchip_init();
275 /*
276 * Since platsmp.c needs pmu base address by the time
277 * DT is not unflatten so we can't use DT APIs before
278 * init_irq
279 */
280 exynos_map_pmu();
281}
282
cbf08b9e 283static void __init exynos_dt_machine_init(void)
cc511b8d 284{
cbf08b9e
SK
285 struct device_node *i2c_np;
286 const char *i2c_compat = "samsung,s3c2440-i2c";
287 unsigned int tmp;
288 int id;
289
290 /*
291 * Exynos5's legacy i2c controller and new high speed i2c
292 * controller have muxed interrupt sources. By default the
293 * interrupts for 4-channel HS-I2C controller are enabled.
294 * If node for first four channels of legacy i2c controller
295 * are available then re-configure the interrupts via the
296 * system register.
297 */
298 if (soc_is_exynos5()) {
299 for_each_compatible_node(i2c_np, NULL, i2c_compat) {
300 if (of_device_is_available(i2c_np)) {
301 id = of_alias_get_id(i2c_np, "i2c");
302 if (id < 4) {
303 tmp = readl(EXYNOS5_SYS_I2C_CFG);
304 writel(tmp & ~(0x1 << id),
305 EXYNOS5_SYS_I2C_CFG);
306 }
307 }
308 }
309 }
94c7ca71 310
1754c42e
OJ
311 /*
312 * This is called from smp_prepare_cpus if we've built for SMP, but
313 * we still need to set it up for PM and firmware ops if not.
314 */
73ea6ec6 315 if (!IS_ENABLED(CONFIG_SMP))
1754c42e
OJ
316 exynos_sysram_init();
317
6887d9e5
PD
318 if (of_machine_is_compatible("samsung,exynos4210") ||
319 of_machine_is_compatible("samsung,exynos5250"))
320 platform_device_register(&exynos_cpuidle);
b5a296cd 321
6887d9e5 322 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
cbf08b9e
SK
323
324 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 325}
cbf08b9e
SK
326
327static char const *exynos_dt_compat[] __initconst = {
940bc58d
CC
328 "samsung,exynos3",
329 "samsung,exynos3250",
4868123c 330 "samsung,exynos4",
cbf08b9e
SK
331 "samsung,exynos4210",
332 "samsung,exynos4212",
333 "samsung,exynos4412",
4868123c 334 "samsung,exynos5",
cbf08b9e 335 "samsung,exynos5250",
ed08f103 336 "samsung,exynos5260",
cbf08b9e
SK
337 "samsung,exynos5420",
338 "samsung,exynos5440",
339 NULL
340};
341
342static void __init exynos_reserve(void)
343{
344#ifdef CONFIG_S5P_DEV_MFC
345 int i;
346 char *mfc_mem[] = {
347 "samsung,mfc-v5",
348 "samsung,mfc-v6",
349 "samsung,mfc-v7",
350 };
351
352 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
353 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
354 break;
355#endif
356}
357
358DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
359 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
360 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
15b0bc40
RK
361 .l2c_aux_val = 0x3c400001,
362 .l2c_aux_mask = 0xc20fffff,
cbf08b9e
SK
363 .smp = smp_ops(exynos_smp_ops),
364 .map_io = exynos_init_io,
365 .init_early = exynos_firmware_init,
fce9e5bb 366 .init_irq = exynos_init_irq,
cbf08b9e
SK
367 .init_machine = exynos_dt_machine_init,
368 .init_late = exynos_init_late,
369 .dt_compat = exynos_dt_compat,
370 .restart = exynos_restart,
371 .reserve = exynos_reserve,
372MACHINE_END
This page took 0.181497 seconds and 5 git commands to generate.