2 * SAMSUNG EXYNOS Flattened Device Tree enabled machine
4 * Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
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.
12 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/serial_s3c.h>
17 #include <linux/of_address.h>
18 #include <linux/of_fdt.h>
19 #include <linux/of_platform.h>
20 #include <linux/platform_device.h>
21 #include <linux/pm_domain.h>
23 #include <asm/cacheflush.h>
24 #include <asm/hardware/cache-l2x0.h>
25 #include <asm/mach/arch.h>
26 #include <asm/mach/map.h>
27 #include <asm/memory.h>
33 #define L2_AUX_VAL 0x7C470001
34 #define L2_AUX_MASK 0xC200ffff
36 static struct map_desc exynos4_iodesc
[] __initdata
= {
38 .virtual = (unsigned long)S3C_VA_SYS
,
39 .pfn
= __phys_to_pfn(EXYNOS4_PA_SYSCON
),
43 .virtual = (unsigned long)S3C_VA_TIMER
,
44 .pfn
= __phys_to_pfn(EXYNOS4_PA_TIMER
),
48 .virtual = (unsigned long)S3C_VA_WATCHDOG
,
49 .pfn
= __phys_to_pfn(EXYNOS4_PA_WATCHDOG
),
53 .virtual = (unsigned long)S5P_VA_SROMC
,
54 .pfn
= __phys_to_pfn(EXYNOS4_PA_SROMC
),
58 .virtual = (unsigned long)S5P_VA_SYSTIMER
,
59 .pfn
= __phys_to_pfn(EXYNOS4_PA_SYSTIMER
),
63 .virtual = (unsigned long)S5P_VA_PMU
,
64 .pfn
= __phys_to_pfn(EXYNOS4_PA_PMU
),
68 .virtual = (unsigned long)S5P_VA_COMBINER_BASE
,
69 .pfn
= __phys_to_pfn(EXYNOS4_PA_COMBINER
),
73 .virtual = (unsigned long)S5P_VA_GIC_CPU
,
74 .pfn
= __phys_to_pfn(EXYNOS4_PA_GIC_CPU
),
78 .virtual = (unsigned long)S5P_VA_GIC_DIST
,
79 .pfn
= __phys_to_pfn(EXYNOS4_PA_GIC_DIST
),
83 .virtual = (unsigned long)S5P_VA_CMU
,
84 .pfn
= __phys_to_pfn(EXYNOS4_PA_CMU
),
88 .virtual = (unsigned long)S5P_VA_COREPERI_BASE
,
89 .pfn
= __phys_to_pfn(EXYNOS4_PA_COREPERI
),
93 .virtual = (unsigned long)S5P_VA_L2CC
,
94 .pfn
= __phys_to_pfn(EXYNOS4_PA_L2CC
),
98 .virtual = (unsigned long)S5P_VA_DMC0
,
99 .pfn
= __phys_to_pfn(EXYNOS4_PA_DMC0
),
103 .virtual = (unsigned long)S5P_VA_DMC1
,
104 .pfn
= __phys_to_pfn(EXYNOS4_PA_DMC1
),
108 .virtual = (unsigned long)S3C_VA_USB_HSPHY
,
109 .pfn
= __phys_to_pfn(EXYNOS4_PA_HSPHY
),
115 static struct map_desc exynos4_iodesc0
[] __initdata
= {
117 .virtual = (unsigned long)S5P_VA_SYSRAM
,
118 .pfn
= __phys_to_pfn(EXYNOS4_PA_SYSRAM0
),
124 static struct map_desc exynos4_iodesc1
[] __initdata
= {
126 .virtual = (unsigned long)S5P_VA_SYSRAM
,
127 .pfn
= __phys_to_pfn(EXYNOS4_PA_SYSRAM1
),
133 static struct map_desc exynos4210_iodesc
[] __initdata
= {
135 .virtual = (unsigned long)S5P_VA_SYSRAM_NS
,
136 .pfn
= __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS
),
142 static struct map_desc exynos4x12_iodesc
[] __initdata
= {
144 .virtual = (unsigned long)S5P_VA_SYSRAM_NS
,
145 .pfn
= __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS
),
151 static struct map_desc exynos5250_iodesc
[] __initdata
= {
153 .virtual = (unsigned long)S5P_VA_SYSRAM_NS
,
154 .pfn
= __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS
),
160 static struct map_desc exynos5_iodesc
[] __initdata
= {
162 .virtual = (unsigned long)S3C_VA_SYS
,
163 .pfn
= __phys_to_pfn(EXYNOS5_PA_SYSCON
),
167 .virtual = (unsigned long)S3C_VA_TIMER
,
168 .pfn
= __phys_to_pfn(EXYNOS5_PA_TIMER
),
172 .virtual = (unsigned long)S3C_VA_WATCHDOG
,
173 .pfn
= __phys_to_pfn(EXYNOS5_PA_WATCHDOG
),
177 .virtual = (unsigned long)S5P_VA_SROMC
,
178 .pfn
= __phys_to_pfn(EXYNOS5_PA_SROMC
),
182 .virtual = (unsigned long)S5P_VA_SYSRAM
,
183 .pfn
= __phys_to_pfn(EXYNOS5_PA_SYSRAM
),
187 .virtual = (unsigned long)S5P_VA_CMU
,
188 .pfn
= __phys_to_pfn(EXYNOS5_PA_CMU
),
189 .length
= 144 * SZ_1K
,
192 .virtual = (unsigned long)S5P_VA_PMU
,
193 .pfn
= __phys_to_pfn(EXYNOS5_PA_PMU
),
199 void exynos_restart(enum reboot_mode mode
, const char *cmd
)
201 struct device_node
*np
;
203 void __iomem
*addr
= EXYNOS_SWRESET
;
205 if (of_machine_is_compatible("samsung,exynos5440")) {
207 np
= of_find_compatible_node(NULL
, NULL
, "samsung,exynos5440-clock");
209 addr
= of_iomap(np
, 0) + 0xbc;
210 status
= __raw_readl(addr
);
212 addr
= of_iomap(np
, 0) + 0xcc;
213 val
= __raw_readl(addr
);
215 val
= (val
& 0xffff0000) | (status
& 0xffff);
218 __raw_writel(val
, addr
);
221 static struct platform_device exynos_cpuidle
= {
222 .name
= "exynos_cpuidle",
226 void __init
exynos_cpuidle_init(void)
228 platform_device_register(&exynos_cpuidle
);
231 void __init
exynos_cpufreq_init(void)
233 platform_device_register_simple("exynos-cpufreq", -1, NULL
, 0);
236 void __init
exynos_init_late(void)
238 if (of_machine_is_compatible("samsung,exynos5440"))
239 /* to be supported later */
242 pm_genpd_poweroff_unused();
246 static int __init
exynos_fdt_map_chipid(unsigned long node
, const char *uname
,
247 int depth
, void *data
)
249 struct map_desc iodesc
;
253 if (!of_flat_dt_is_compatible(node
, "samsung,exynos4210-chipid") &&
254 !of_flat_dt_is_compatible(node
, "samsung,exynos5440-clock"))
257 reg
= of_get_flat_dt_prop(node
, "reg", &len
);
258 if (reg
== NULL
|| len
!= (sizeof(unsigned long) * 2))
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);
272 * register the standard cpu IO areas
274 static void __init
exynos_map_io(void)
276 if (soc_is_exynos4())
277 iotable_init(exynos4_iodesc
, ARRAY_SIZE(exynos4_iodesc
));
279 if (soc_is_exynos5())
280 iotable_init(exynos5_iodesc
, ARRAY_SIZE(exynos5_iodesc
));
282 if (soc_is_exynos4210()) {
283 if (samsung_rev() == EXYNOS4210_REV_0
)
284 iotable_init(exynos4_iodesc0
,
285 ARRAY_SIZE(exynos4_iodesc0
));
287 iotable_init(exynos4_iodesc1
,
288 ARRAY_SIZE(exynos4_iodesc1
));
289 iotable_init(exynos4210_iodesc
, ARRAY_SIZE(exynos4210_iodesc
));
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
));
297 void __init
exynos_init_io(void)
301 of_scan_flat_dt(exynos_fdt_map_chipid
, NULL
);
303 /* detect cpu id and rev. */
304 s5p_init_cpu(S5P_VA_CHIPID
);
309 static int __init
exynos4_l2x0_cache_init(void)
313 ret
= l2x0_of_init(L2_AUX_VAL
, L2_AUX_MASK
);
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));
323 early_initcall(exynos4_l2x0_cache_init
);
325 static void __init
exynos_dt_machine_init(void)
327 struct device_node
*i2c_np
;
328 const char *i2c_compat
= "samsung,s3c2440-i2c";
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
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");
345 tmp
= readl(EXYNOS5_SYS_I2C_CFG
);
346 writel(tmp
& ~(0x1 << id
),
347 EXYNOS5_SYS_I2C_CFG
);
353 exynos_cpuidle_init();
354 exynos_cpufreq_init();
356 of_platform_populate(NULL
, of_default_bus_match_table
, NULL
, NULL
);
359 static char const *exynos_dt_compat
[] __initconst
= {
361 "samsung,exynos4210",
362 "samsung,exynos4212",
363 "samsung,exynos4412",
365 "samsung,exynos5250",
366 "samsung,exynos5420",
367 "samsung,exynos5440",
371 static void __init
exynos_reserve(void)
373 #ifdef CONFIG_S5P_DEV_MFC
381 for (i
= 0; i
< ARRAY_SIZE(mfc_mem
); i
++)
382 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem
, mfc_mem
[i
]))
387 DT_MACHINE_START(EXYNOS_DT
, "SAMSUNG EXYNOS (Flattened Device Tree)")
388 /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
389 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
390 .smp
= smp_ops(exynos_smp_ops
),
391 .map_io
= exynos_init_io
,
392 .init_early
= exynos_firmware_init
,
393 .init_machine
= exynos_dt_machine_init
,
394 .init_late
= exynos_init_late
,
395 .dt_compat
= exynos_dt_compat
,
396 .restart
= exynos_restart
,
397 .reserve
= exynos_reserve
,