blob: cd70d74c8eecc5bdbd5cb8c17b7dfec5d3503348 [file] [log] [blame]
Kukjin Kimcc511b82011-12-27 08:18:36 +01001/*
2 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Common Codes for EXYNOS
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
12#include <linux/kernel.h>
Tomasz Figa68a433f2013-05-25 06:27:29 +090013#include <linux/bitops.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010014#include <linux/interrupt.h>
15#include <linux/irq.h>
Rob Herringa900e5d2013-02-12 16:04:52 -060016#include <linux/irqchip.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010017#include <linux/io.h>
Linus Torvalds7affca32012-01-07 12:03:30 -080018#include <linux/device.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010019#include <linux/gpio.h>
Tomasz Figa68a433f2013-05-25 06:27:29 +090020#include <clocksource/samsung_pwm.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010021#include <linux/sched.h>
22#include <linux/serial_core.h>
Arnd Bergmann237c78b2012-01-07 12:30:20 +000023#include <linux/of.h>
Doug Anderson5b7897d2012-11-27 11:53:14 -080024#include <linux/of_fdt.h>
Arnd Bergmann237c78b2012-01-07 12:30:20 +000025#include <linux/of_irq.h>
Sylwester Nawrocki1fd3cbc2013-12-21 06:33:30 +090026#include <linux/pm_domain.h>
Thomas Abraham1e60bc02012-05-15 16:18:35 +090027#include <linux/export.h>
28#include <linux/irqdomain.h>
Thomas Abrahame873a472012-05-15 16:25:23 +090029#include <linux/of_address.h>
Rob Herring520f7bd2012-12-27 13:10:24 -060030#include <linux/irqchip/arm-gic.h>
Catalin Marinasde88cbb2013-01-18 15:31:37 +000031#include <linux/irqchip/chained_irq.h>
Bartlomiej Zolnierkiewicz35baa332013-08-30 12:15:04 +020032#include <linux/platform_device.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010033
34#include <asm/proc-fns.h>
Arnd Bergmann40ba95f2012-01-07 11:51:28 +000035#include <asm/exception.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010036#include <asm/hardware/cache-l2x0.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010037#include <asm/mach/map.h>
38#include <asm/mach/irq.h>
Amit Daniel Kachhapb756a502012-03-08 02:07:41 -080039#include <asm/cacheflush.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010040
Kukjin Kimcc511b82011-12-27 08:18:36 +010041#include <plat/cpu.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010042#include <plat/pm.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010043#include <plat/regs-serial.h>
44
45#include "common.h"
Kukjin Kim65c9a852013-12-19 04:06:56 +090046#include "regs-pmu.h"
47
Amit Daniel Kachhap6cdeddc2012-03-08 02:09:12 -080048#define L2_AUX_VAL 0x7C470001
49#define L2_AUX_MASK 0xC200ffff
Kukjin Kimcc511b82011-12-27 08:18:36 +010050
Kukjin Kimcc511b82011-12-27 08:18:36 +010051/* Initial IO mappings */
52
Kukjin Kim94c7ca72012-02-11 22:15:45 +090053static struct map_desc exynos4_iodesc[] __initdata = {
54 {
Kukjin Kimcc511b82011-12-27 08:18:36 +010055 .virtual = (unsigned long)S3C_VA_SYS,
56 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
57 .length = SZ_64K,
58 .type = MT_DEVICE,
59 }, {
60 .virtual = (unsigned long)S3C_VA_TIMER,
61 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
62 .length = SZ_16K,
63 .type = MT_DEVICE,
64 }, {
65 .virtual = (unsigned long)S3C_VA_WATCHDOG,
66 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
67 .length = SZ_4K,
68 .type = MT_DEVICE,
69 }, {
70 .virtual = (unsigned long)S5P_VA_SROMC,
71 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
72 .length = SZ_4K,
73 .type = MT_DEVICE,
74 }, {
75 .virtual = (unsigned long)S5P_VA_SYSTIMER,
76 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
77 .length = SZ_4K,
78 .type = MT_DEVICE,
79 }, {
80 .virtual = (unsigned long)S5P_VA_PMU,
81 .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
82 .length = SZ_64K,
83 .type = MT_DEVICE,
84 }, {
85 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
86 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
87 .length = SZ_4K,
88 .type = MT_DEVICE,
89 }, {
90 .virtual = (unsigned long)S5P_VA_GIC_CPU,
91 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
92 .length = SZ_64K,
93 .type = MT_DEVICE,
94 }, {
95 .virtual = (unsigned long)S5P_VA_GIC_DIST,
96 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
97 .length = SZ_64K,
98 .type = MT_DEVICE,
99 }, {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100100 .virtual = (unsigned long)S5P_VA_CMU,
101 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
102 .length = SZ_128K,
103 .type = MT_DEVICE,
104 }, {
105 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
106 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
107 .length = SZ_8K,
108 .type = MT_DEVICE,
109 }, {
110 .virtual = (unsigned long)S5P_VA_L2CC,
111 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
112 .length = SZ_4K,
113 .type = MT_DEVICE,
114 }, {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100115 .virtual = (unsigned long)S5P_VA_DMC0,
116 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
MyungJoo Ham2bde0b02011-12-01 15:12:30 +0900117 .length = SZ_64K,
118 .type = MT_DEVICE,
119 }, {
120 .virtual = (unsigned long)S5P_VA_DMC1,
121 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
122 .length = SZ_64K,
Kukjin Kimcc511b82011-12-27 08:18:36 +0100123 .type = MT_DEVICE,
124 }, {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100125 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
126 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
127 .length = SZ_4K,
128 .type = MT_DEVICE,
129 },
130};
131
132static struct map_desc exynos4_iodesc0[] __initdata = {
133 {
134 .virtual = (unsigned long)S5P_VA_SYSRAM,
135 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
136 .length = SZ_4K,
137 .type = MT_DEVICE,
138 },
139};
140
141static struct map_desc exynos4_iodesc1[] __initdata = {
142 {
143 .virtual = (unsigned long)S5P_VA_SYSRAM,
144 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
145 .length = SZ_4K,
146 .type = MT_DEVICE,
147 },
148};
149
Tomasz Figa41de8982012-12-11 13:58:43 +0900150static struct map_desc exynos4210_iodesc[] __initdata = {
151 {
152 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
153 .pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
154 .length = SZ_4K,
155 .type = MT_DEVICE,
156 },
157};
158
159static struct map_desc exynos4x12_iodesc[] __initdata = {
160 {
161 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
162 .pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
163 .length = SZ_4K,
164 .type = MT_DEVICE,
165 },
166};
167
168static struct map_desc exynos5250_iodesc[] __initdata = {
169 {
170 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
171 .pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
172 .length = SZ_4K,
173 .type = MT_DEVICE,
174 },
175};
176
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900177static struct map_desc exynos5_iodesc[] __initdata = {
178 {
179 .virtual = (unsigned long)S3C_VA_SYS,
180 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
181 .length = SZ_64K,
182 .type = MT_DEVICE,
183 }, {
184 .virtual = (unsigned long)S3C_VA_TIMER,
185 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
186 .length = SZ_16K,
187 .type = MT_DEVICE,
188 }, {
189 .virtual = (unsigned long)S3C_VA_WATCHDOG,
190 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
191 .length = SZ_4K,
192 .type = MT_DEVICE,
193 }, {
194 .virtual = (unsigned long)S5P_VA_SROMC,
195 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
196 .length = SZ_4K,
197 .type = MT_DEVICE,
198 }, {
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900199 .virtual = (unsigned long)S5P_VA_SYSRAM,
200 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
201 .length = SZ_4K,
202 .type = MT_DEVICE,
203 }, {
204 .virtual = (unsigned long)S5P_VA_CMU,
205 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
206 .length = 144 * SZ_1K,
207 .type = MT_DEVICE,
208 }, {
209 .virtual = (unsigned long)S5P_VA_PMU,
210 .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
211 .length = SZ_64K,
212 .type = MT_DEVICE,
Kukjin Kim2edb36c2012-11-15 15:48:56 +0900213 },
214};
215
Robin Holt7b6d8642013-07-08 16:01:40 -0700216void exynos4_restart(enum reboot_mode mode, const char *cmd)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100217{
218 __raw_writel(0x1, S5P_SWRESET);
219}
220
Robin Holt7b6d8642013-07-08 16:01:40 -0700221void exynos5_restart(enum reboot_mode mode, const char *cmd)
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900222{
Thomas Abraham60db7e52013-01-24 10:09:13 -0800223 struct device_node *np;
Kukjin Kim2edb36c2012-11-15 15:48:56 +0900224 u32 val;
225 void __iomem *addr;
226
Chander Kashyapeff4e7c2013-06-19 00:29:35 +0900227 val = 0x1;
228 addr = EXYNOS_SWRESET;
229
230 if (of_machine_is_compatible("samsung,exynos5440")) {
Jungseok Lee1ba830c2013-05-25 06:33:03 +0900231 u32 status;
Thomas Abraham60db7e52013-01-24 10:09:13 -0800232 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
Jungseok Lee1ba830c2013-05-25 06:33:03 +0900233
234 addr = of_iomap(np, 0) + 0xbc;
235 status = __raw_readl(addr);
236
Thomas Abraham60db7e52013-01-24 10:09:13 -0800237 addr = of_iomap(np, 0) + 0xcc;
Jungseok Lee1ba830c2013-05-25 06:33:03 +0900238 val = __raw_readl(addr);
239
240 val = (val & 0xffff0000) | (status & 0xffff);
Kukjin Kim2edb36c2012-11-15 15:48:56 +0900241 }
242
243 __raw_writel(val, addr);
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900244}
245
Bartlomiej Zolnierkiewicz35baa332013-08-30 12:15:04 +0200246static struct platform_device exynos_cpuidle = {
247 .name = "exynos_cpuidle",
248 .id = -1,
249};
250
251void __init exynos_cpuidle_init(void)
252{
253 platform_device_register(&exynos_cpuidle);
254}
255
Lukasz Majewskid568b6f2013-11-28 13:42:42 +0100256void __init exynos_cpufreq_init(void)
257{
258 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
259}
260
Shawn Guobb13fab2012-04-26 10:35:40 +0800261void __init exynos_init_late(void)
262{
Kukjin Kim2edb36c2012-11-15 15:48:56 +0900263 if (of_machine_is_compatible("samsung,exynos5440"))
264 /* to be supported later */
265 return;
266
Sylwester Nawrocki1fd3cbc2013-12-21 06:33:30 +0900267 pm_genpd_poweroff_unused();
Shawn Guobb13fab2012-04-26 10:35:40 +0800268}
269
Arnd Bergmann564d06b2013-06-19 01:36:56 +0900270static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
Thomas Abrahamf5f83c72013-04-23 22:46:53 +0900271 int depth, void *data)
272{
273 struct map_desc iodesc;
274 __be32 *reg;
275 unsigned long len;
276
277 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
278 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
279 return 0;
280
281 reg = of_get_flat_dt_prop(node, "reg", &len);
282 if (reg == NULL || len != (sizeof(unsigned long) * 2))
283 return 0;
284
285 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
286 iodesc.length = be32_to_cpu(reg[1]) - 1;
287 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
288 iodesc.type = MT_DEVICE;
289 iotable_init(&iodesc, 1);
290 return 1;
291}
Thomas Abrahamf5f83c72013-04-23 22:46:53 +0900292
Kukjin Kimcc511b82011-12-27 08:18:36 +0100293/*
294 * exynos_map_io
295 *
296 * register the standard cpu IO areas
297 */
Sachin Kamat6eb84662014-03-21 02:09:39 +0900298static void __init exynos_map_io(void)
299{
300 if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412())
301 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
302
303 if (soc_is_exynos5250() || soc_is_exynos5420())
304 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
305
306 if (soc_is_exynos4210()) {
307 if (samsung_rev() == EXYNOS4210_REV_0)
308 iotable_init(exynos4_iodesc0,
309 ARRAY_SIZE(exynos4_iodesc0));
310 else
311 iotable_init(exynos4_iodesc1,
312 ARRAY_SIZE(exynos4_iodesc1));
313 iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
314 }
315 if (soc_is_exynos4212() || soc_is_exynos4412())
316 iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
317 if (soc_is_exynos5250())
318 iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
319}
Kukjin Kimcc511b82011-12-27 08:18:36 +0100320
Arnd Bergmann0e2238e2013-06-19 01:36:47 +0900321void __init exynos_init_io(void)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100322{
Doug Anderson9c1fcdc2013-06-05 13:56:33 -0700323 debug_ll_io_init();
324
Tomasz Figa04fae592013-06-15 09:13:25 +0900325 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
Kukjin Kim2edb36c2012-11-15 15:48:56 +0900326
Kukjin Kimcc511b82011-12-27 08:18:36 +0100327 /* detect cpu id and rev. */
328 s5p_init_cpu(S5P_VA_CHIPID);
329
Sachin Kamat6eb84662014-03-21 02:09:39 +0900330 exynos_map_io();
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900331}
332
Thomas Abraham9ee6af92012-05-15 15:47:40 +0900333struct bus_type exynos_subsys = {
334 .name = "exynos-core",
335 .dev_name = "exynos-core",
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900336};
337
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900338static int __init exynos_core_init(void)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100339{
Thomas Abraham9ee6af92012-05-15 15:47:40 +0900340 return subsys_system_register(&exynos_subsys, NULL);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100341}
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900342core_initcall(exynos_core_init);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100343
Kukjin Kimcc511b82011-12-27 08:18:36 +0100344static int __init exynos4_l2x0_cache_init(void)
345{
Il Hane1b19942012-04-05 07:59:36 -0700346 int ret;
347
Amit Daniel Kachhap6cdeddc2012-03-08 02:09:12 -0800348 ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
Arnd Bergmann87107d82013-06-19 01:36:52 +0900349 if (ret)
350 return ret;
Kukjin Kimcc511b82011-12-27 08:18:36 +0100351
Arnd Bergmann87107d82013-06-19 01:36:52 +0900352 l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
353 clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
Kukjin Kimcc511b82011-12-27 08:18:36 +0100354 return 0;
355}
Kukjin Kimcc511b82011-12-27 08:18:36 +0100356early_initcall(exynos4_l2x0_cache_init);