1 /* linux/arch/arm/mach-s5pv310/cpu.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/clk.h>
12 #include <linux/err.h>
13 #include <linux/sched.h>
14 #include <linux/sysdev.h>
15 #include <linux/delay.h>
16 #include <asm/hardware/cache-l2x0.h>
18 #include <asm/mach/map.h>
19 #include <asm/mach/irq.h>
21 #include <asm/proc-fns.h>
24 #include <plat/devs.h>
25 #include <plat/clock.h>
26 #include <plat/adc-core.h>
27 #include <plat/s5pv310.h>
28 #include <plat/mshci.h>
29 #include <plat/sdhci.h>
30 #include <plat/reset.h>
32 #include <mach/regs-irq.h>
33 #include <mach/regs-pmu.h>
34 #include <mach/irqs.h>
35 #include <mach/ext-gic.h>
36 void __iomem *gic_cpu_base_addr;
38 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
39 unsigned int irq_start);
40 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
43 extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
45 #define s3c_irq_wake NULL
48 unsigned int cpu_revision = 0;
50 static struct map_desc s5pv310_iodesc_evt0[] __initdata = {
52 .virtual = (unsigned long)S5P_VA_SYSRAM,
53 .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM_EVT0),
59 static struct map_desc s5pv310_iodesc_evt1[] __initdata = {
61 .virtual = (unsigned long)S5P_VA_SYSRAM,
62 .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM_EVT1),
68 /* Initial IO mappings */
69 static struct map_desc s5pv310_iodesc_common[] __initdata = {
71 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
72 .pfn = __phys_to_pfn(S5PV310_PA_COREPERI),
76 .virtual = (unsigned long)S5P_VA_EXTGIC_CPU,
77 .pfn = __phys_to_pfn(S5PV310_PA_EXTGIC_CPU),
81 .virtual = (unsigned long)S5P_VA_EXTGIC_DIST,
82 .pfn = __phys_to_pfn(S5PV310_PA_EXTGIC_DIST),
86 .virtual = (unsigned long)S5P_VA_EXTCOMBINER_BASE,
87 .pfn = __phys_to_pfn(S5PV310_PA_EXTCOMBINER),
91 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
92 .pfn = __phys_to_pfn(S5PV310_PA_COMBINER),
96 .virtual = (unsigned long)S5P_VA_L2CC,
97 .pfn = __phys_to_pfn(S5PV310_PA_L2CC),
101 .virtual = (unsigned long)S5P_VA_CMU,
102 .pfn = __phys_to_pfn(S5PV310_PA_CMU),
106 .virtual = (unsigned long)S5P_VA_GPIO2,
107 .pfn = __phys_to_pfn(S5PV310_PA_GPIO2),
111 .virtual = (unsigned long)S5P_VA_GPIO3,
112 .pfn = __phys_to_pfn(S5PV310_PA_GPIO3),
116 .virtual = (unsigned long)S5P_VA_SROMC,
117 .pfn = __phys_to_pfn(S5PV310_PA_SROMC),
121 .virtual = (unsigned long)S5P_VA_PPMU_CPU,
122 .pfn = __phys_to_pfn(S5PV310_PA_PPMU_CPU),
126 .virtual = (unsigned long)S5P_VA_PPMU_LCD0,
127 .pfn = __phys_to_pfn(S5PV310_PA_PPMU_LCD0),
131 .virtual = (unsigned long)S5P_VA_AUDSS,
132 .pfn = __phys_to_pfn(S5PV310_PA_AUDSS),
136 .virtual = (unsigned long)S5PV310_VA_PMU,
137 .pfn = __phys_to_pfn(S5PV310_PA_PMU),
141 .virtual = (unsigned long)S5P_VA_SYSTIMER,
142 .pfn = __phys_to_pfn(S5PV310_PA_SYSTIMER),
146 .virtual = (unsigned long)S3C_VA_GPS,
147 .pfn = __phys_to_pfn(S5PV310_PA_GPS),
151 .virtual = (unsigned long)S5P_VA_DMC0,
152 .pfn = __phys_to_pfn(S5PV310_PA_DMC0),
156 .virtual = (unsigned long)S5P_VA_DMC1,
157 .pfn = __phys_to_pfn(S5PV310_PA_DMC1),
165 static void s5pv310_idle(void)
173 static void s5pv310_power_off(void)
177 printk("Send a signal to S5P_PS_HOLD_CONTROL\n");
178 value = __raw_readl(S5P_PS_HOLD_CONTROL);
180 __raw_writel(value, S5P_PS_HOLD_CONTROL);
185 * register the standard cpu IO areas
187 static void __init __s5pv310_map_io(void)
189 iotable_init(s5pv310_iodesc_common, ARRAY_SIZE(s5pv310_iodesc_common));
191 if (cpu_revision == 0)
192 iotable_init(s5pv310_iodesc_evt0,
193 ARRAY_SIZE(s5pv310_iodesc_evt0));
195 iotable_init(s5pv310_iodesc_evt1,
196 ARRAY_SIZE(s5pv310_iodesc_evt1));
198 /* initialize device information early */
199 #ifdef CONFIG_S3C_DEV_HSMMC
200 s5pv310_default_sdhci0();
202 #ifdef CONFIG_S3C_DEV_HSMMC1
203 s5pv310_default_sdhci1();
205 #ifdef CONFIG_S3C_DEV_HSMMC2
206 s5pv310_default_sdhci2();
208 #ifdef CONFIG_S3C_DEV_HSMMC3
209 s5pv310_default_sdhci3();
211 #ifdef CONFIG_S5P_DEV_MSHC
212 s5pv310_default_mshci();
215 #ifdef CONFIG_S3C_ADC
216 s3c_adc_setname("s5pv210-adc");
218 #ifdef CONFIG_S5P_ADC
219 s3c_adc_setname("s3c-adc");
223 void __init s5pv310_map_io_evt0(void)
226 printk(KERN_INFO "S5PV310 Revision: EVT0\n");
230 void __init s5pv310_map_io_evt1(void)
233 printk(KERN_INFO "S5PV310 Revision: EVT1\n");
237 void __init s5pv310_init_clocks(int xtal)
239 printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
241 s3c24xx_register_baseclocks(xtal);
242 s5p_register_clocks(xtal);
243 s5pv310_register_clocks();
244 s5pv310_setup_clocks();
247 void __init s5pv310_init_irq(void)
251 #ifdef CONFIG_USE_EXT_GIC
252 gic_cpu_base_addr = S5P_VA_EXTGIC_CPU;
253 gic_dist_init(0, S5P_VA_EXTGIC_DIST, IRQ_SPI(0));
254 gic_cpu_init(0, S5P_VA_EXTGIC_CPU);
256 gic_cpu_base_addr = S5P_VA_GIC_CPU;
257 gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_SPI(0));
258 gic_cpu_init(0, S5P_VA_GIC_CPU);
261 for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
263 #ifdef CONFIG_USE_EXT_GIC
264 combiner_init(irq, (void __iomem *)S5P_VA_EXTCOMBINER(irq),
265 COMBINER_IRQ(irq, 0));
267 /* EVT1: From SPI(0) to SPI(39) and SPI(51), SPI(53)
268 * are connected to the interrupt combiner. These irqs
269 * should be initialized to support cascade interrupt.
271 if ((cpu_revision == 0) && (irq >= 40))
272 continue; /* EVT0: MAX = 39 */
273 if ((irq >= 40) && !(irq == 51) && !(irq == 53))
274 continue; /* EVT1: has 51, 53 */
276 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
277 COMBINER_IRQ(irq, 0));
279 combiner_cascade_irq(irq, IRQ_SPI(irq));
282 /* The parameters of s5p_init_irq() are for VIC init.
283 * Theses parameters should be NULL and 0 because S5PV310
284 * uses GIC instead of VIC.
286 s5p_init_irq(NULL, 0);
288 /* Set s3c_irq_wake as set_wake() of GIC irq_chip */
289 get_irq_chip(IRQ_RTC_ALARM)->set_wake = s3c_irq_wake;
292 #ifdef CONFIG_CACHE_L2X0
293 int s5p_l2x0_cache_init(void)
295 /* Data, TAG Latency is 2cycle */
296 __raw_writel(0x111, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
297 __raw_writel(0x111, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
299 /* L2 cache Prefetch Control Register setting */
300 __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
302 /* Power control register setting */
303 __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
304 S5P_VA_L2CC + L2X0_POWER_CTRL);
306 l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
310 early_initcall(s5p_l2x0_cache_init);
313 struct sysdev_class s5pv310_sysclass = {
314 .name = "s5pv310-core",
317 static struct sys_device s5pv310_sysdev = {
318 .cls = &s5pv310_sysclass,
321 static int __init s5pv310_core_init(void)
323 return sysdev_class_register(&s5pv310_sysclass);
326 core_initcall(s5pv310_core_init);
328 #include <mach/regs-clock.h>
329 static void s5pv310_sw_reset(void)
331 /* Clear Sleep/Didle related registers */
332 __raw_writel(0x0, S5P_INFORM0);
333 __raw_writel(0x0, S5P_INFORM1);
334 /* Obsolete: for the compatibility with obsolete s-boot */
335 if (s5pv310_subrev() == 0)
336 __raw_writel(0x0, S5P_INFORM7);
338 __raw_writel(0x1, S5P_SWRESET);
341 #include <mach/universal.h>
342 void s5pv310_inform6_set(char mode)
344 volatile u32 rst_check_flag = 0;
346 __raw_writel(0x0, S5P_INFORM6);
348 #ifdef CONFIG_CHARGER_DETECT_BOOT
349 /* do charger boot in case of power off with cables. */
351 rst_check_flag = rst_check_flag | RST_FLAG_CHARGE_REBOOT_CHECK;
355 #ifdef CONFIG_SAMSUNG_BOOT_MODE
356 if (samsung_fota_config) {
357 rst_check_flag = rst_check_flag | RST_FLAG_FOTA_REBOOT_CHECK;
360 if (samsung_fus_config) {
361 rst_check_flag = rst_check_flag | RST_FLAG_FUS_REBOOT_CHECK;
364 if (samsung_rtl_config) {
365 rst_check_flag = rst_check_flag | RST_FLAG_RTL_REBOOT_CHECK;
369 /* set for intended reset */
370 rst_check_flag |= (RST_FLAG_WDT_MAGIC_CODE << 16);
371 rst_check_flag |= RST_FLAG_INTENTIONAL_WATCHDOG_RESET_CHECK;
373 __raw_writel(CHECK_RST_FLAG_BIT(rst_check_flag), S5P_INFORM6);
375 EXPORT_SYMBOL(s5pv310_inform6_set);
377 static void s5pv310_sc_feedback(void)
381 tmp = __raw_readl(S5P_ARM_CORE0_OPTION);
384 __raw_writel(tmp, S5P_ARM_CORE0_OPTION);
386 tmp = __raw_readl(S5P_ARM_CORE1_OPTION);
389 __raw_writel(tmp, S5P_ARM_CORE1_OPTION);
391 __raw_writel(0x2, S5P_ARM_COMMON_OPTION);
392 __raw_writel(0x2, S5P_CAM_OPTION);
393 __raw_writel(0x2, S5P_TV_OPTION);
394 __raw_writel(0x2, S5P_MFC_OPTION);
395 __raw_writel(0x2, S5P_G3D_OPTION);
396 __raw_writel(0x2, S5P_LCD0_OPTION);
397 __raw_writel(0x2, S5P_LCD1_OPTION);
398 __raw_writel(0x2, S5P_GPS_OPTION);
399 __raw_writel(0x2, S5P_GPS_ALIVE_OPTION);
402 int s5pv310_get_max_speed(void)
404 static int max_speed = -1;
406 if (unlikely(max_speed < 0)) {
407 struct clk *chipid_clk;
408 unsigned int pro_id, pkg_id;
410 chipid_clk = clk_get(NULL, "chipid");
411 if (chipid_clk == NULL)
413 printk(KERN_ERR "failed to find chipid clock source\n");
416 clk_enable(chipid_clk);
418 pro_id = __raw_readl(S5P_VA_CHIPID);
419 printk(KERN_INFO "pro_id: 0x%08x\n", pro_id);
421 if ((pro_id & 0xf) == 0x1) {
422 pkg_id = __raw_readl(S5P_VA_CHIPID + 0x4);
423 printk(KERN_INFO "pkg_id: 0x%08x\n", pkg_id);
425 switch (pkg_id & 0x7) {
443 clk_disable(chipid_clk);
450 int s5pv310_subrev(void)
452 static int subrev = -1;
454 if (unlikely(subrev < 0)) {
455 struct clk *clk = clk_get(NULL, "chipid");
457 if (IS_ERR_OR_NULL(clk))
462 subrev = readl(S5P_VA_CHIPID) & 0xf;
473 int __init s5pv310_init(void)
475 /* set idle function */
476 pm_idle = s5pv310_idle;
478 /* set power_off function */
479 // pm_power_off = s5pv310_power_off; /* We don't use s5pv310_power_off (use each board's power off function) */
481 /* set sw_reset function */
482 s5p_reset_hook = s5pv310_sw_reset; /* Change reset function from sw_reset to watchdog reset */
484 s5pv310_sc_feedback();
486 return sysdev_register(&s5pv310_sysdev);