ARM: SAMSUNG: Restore Samsung PM Debug functionality
[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
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" },
22ead0d7 255 { .compatible = "samsung,exynos5260-pmu" },
98504def 256 { .compatible = "samsung,exynos5410-pmu" },
fce9e5bb
PD
257 { .compatible = "samsung,exynos5420-pmu" },
258 { /*sentinel*/ },
259};
260
261static void exynos_map_pmu(void)
262{
263 struct device_node *np;
264
265 np = of_find_matching_node(NULL, exynos_dt_pmu_match);
266 if (np)
267 pmu_base_addr = of_iomap(np, 0);
268
269 if (!pmu_base_addr)
270 panic("failed to find exynos pmu register\n");
271}
272
273static void __init exynos_init_irq(void)
274{
275 irqchip_init();
276 /*
277 * Since platsmp.c needs pmu base address by the time
278 * DT is not unflatten so we can't use DT APIs before
279 * init_irq
280 */
281 exynos_map_pmu();
282}
283
cbf08b9e 284static void __init exynos_dt_machine_init(void)
cc511b8d 285{
cbf08b9e
SK
286 struct device_node *i2c_np;
287 const char *i2c_compat = "samsung,s3c2440-i2c";
288 unsigned int tmp;
289 int id;
290
291 /*
292 * Exynos5's legacy i2c controller and new high speed i2c
293 * controller have muxed interrupt sources. By default the
294 * interrupts for 4-channel HS-I2C controller are enabled.
295 * If node for first four channels of legacy i2c controller
296 * are available then re-configure the interrupts via the
297 * system register.
298 */
299 if (soc_is_exynos5()) {
300 for_each_compatible_node(i2c_np, NULL, i2c_compat) {
301 if (of_device_is_available(i2c_np)) {
302 id = of_alias_get_id(i2c_np, "i2c");
303 if (id < 4) {
304 tmp = readl(EXYNOS5_SYS_I2C_CFG);
305 writel(tmp & ~(0x1 << id),
306 EXYNOS5_SYS_I2C_CFG);
307 }
308 }
309 }
310 }
94c7ca71 311
1754c42e
OJ
312 /*
313 * This is called from smp_prepare_cpus if we've built for SMP, but
314 * we still need to set it up for PM and firmware ops if not.
315 */
73ea6ec6 316 if (!IS_ENABLED(CONFIG_SMP))
1754c42e
OJ
317 exynos_sysram_init();
318
6887d9e5
PD
319 if (of_machine_is_compatible("samsung,exynos4210") ||
320 of_machine_is_compatible("samsung,exynos5250"))
321 platform_device_register(&exynos_cpuidle);
b5a296cd 322
6887d9e5 323 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
cbf08b9e
SK
324
325 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 326}
cbf08b9e
SK
327
328static char const *exynos_dt_compat[] __initconst = {
940bc58d
CC
329 "samsung,exynos3",
330 "samsung,exynos3250",
4868123c 331 "samsung,exynos4",
cbf08b9e
SK
332 "samsung,exynos4210",
333 "samsung,exynos4212",
334 "samsung,exynos4412",
4868123c 335 "samsung,exynos5",
cbf08b9e 336 "samsung,exynos5250",
ed08f103 337 "samsung,exynos5260",
cbf08b9e
SK
338 "samsung,exynos5420",
339 "samsung,exynos5440",
340 NULL
341};
342
343static void __init exynos_reserve(void)
344{
345#ifdef CONFIG_S5P_DEV_MFC
346 int i;
347 char *mfc_mem[] = {
348 "samsung,mfc-v5",
349 "samsung,mfc-v6",
350 "samsung,mfc-v7",
351 };
352
353 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
354 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
355 break;
356#endif
357}
358
5a12a597
LA
359static void __init exynos_dt_fixup(void)
360{
361 /*
362 * Some versions of uboot pass garbage entries in the memory node,
363 * use the old CONFIG_ARM_NR_BANKS
364 */
365 of_fdt_limit_memory(8);
366}
367
cbf08b9e
SK
368DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
369 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
370 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
15b0bc40
RK
371 .l2c_aux_val = 0x3c400001,
372 .l2c_aux_mask = 0xc20fffff,
cbf08b9e
SK
373 .smp = smp_ops(exynos_smp_ops),
374 .map_io = exynos_init_io,
375 .init_early = exynos_firmware_init,
fce9e5bb 376 .init_irq = exynos_init_irq,
cbf08b9e
SK
377 .init_machine = exynos_dt_machine_init,
378 .init_late = exynos_init_late,
379 .dt_compat = exynos_dt_compat,
380 .restart = exynos_restart,
381 .reserve = exynos_reserve,
5a12a597 382 .dt_fixup = exynos_dt_fixup,
cbf08b9e 383MACHINE_END
This page took 0.1826 seconds and 5 git commands to generate.