cpuidle: exynos: add coupled cpuidle support for exynos4210
[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,
cc511b8d
KK
43 }, {
44 .virtual = (unsigned long)S5P_VA_SROMC,
45 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
46 .length = SZ_4K,
47 .type = MT_DEVICE,
94c7ca71 48 }, {
cc511b8d
KK
49 .virtual = (unsigned long)S5P_VA_CMU,
50 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
51 .length = SZ_128K,
52 .type = MT_DEVICE,
53 }, {
54 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
55 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
56 .length = SZ_8K,
57 .type = MT_DEVICE,
cc511b8d
KK
58 }, {
59 .virtual = (unsigned long)S5P_VA_DMC0,
60 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
2bde0b08
MH
61 .length = SZ_64K,
62 .type = MT_DEVICE,
63 }, {
64 .virtual = (unsigned long)S5P_VA_DMC1,
65 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
66 .length = SZ_64K,
cc511b8d 67 .type = MT_DEVICE,
cc511b8d
KK
68 },
69};
70
94c7ca71
KK
71static struct map_desc exynos5_iodesc[] __initdata = {
72 {
73 .virtual = (unsigned long)S3C_VA_SYS,
74 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
75 .length = SZ_64K,
76 .type = MT_DEVICE,
94c7ca71
KK
77 }, {
78 .virtual = (unsigned long)S5P_VA_SROMC,
79 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
80 .length = SZ_4K,
81 .type = MT_DEVICE,
94c7ca71
KK
82 }, {
83 .virtual = (unsigned long)S5P_VA_CMU,
84 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
85 .length = 144 * SZ_1K,
86 .type = MT_DEVICE,
2edb36c4
KK
87 },
88};
89
35baa336 90static struct platform_device exynos_cpuidle = {
277f5046 91 .name = "exynos_cpuidle",
658cff0d 92#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
277f5046 93 .dev.platform_data = exynos_enter_aftr,
658cff0d 94#endif
277f5046 95 .id = -1,
35baa336
BZ
96};
97
1754c42e
OJ
98void __iomem *sysram_base_addr;
99void __iomem *sysram_ns_base_addr;
100
101void __init exynos_sysram_init(void)
102{
103 struct device_node *node;
104
105 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
106 if (!of_device_is_available(node))
107 continue;
108 sysram_base_addr = of_iomap(node, 0);
109 break;
110 }
111
112 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
113 if (!of_device_is_available(node))
114 continue;
115 sysram_ns_base_addr = of_iomap(node, 0);
116 break;
117 }
118}
119
5e299f65 120static void __init exynos_init_late(void)
bb13fabc 121{
2edb36c4
KK
122 if (of_machine_is_compatible("samsung,exynos5440"))
123 /* to be supported later */
124 return;
125
559ba237 126 exynos_pm_init();
bb13fabc
SG
127}
128
564d06b1 129static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
f5f83c71
TA
130 int depth, void *data)
131{
132 struct map_desc iodesc;
3eb93646 133 const __be32 *reg;
9d0c4dfe 134 int len;
f5f83c71
TA
135
136 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
137 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
138 return 0;
139
140 reg = of_get_flat_dt_prop(node, "reg", &len);
141 if (reg == NULL || len != (sizeof(unsigned long) * 2))
142 return 0;
143
144 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
145 iodesc.length = be32_to_cpu(reg[1]) - 1;
146 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
147 iodesc.type = MT_DEVICE;
148 iotable_init(&iodesc, 1);
149 return 1;
150}
f5f83c71 151
cc511b8d
KK
152/*
153 * exynos_map_io
154 *
155 * register the standard cpu IO areas
156 */
6eb84669
SK
157static void __init exynos_map_io(void)
158{
cbf08b9e 159 if (soc_is_exynos4())
6eb84669
SK
160 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
161
cbf08b9e 162 if (soc_is_exynos5())
6eb84669 163 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
6eb84669 164}
cc511b8d 165
5e299f65 166static void __init exynos_init_io(void)
cc511b8d 167{
9c1fcdcc
DA
168 debug_ll_io_init();
169
04fae596 170 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
2edb36c4 171
cc511b8d
KK
172 /* detect cpu id and rev. */
173 s5p_init_cpu(S5P_VA_CHIPID);
174
6eb84669 175 exynos_map_io();
94c7ca71
KK
176}
177
fce9e5bb
PD
178static const struct of_device_id exynos_dt_pmu_match[] = {
179 { .compatible = "samsung,exynos3250-pmu" },
180 { .compatible = "samsung,exynos4210-pmu" },
181 { .compatible = "samsung,exynos4212-pmu" },
182 { .compatible = "samsung,exynos4412-pmu" },
c0adae9e 183 { .compatible = "samsung,exynos4415-pmu" },
fce9e5bb 184 { .compatible = "samsung,exynos5250-pmu" },
22ead0d7 185 { .compatible = "samsung,exynos5260-pmu" },
98504def 186 { .compatible = "samsung,exynos5410-pmu" },
fce9e5bb
PD
187 { .compatible = "samsung,exynos5420-pmu" },
188 { /*sentinel*/ },
189};
190
191static void exynos_map_pmu(void)
192{
193 struct device_node *np;
194
195 np = of_find_matching_node(NULL, exynos_dt_pmu_match);
196 if (np)
197 pmu_base_addr = of_iomap(np, 0);
198
199 if (!pmu_base_addr)
200 panic("failed to find exynos pmu register\n");
201}
202
203static void __init exynos_init_irq(void)
204{
205 irqchip_init();
206 /*
207 * Since platsmp.c needs pmu base address by the time
208 * DT is not unflatten so we can't use DT APIs before
209 * init_irq
210 */
211 exynos_map_pmu();
212}
213
cbf08b9e 214static void __init exynos_dt_machine_init(void)
cc511b8d 215{
cbf08b9e
SK
216 struct device_node *i2c_np;
217 const char *i2c_compat = "samsung,s3c2440-i2c";
218 unsigned int tmp;
219 int id;
220
221 /*
222 * Exynos5's legacy i2c controller and new high speed i2c
223 * controller have muxed interrupt sources. By default the
224 * interrupts for 4-channel HS-I2C controller are enabled.
225 * If node for first four channels of legacy i2c controller
226 * are available then re-configure the interrupts via the
227 * system register.
228 */
229 if (soc_is_exynos5()) {
230 for_each_compatible_node(i2c_np, NULL, i2c_compat) {
231 if (of_device_is_available(i2c_np)) {
232 id = of_alias_get_id(i2c_np, "i2c");
233 if (id < 4) {
234 tmp = readl(EXYNOS5_SYS_I2C_CFG);
235 writel(tmp & ~(0x1 << id),
236 EXYNOS5_SYS_I2C_CFG);
237 }
238 }
239 }
240 }
94c7ca71 241
1754c42e
OJ
242 /*
243 * This is called from smp_prepare_cpus if we've built for SMP, but
244 * we still need to set it up for PM and firmware ops if not.
245 */
73ea6ec6 246 if (!IS_ENABLED(CONFIG_SMP))
1754c42e
OJ
247 exynos_sysram_init();
248
712eddf7
BZ
249#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
250 if (of_machine_is_compatible("samsung,exynos4210"))
251 exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
252#endif
6887d9e5 253 if (of_machine_is_compatible("samsung,exynos4210") ||
42d5dc37
BZ
254 of_machine_is_compatible("samsung,exynos4212") ||
255 (of_machine_is_compatible("samsung,exynos4412") &&
256 of_machine_is_compatible("samsung,trats2")) ||
257 of_machine_is_compatible("samsung,exynos5250"))
6887d9e5 258 platform_device_register(&exynos_cpuidle);
b5a296cd 259
6887d9e5 260 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
cbf08b9e
SK
261
262 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
cc511b8d 263}
cbf08b9e
SK
264
265static char const *exynos_dt_compat[] __initconst = {
940bc58d
CC
266 "samsung,exynos3",
267 "samsung,exynos3250",
4868123c 268 "samsung,exynos4",
cbf08b9e
SK
269 "samsung,exynos4210",
270 "samsung,exynos4212",
271 "samsung,exynos4412",
c0adae9e 272 "samsung,exynos4415",
4868123c 273 "samsung,exynos5",
cbf08b9e 274 "samsung,exynos5250",
ed08f103 275 "samsung,exynos5260",
cbf08b9e
SK
276 "samsung,exynos5420",
277 "samsung,exynos5440",
278 NULL
279};
280
281static void __init exynos_reserve(void)
282{
283#ifdef CONFIG_S5P_DEV_MFC
284 int i;
285 char *mfc_mem[] = {
286 "samsung,mfc-v5",
287 "samsung,mfc-v6",
288 "samsung,mfc-v7",
289 };
290
291 for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
292 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
293 break;
294#endif
295}
296
5a12a597
LA
297static void __init exynos_dt_fixup(void)
298{
299 /*
300 * Some versions of uboot pass garbage entries in the memory node,
301 * use the old CONFIG_ARM_NR_BANKS
302 */
303 of_fdt_limit_memory(8);
304}
305
cbf08b9e
SK
306DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
307 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
308 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
15b0bc40
RK
309 .l2c_aux_val = 0x3c400001,
310 .l2c_aux_mask = 0xc20fffff,
cbf08b9e
SK
311 .smp = smp_ops(exynos_smp_ops),
312 .map_io = exynos_init_io,
313 .init_early = exynos_firmware_init,
fce9e5bb 314 .init_irq = exynos_init_irq,
cbf08b9e
SK
315 .init_machine = exynos_dt_machine_init,
316 .init_late = exynos_init_late,
317 .dt_compat = exynos_dt_compat,
cbf08b9e 318 .reserve = exynos_reserve,
5a12a597 319 .dt_fixup = exynos_dt_fixup,
cbf08b9e 320MACHINE_END
This page took 0.185757 seconds and 5 git commands to generate.