diff options
Diffstat (limited to 'arch/arm/mach-exynos/common.c')
-rw-r--r-- | arch/arm/mach-exynos/common.c | 550 |
1 files changed, 31 insertions, 519 deletions
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 745e304ad0d..2c655db4b78 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -10,12 +10,14 @@ */ #include <linux/kernel.h> +#include <linux/bitops.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqchip.h> #include <linux/io.h> #include <linux/device.h> #include <linux/gpio.h> +#include <clocksource/samsung_pwm.h> #include <linux/sched.h> #include <linux/serial_core.h> #include <linux/of.h> @@ -38,20 +40,9 @@ #include <mach/regs-irq.h> #include <mach/regs-pmu.h> -#include <mach/regs-gpio.h> -#include <mach/irqs.h> #include <plat/cpu.h> -#include <plat/devs.h> #include <plat/pm.h> -#include <plat/sdhci.h> -#include <plat/gpio-cfg.h> -#include <plat/adc-core.h> -#include <plat/fb-core.h> -#include <plat/fimc-core.h> -#include <plat/iic-core.h> -#include <plat/tv-core.h> -#include <plat/spi-core.h> #include <plat/regs-serial.h> #include "common.h" @@ -62,36 +53,31 @@ static const char name_exynos4210[] = "EXYNOS4210"; static const char name_exynos4212[] = "EXYNOS4212"; static const char name_exynos4412[] = "EXYNOS4412"; static const char name_exynos5250[] = "EXYNOS5250"; +static const char name_exynos5420[] = "EXYNOS5420"; static const char name_exynos5440[] = "EXYNOS5440"; static void exynos4_map_io(void); static void exynos5_map_io(void); static void exynos5440_map_io(void); -static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no); static int exynos_init(void); -unsigned long xxti_f = 0, xusbxti_f = 0; - static struct cpu_table cpu_ids[] __initdata = { { .idcode = EXYNOS4210_CPU_ID, .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, - .init_uarts = exynos4_init_uarts, .init = exynos_init, .name = name_exynos4210, }, { .idcode = EXYNOS4212_CPU_ID, .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, - .init_uarts = exynos4_init_uarts, .init = exynos_init, .name = name_exynos4212, }, { .idcode = EXYNOS4412_CPU_ID, .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, - .init_uarts = exynos4_init_uarts, .init = exynos_init, .name = name_exynos4412, }, { @@ -101,6 +87,12 @@ static struct cpu_table cpu_ids[] __initdata = { .init = exynos_init, .name = name_exynos5250, }, { + .idcode = EXYNOS5420_SOC_ID, + .idmask = EXYNOS5_SOC_MASK, + .map_io = exynos5_map_io, + .init = exynos_init, + .name = name_exynos5420, + }, { .idcode = EXYNOS5440_SOC_ID, .idmask = EXYNOS5_SOC_MASK, .map_io = exynos5440_map_io, @@ -111,15 +103,6 @@ static struct cpu_table cpu_ids[] __initdata = { /* Initial IO mappings */ -static struct map_desc exynos_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_CHIPID, - .pfn = __phys_to_pfn(EXYNOS_PA_CHIPID), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - static struct map_desc exynos4_iodesc[] __initdata = { { .virtual = (unsigned long)S3C_VA_SYS, @@ -313,16 +296,20 @@ void exynos5_restart(char mode, const char *cmd) u32 val; void __iomem *addr; - if (of_machine_is_compatible("samsung,exynos5250")) { - val = 0x1; - addr = EXYNOS_SWRESET; - } else if (of_machine_is_compatible("samsung,exynos5440")) { + val = 0x1; + addr = EXYNOS_SWRESET; + + if (of_machine_is_compatible("samsung,exynos5440")) { + u32 status; np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock"); + + addr = of_iomap(np, 0) + 0xbc; + status = __raw_readl(addr); + addr = of_iomap(np, 0) + 0xcc; - val = (0xfff << 20) | (0x1 << 16); - } else { - pr_err("%s: cannot support non-DT\n", __func__); - return; + val = __raw_readl(addr); + + val = (val & 0xffff0000) | (status & 0xffff); } __raw_writel(val, addr); @@ -337,8 +324,7 @@ void __init exynos_init_late(void) exynos_pm_late_initcall(); } -#ifdef CONFIG_OF -int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, +static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, int depth, void *data) { struct map_desc iodesc; @@ -360,7 +346,6 @@ int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, iotable_init(&iodesc, 1); return 1; } -#endif /* * exynos_map_io @@ -368,17 +353,11 @@ int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, * register the standard cpu IO areas */ -void __init exynos_init_io(struct map_desc *mach_desc, int size) +void __init exynos_init_io(void) { -#ifdef CONFIG_OF - if (initial_boot_params) - of_scan_flat_dt(exynos_fdt_map_chipid, NULL); - else -#endif - iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc)); + debug_ll_io_init(); - if (mach_desc) - iotable_init(mach_desc, size); + of_scan_flat_dt(exynos_fdt_map_chipid, NULL); /* detect cpu id and rev. */ s5p_init_cpu(S5P_VA_CHIPID); @@ -399,34 +378,6 @@ static void __init exynos4_map_io(void) iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc)); if (soc_is_exynos4212() || soc_is_exynos4412()) iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc)); - - /* initialize device information early */ - exynos4_default_sdhci0(); - exynos4_default_sdhci1(); - exynos4_default_sdhci2(); - exynos4_default_sdhci3(); - - s3c_adc_setname("samsung-adc-v3"); - - s3c_fimc_setname(0, "exynos4-fimc"); - s3c_fimc_setname(1, "exynos4-fimc"); - s3c_fimc_setname(2, "exynos4-fimc"); - s3c_fimc_setname(3, "exynos4-fimc"); - - s3c_sdhci_setname(0, "exynos4-sdhci"); - s3c_sdhci_setname(1, "exynos4-sdhci"); - s3c_sdhci_setname(2, "exynos4-sdhci"); - s3c_sdhci_setname(3, "exynos4-sdhci"); - - /* The I2C bus controllers are directly compatible with s3c2440 */ - s3c_i2c0_setname("s3c2440-i2c"); - s3c_i2c1_setname("s3c2440-i2c"); - s3c_i2c2_setname("s3c2440-i2c"); - - s5p_fb_setname(0, "exynos4-fb"); - s5p_hdmi_setname("exynos4-hdmi"); - - s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos5_map_io(void) @@ -444,60 +395,8 @@ static void __init exynos5440_map_io(void) void __init exynos_init_time(void) { - if (of_have_populated_dt()) { -#ifdef CONFIG_OF - of_clk_init(NULL); - clocksource_of_init(); -#endif - } else { - /* todo: remove after migrating legacy E4 platforms to dt */ -#ifdef CONFIG_ARCH_EXYNOS4 - exynos4_clk_init(NULL, !soc_is_exynos4210(), S5P_VA_CMU, readl(S5P_VA_CHIPID + 8) & 1); - exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f); -#endif - mct_init(S5P_VA_SYSTIMER, EXYNOS4_IRQ_MCT_G0, EXYNOS4_IRQ_MCT_L0, EXYNOS4_IRQ_MCT_L1); - } -} - -static unsigned int max_combiner_nr(void) -{ - if (soc_is_exynos5250()) - return EXYNOS5_MAX_COMBINER_NR; - else if (soc_is_exynos4412()) - return EXYNOS4412_MAX_COMBINER_NR; - else if (soc_is_exynos4212()) - return EXYNOS4212_MAX_COMBINER_NR; - else - return EXYNOS4210_MAX_COMBINER_NR; -} - - -void __init exynos4_init_irq(void) -{ - unsigned int gic_bank_offset; - - gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; - - if (!of_have_populated_dt()) - gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL); -#ifdef CONFIG_OF - else - irqchip_init(); -#endif - - if (!of_have_populated_dt()) - combiner_init(S5P_VA_COMBINER_BASE, NULL, - max_combiner_nr(), COMBINER_IRQ(0, 0)); - - gic_arch_extn.irq_set_wake = s3c_irq_wake; -} - -void __init exynos5_init_irq(void) -{ -#ifdef CONFIG_OF - irqchip_init(); -#endif - gic_arch_extn.irq_set_wake = s3c_irq_wake; + of_clk_init(NULL); + clocksource_of_init(); } struct bus_type exynos_subsys = { @@ -515,59 +414,19 @@ static int __init exynos_core_init(void) } core_initcall(exynos_core_init); -#ifdef CONFIG_CACHE_L2X0 static int __init exynos4_l2x0_cache_init(void) { int ret; - if (soc_is_exynos5250() || soc_is_exynos5440()) - return 0; - ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); - if (!ret) { - l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); - clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long)); - return 0; - } - - if (!(__raw_readl(S5P_VA_L2CC + L2X0_CTRL) & 0x1)) { - l2x0_saved_regs.phy_base = EXYNOS4_PA_L2CC; - /* TAG, Data Latency Control: 2 cycles */ - l2x0_saved_regs.tag_latency = 0x110; - - if (soc_is_exynos4212() || soc_is_exynos4412()) - l2x0_saved_regs.data_latency = 0x120; - else - l2x0_saved_regs.data_latency = 0x110; - - l2x0_saved_regs.prefetch_ctrl = 0x30000007; - l2x0_saved_regs.pwr_ctrl = - (L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN); + if (ret) + return ret; - l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); - - __raw_writel(l2x0_saved_regs.tag_latency, - S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL); - __raw_writel(l2x0_saved_regs.data_latency, - S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL); - - /* L2X0 Prefetch Control */ - __raw_writel(l2x0_saved_regs.prefetch_ctrl, - S5P_VA_L2CC + L2X0_PREFETCH_CTRL); - - /* L2X0 Power Control */ - __raw_writel(l2x0_saved_regs.pwr_ctrl, - S5P_VA_L2CC + L2X0_POWER_CTRL); - - clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long)); - clean_dcache_area(&l2x0_saved_regs, sizeof(struct l2x0_regs)); - } - - l2x0_init(S5P_VA_L2CC, L2_AUX_VAL, L2_AUX_MASK); + l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); + clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long)); return 0; } early_initcall(exynos4_l2x0_cache_init); -#endif static int __init exynos_init(void) { @@ -575,350 +434,3 @@ static int __init exynos_init(void) return device_register(&exynos4_dev); } - -/* uart registration process */ - -static void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - struct s3c2410_uartcfg *tcfg = cfg; - u32 ucnt; - - for (ucnt = 0; ucnt < no; ucnt++, tcfg++) - tcfg->has_fracval = 1; - - s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no); -} - -static void __iomem *exynos_eint_base; - -static DEFINE_SPINLOCK(eint_lock); - -static unsigned int eint0_15_data[16]; - -static inline int exynos4_irq_to_gpio(unsigned int irq) -{ - if (irq < IRQ_EINT(0)) - return -EINVAL; - - irq -= IRQ_EINT(0); - if (irq < 8) - return EXYNOS4_GPX0(irq); - - irq -= 8; - if (irq < 8) - return EXYNOS4_GPX1(irq); - - irq -= 8; - if (irq < 8) - return EXYNOS4_GPX2(irq); - - irq -= 8; - if (irq < 8) - return EXYNOS4_GPX3(irq); - - return -EINVAL; -} - -static inline int exynos5_irq_to_gpio(unsigned int irq) -{ - if (irq < IRQ_EINT(0)) - return -EINVAL; - - irq -= IRQ_EINT(0); - if (irq < 8) - return EXYNOS5_GPX0(irq); - - irq -= 8; - if (irq < 8) - return EXYNOS5_GPX1(irq); - - irq -= 8; - if (irq < 8) - return EXYNOS5_GPX2(irq); - - irq -= 8; - if (irq < 8) - return EXYNOS5_GPX3(irq); - - return -EINVAL; -} - -static unsigned int exynos4_eint0_15_src_int[16] = { - EXYNOS4_IRQ_EINT0, - EXYNOS4_IRQ_EINT1, - EXYNOS4_IRQ_EINT2, - EXYNOS4_IRQ_EINT3, - EXYNOS4_IRQ_EINT4, - EXYNOS4_IRQ_EINT5, - EXYNOS4_IRQ_EINT6, - EXYNOS4_IRQ_EINT7, - EXYNOS4_IRQ_EINT8, - EXYNOS4_IRQ_EINT9, - EXYNOS4_IRQ_EINT10, - EXYNOS4_IRQ_EINT11, - EXYNOS4_IRQ_EINT12, - EXYNOS4_IRQ_EINT13, - EXYNOS4_IRQ_EINT14, - EXYNOS4_IRQ_EINT15, -}; - -static unsigned int exynos5_eint0_15_src_int[16] = { - EXYNOS5_IRQ_EINT0, - EXYNOS5_IRQ_EINT1, - EXYNOS5_IRQ_EINT2, - EXYNOS5_IRQ_EINT3, - EXYNOS5_IRQ_EINT4, - EXYNOS5_IRQ_EINT5, - EXYNOS5_IRQ_EINT6, - EXYNOS5_IRQ_EINT7, - EXYNOS5_IRQ_EINT8, - EXYNOS5_IRQ_EINT9, - EXYNOS5_IRQ_EINT10, - EXYNOS5_IRQ_EINT11, - EXYNOS5_IRQ_EINT12, - EXYNOS5_IRQ_EINT13, - EXYNOS5_IRQ_EINT14, - EXYNOS5_IRQ_EINT15, -}; -static inline void exynos_irq_eint_mask(struct irq_data *data) -{ - u32 mask; - - spin_lock(&eint_lock); - mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq)); - mask |= EINT_OFFSET_BIT(data->irq); - __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq)); - spin_unlock(&eint_lock); -} - -static void exynos_irq_eint_unmask(struct irq_data *data) -{ - u32 mask; - - spin_lock(&eint_lock); - mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq)); - mask &= ~(EINT_OFFSET_BIT(data->irq)); - __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq)); - spin_unlock(&eint_lock); -} - -static inline void exynos_irq_eint_ack(struct irq_data *data) -{ - __raw_writel(EINT_OFFSET_BIT(data->irq), - EINT_PEND(exynos_eint_base, data->irq)); -} - -static void exynos_irq_eint_maskack(struct irq_data *data) -{ - exynos_irq_eint_mask(data); - exynos_irq_eint_ack(data); -} - -static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type) -{ - int offs = EINT_OFFSET(data->irq); - int shift; - u32 ctrl, mask; - u32 newvalue = 0; - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - newvalue = S5P_IRQ_TYPE_EDGE_RISING; - break; - - case IRQ_TYPE_EDGE_FALLING: - newvalue = S5P_IRQ_TYPE_EDGE_FALLING; - break; - - case IRQ_TYPE_EDGE_BOTH: - newvalue = S5P_IRQ_TYPE_EDGE_BOTH; - break; - - case IRQ_TYPE_LEVEL_LOW: - newvalue = S5P_IRQ_TYPE_LEVEL_LOW; - break; - - case IRQ_TYPE_LEVEL_HIGH: - newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; - break; - - default: - printk(KERN_ERR "No such irq type %d", type); - return -EINVAL; - } - - shift = (offs & 0x7) * 4; - mask = 0x7 << shift; - - spin_lock(&eint_lock); - ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq)); - ctrl &= ~mask; - ctrl |= newvalue << shift; - __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq)); - spin_unlock(&eint_lock); - - if (soc_is_exynos5250()) - s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf)); - else - s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf)); - - return 0; -} - -static struct irq_chip exynos_irq_eint = { - .name = "exynos-eint", - .irq_mask = exynos_irq_eint_mask, - .irq_unmask = exynos_irq_eint_unmask, - .irq_mask_ack = exynos_irq_eint_maskack, - .irq_ack = exynos_irq_eint_ack, - .irq_set_type = exynos_irq_eint_set_type, -#ifdef CONFIG_PM - .irq_set_wake = s3c_irqext_wake, -#endif -}; - -/* - * exynos4_irq_demux_eint - * - * This function demuxes the IRQ from from EINTs 16 to 31. - * It is designed to be inlined into the specific handler - * s5p_irq_demux_eintX_Y. - * - * Each EINT pend/mask registers handle eight of them. - */ -static inline void exynos_irq_demux_eint(unsigned int start) -{ - unsigned int irq; - - u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start)); - u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start)); - - status &= ~mask; - status &= 0xff; - - while (status) { - irq = fls(status) - 1; - generic_handle_irq(irq + start); - status &= ~(1 << irq); - } -} - -static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) -{ - struct irq_chip *chip = irq_get_chip(irq); - chained_irq_enter(chip, desc); - exynos_irq_demux_eint(IRQ_EINT(16)); - exynos_irq_demux_eint(IRQ_EINT(24)); - chained_irq_exit(chip, desc); -} - -static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) -{ - u32 *irq_data = irq_get_handler_data(irq); - struct irq_chip *chip = irq_get_chip(irq); - - chained_irq_enter(chip, desc); - generic_handle_irq(*irq_data); - chained_irq_exit(chip, desc); -} - -static int __init exynos_init_irq_eint(void) -{ - int irq; - -#ifdef CONFIG_PINCTRL_SAMSUNG - /* - * The Samsung pinctrl driver provides an integrated gpio/pinmux/pinconf - * functionality along with support for external gpio and wakeup - * interrupts. If the samsung pinctrl driver is enabled and includes - * the wakeup interrupt support, then the setting up external wakeup - * interrupts here can be skipped. This check here is temporary to - * allow exynos4 platforms that do not use Samsung pinctrl driver to - * co-exist with platforms that do. When all of the Samsung Exynos4 - * platforms switch over to using the pinctrl driver, the wakeup - * interrupt support code here can be completely removed. - */ - static const struct of_device_id exynos_pinctrl_ids[] = { - { .compatible = "samsung,exynos4210-pinctrl", }, - { .compatible = "samsung,exynos4x12-pinctrl", }, - { .compatible = "samsung,exynos5250-pinctrl", }, - }; - struct device_node *pctrl_np, *wkup_np; - const char *wkup_compat = "samsung,exynos4210-wakeup-eint"; - - for_each_matching_node(pctrl_np, exynos_pinctrl_ids) { - if (of_device_is_available(pctrl_np)) { - wkup_np = of_find_compatible_node(pctrl_np, NULL, - wkup_compat); - if (wkup_np) - return -ENODEV; - } - } -#endif - if (soc_is_exynos5440()) - return 0; - - if (soc_is_exynos5250()) - exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K); - else - exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K); - - if (exynos_eint_base == NULL) { - pr_err("unable to ioremap for EINT base address\n"); - return -ENOMEM; - } - - for (irq = 0 ; irq <= 31 ; irq++) { - irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint, - handle_level_irq); - set_irq_flags(IRQ_EINT(irq), IRQF_VALID); - } - - irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31); - - for (irq = 0 ; irq <= 15 ; irq++) { - eint0_15_data[irq] = IRQ_EINT(irq); - - if (soc_is_exynos5250()) { - irq_set_handler_data(exynos5_eint0_15_src_int[irq], - &eint0_15_data[irq]); - irq_set_chained_handler(exynos5_eint0_15_src_int[irq], - exynos_irq_eint0_15); - } else { - irq_set_handler_data(exynos4_eint0_15_src_int[irq], - &eint0_15_data[irq]); - irq_set_chained_handler(exynos4_eint0_15_src_int[irq], - exynos_irq_eint0_15); - } - } - - return 0; -} -arch_initcall(exynos_init_irq_eint); - -static struct resource exynos4_pmu_resource[] = { - DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU), - DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU1), -#if defined(CONFIG_SOC_EXYNOS4412) - DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU2), - DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU3), -#endif -}; - -static struct platform_device exynos4_device_pmu = { - .name = "arm-pmu", - .num_resources = ARRAY_SIZE(exynos4_pmu_resource), - .resource = exynos4_pmu_resource, -}; - -static int __init exynos_armpmu_init(void) -{ - if (!of_have_populated_dt()) { - if (soc_is_exynos4210() || soc_is_exynos4212()) - exynos4_device_pmu.num_resources = 2; - platform_device_register(&exynos4_device_pmu); - } - - return 0; -} -arch_initcall(exynos_armpmu_init); |