diff options
Diffstat (limited to 'arch/arm/mach-exynos')
-rw-r--r-- | arch/arm/mach-exynos/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/mach-exynos/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.c | 79 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/irqs.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/map.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/regs-pmu.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mach-exynos4-dt.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mach-exynos5-dt.c | 34 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mct.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-exynos/platsmp.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-exynos/setup-i2c0.c | 2 |
11 files changed, 155 insertions, 26 deletions
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 69d10373a410..070c7b6d3d86 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -67,6 +67,15 @@ config SOC_EXYNOS5250 help Enable EXYNOS5250 SoC support +config SOC_EXYNOS5440 + bool "SAMSUNG EXYNOS5440" + default y + depends on ARCH_EXYNOS5 + select ARM_ARCH_TIMER + select AUTO_ZRELADDR + help + Enable EXYNOS5440 SoC support + config EXYNOS4_MCT bool default y @@ -412,9 +421,9 @@ config MACH_EXYNOS4_DT config MACH_EXYNOS5_DT bool "SAMSUNG EXYNOS5 Machine using device tree" + default y depends on ARCH_EXYNOS5 select ARM_AMBA - select SOC_EXYNOS5250 select USE_OF help Machine support for Samsung EXYNOS5 machine with device tree enabled. diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 0c74bdc6b698..66135eedf491 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -14,9 +14,9 @@ obj- := obj-$(CONFIG_ARCH_EXYNOS) += common.o obj-$(CONFIG_ARCH_EXYNOS4) += clock-exynos4.o -obj-$(CONFIG_ARCH_EXYNOS5) += clock-exynos5.o obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o +obj-$(CONFIG_SOC_EXYNOS5250) += clock-exynos5.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 0dbee7fef9bd..e05f6cca2c9b 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -18,6 +18,7 @@ #include <linux/sched.h> #include <linux/serial_core.h> #include <linux/of.h> +#include <linux/of_fdt.h> #include <linux/of_irq.h> #include <linux/export.h> #include <linux/irqdomain.h> @@ -58,9 +59,11 @@ 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_exynos5440[] = "EXYNOS5440"; static void exynos4_map_io(void); static void exynos5_map_io(void); +static void exynos5440_map_io(void); static void exynos4_init_clocks(int xtal); static void exynos5_init_clocks(int xtal); static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no); @@ -98,6 +101,12 @@ static struct cpu_table cpu_ids[] __initdata = { .init_clocks = exynos5_init_clocks, .init = exynos_init, .name = name_exynos5250, + }, { + .idcode = EXYNOS5440_SOC_ID, + .idmask = EXYNOS5_SOC_MASK, + .map_io = exynos5440_map_io, + .init = exynos_init, + .name = name_exynos5440, }, }; @@ -112,6 +121,17 @@ static struct map_desc exynos_iodesc[] __initdata = { }, }; +#ifdef CONFIG_ARCH_EXYNOS5 +static struct map_desc exynos5440_iodesc[] __initdata = { + { + .virtual = (unsigned long)S5P_VA_CHIPID, + .pfn = __phys_to_pfn(EXYNOS5440_PA_CHIPID), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; +#endif + static struct map_desc exynos4_iodesc[] __initdata = { { .virtual = (unsigned long)S3C_VA_SYS, @@ -263,6 +283,15 @@ static struct map_desc exynos5_iodesc[] __initdata = { }, }; +static struct map_desc exynos5440_iodesc0[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(EXYNOS5440_PA_UART0), + .length = SZ_512K, + .type = MT_DEVICE, + }, +}; + void exynos4_restart(char mode, const char *cmd) { __raw_writel(0x1, S5P_SWRESET); @@ -270,11 +299,29 @@ void exynos4_restart(char mode, const char *cmd) void exynos5_restart(char mode, const char *cmd) { - __raw_writel(0x1, EXYNOS_SWRESET); + 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 = (0x10 << 20) | (0x1 << 16); + addr = EXYNOS5440_SWRESET; + } else { + pr_err("%s: cannot support non-DT\n", __func__); + return; + } + + __raw_writel(val, addr); } void __init exynos_init_late(void) { + if (of_machine_is_compatible("samsung,exynos5440")) + /* to be supported later */ + return; + exynos_pm_late_initcall(); } @@ -286,8 +333,20 @@ void __init exynos_init_late(void) void __init exynos_init_io(struct map_desc *mach_desc, int size) { + struct map_desc *iodesc = exynos_iodesc; + int iodesc_sz = ARRAY_SIZE(exynos_iodesc); +#if defined(CONFIG_OF) && defined(CONFIG_ARCH_EXYNOS5) + unsigned long root = of_get_flat_dt_root(); + /* initialize the io descriptors we need for initialization */ - iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc)); + if (of_flat_dt_is_compatible(root, "samsung,exynos5440")) { + iodesc = exynos5440_iodesc; + iodesc_sz = ARRAY_SIZE(exynos5440_iodesc); + } +#endif + + iotable_init(iodesc, iodesc_sz); + if (mach_desc) iotable_init(mach_desc, size); @@ -356,6 +415,11 @@ static void __init exynos4_init_clocks(int xtal) exynos4_setup_clocks(); } +static void __init exynos5440_map_io(void) +{ + iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0)); +} + static void __init exynos5_init_clocks(int xtal) { printk(KERN_DEBUG "%s: initializing clocks\n", __func__); @@ -572,8 +636,9 @@ static int __init combiner_of_init(struct device_node *np, return 0; } -static const struct of_device_id exynos4_dt_irq_match[] = { +static const struct of_device_id exynos_dt_irq_match[] = { { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, + { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, { .compatible = "samsung,exynos4210-combiner", .data = combiner_of_init, }, {}, @@ -590,7 +655,7 @@ void __init exynos4_init_irq(void) gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL); #ifdef CONFIG_OF else - of_irq_init(exynos4_dt_irq_match); + of_irq_init(exynos_dt_irq_match); #endif if (!of_have_populated_dt()) @@ -607,7 +672,7 @@ void __init exynos4_init_irq(void) void __init exynos5_init_irq(void) { #ifdef CONFIG_OF - of_irq_init(exynos4_dt_irq_match); + of_irq_init(exynos_dt_irq_match); #endif /* * The parameters of s5p_init_irq() are for VIC init. @@ -637,7 +702,7 @@ static int __init exynos4_l2x0_cache_init(void) { int ret; - if (soc_is_exynos5250()) + if (soc_is_exynos5250() || soc_is_exynos5440()) return 0; ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); @@ -968,6 +1033,8 @@ static int __init exynos_init_irq_eint(void) } } #endif + if (soc_is_exynos5440()) + return 0; if (soc_is_exynos5250()) exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K); diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 6da31152de3a..e0f0ae3e0cf9 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -328,6 +328,11 @@ #define EXYNOS5_IRQ_FIMC_LITE1 IRQ_SPI(126) #define EXYNOS5_IRQ_RP_TIMER IRQ_SPI(127) +/* EXYNOS5440 */ + +#define EXYNOS5440_IRQ_UART0 IRQ_SPI(2) +#define EXYNOS5440_IRQ_UART1 IRQ_SPI(3) + #define EXYNOS5_IRQ_PMU COMBINER_IRQ(1, 2) #define EXYNOS5_IRQ_SYSMMU_GSC0_0 COMBINER_IRQ(2, 0) diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 872840b2ff45..61b74e12d12b 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -53,6 +53,7 @@ #define EXYNOS4_PA_ONENAND_DMA 0x0C600000 #define EXYNOS_PA_CHIPID 0x10000000 +#define EXYNOS5440_PA_CHIPID 0x00160000 #define EXYNOS4_PA_SYSCON 0x10010000 #define EXYNOS5_PA_SYSCON 0x10050100 @@ -281,6 +282,10 @@ #define EXYNOS5_PA_UART2 0x12C20000 #define EXYNOS5_PA_UART3 0x12C30000 +#define EXYNOS5440_PA_UART0 0x000B0000 +#define EXYNOS5440_PA_UART1 0x000C0000 +#define EXYNOS5440_SZ_UART SZ_256 + #define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h index 70b2795f5283..84428e72cf5e 100644 --- a/arch/arm/mach-exynos/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h @@ -31,6 +31,7 @@ #define S5P_SWRESET S5P_PMUREG(0x0400) #define EXYNOS_SWRESET S5P_PMUREG(0x0400) +#define EXYNOS5440_SWRESET S5P_PMUREG(0x00C4) #define S5P_WAKEUP_STAT S5P_PMUREG(0x0600) #define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index eadf4b59e7d2..6df99c06419d 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -77,6 +77,7 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = { "exynos4210-spi.2", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL), {}, }; diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index db1cd8eacf28..f1326be80b91 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -10,6 +10,7 @@ */ #include <linux/of_platform.h> +#include <linux/of_fdt.h> #include <linux/serial_core.h> #include <asm/mach/arch.h> @@ -75,20 +76,35 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { {}, }; -static void __init exynos5250_dt_map_io(void) +static const struct of_dev_auxdata exynos5440_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5440_PA_UART0, + "exynos4210-uart.0", NULL), + {}, +}; + +static void __init exynos5_dt_map_io(void) { + unsigned long root = of_get_flat_dt_root(); + exynos_init_io(NULL, 0); - s3c24xx_init_clocks(24000000); + + if (of_flat_dt_is_compatible(root, "samsung,exynos5250")) + s3c24xx_init_clocks(24000000); } -static void __init exynos5250_dt_machine_init(void) +static void __init exynos5_dt_machine_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, - exynos5250_auxdata_lookup, NULL); + if (of_machine_is_compatible("samsung,exynos5250")) + of_platform_populate(NULL, of_default_bus_match_table, + exynos5250_auxdata_lookup, NULL); + else if (of_machine_is_compatible("samsung,exynos5440")) + of_platform_populate(NULL, of_default_bus_match_table, + exynos5440_auxdata_lookup, NULL); } -static char const *exynos5250_dt_compat[] __initdata = { +static char const *exynos5_dt_compat[] __initdata = { "samsung,exynos5250", + "samsung,exynos5440", NULL }; @@ -96,11 +112,11 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .init_irq = exynos5_init_irq, .smp = smp_ops(exynos_smp_ops), - .map_io = exynos5250_dt_map_io, + .map_io = exynos5_dt_map_io, .handle_irq = gic_handle_irq, - .init_machine = exynos5250_dt_machine_init, + .init_machine = exynos5_dt_machine_init, .init_late = exynos_init_late, .timer = &exynos4_timer, - .dt_compat = exynos5250_dt_compat, + .dt_compat = exynos5_dt_compat, .restart = exynos5_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index b601fb8a408b..57668eb68e75 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -19,7 +19,9 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/percpu.h> +#include <linux/of.h> +#include <asm/arch_timer.h> #include <asm/hardware/gic.h> #include <asm/localtimer.h> @@ -476,8 +478,13 @@ static void __init exynos4_timer_resources(void) #endif /* CONFIG_LOCAL_TIMERS */ } -static void __init exynos4_timer_init(void) +static void __init exynos_timer_init(void) { + if (soc_is_exynos5440()) { + arch_timer_of_register(); + return; + } + if ((soc_is_exynos4210()) || (soc_is_exynos5250())) mct_int_type = MCT_INT_SPI; else @@ -489,5 +496,5 @@ static void __init exynos4_timer_init(void) } struct sys_timer exynos4_timer = { - .init = exynos4_timer_init, + .init = exynos_timer_init, }; diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index f93d820ecab5..4ca8ff14a5bf 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -36,8 +36,22 @@ extern void exynos4_secondary_startup(void); -#define CPU1_BOOT_REG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ - S5P_INFORM5 : S5P_VA_SYSRAM) +static inline void __iomem *cpu_boot_reg_base(void) +{ + if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) + return S5P_INFORM5; + return S5P_VA_SYSRAM; +} + +static inline void __iomem *cpu_boot_reg(int cpu) +{ + void __iomem *boot_reg; + + boot_reg = cpu_boot_reg_base(); + if (soc_is_exynos4412()) + boot_reg += 4*cpu; + return boot_reg; +} /* * Write pen_release in a way that is guaranteed to be visible to all @@ -84,6 +98,7 @@ static void __cpuinit exynos_secondary_init(unsigned int cpu) static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; + unsigned long phys_cpu = cpu_logical_map(cpu); /* * Set synchronisation state between this boot processor @@ -99,7 +114,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct * Note that "pen_release" is the hardware CPU ID, whereas * "cpu" is Linux's internal ID. */ - write_pen_release(cpu_logical_map(cpu)); + write_pen_release(phys_cpu); if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { __raw_writel(S5P_CORE_LOCAL_PWR_EN, @@ -133,7 +148,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct smp_rmb(); __raw_writel(virt_to_phys(exynos4_secondary_startup), - CPU1_BOOT_REG); + cpu_boot_reg(phys_cpu)); gic_raise_softirq(cpumask_of(cpu), 0); if (pen_release == -1) @@ -181,6 +196,8 @@ static void __init exynos_smp_init_cpus(void) static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) { + int i; + if (!soc_is_exynos5250()) scu_enable(scu_base_addr()); @@ -190,8 +207,9 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) * until it receives a soft interrupt, and then the * secondary CPU branches to this address. */ - __raw_writel(virt_to_phys(exynos4_secondary_startup), - CPU1_BOOT_REG); + for (i = 1; i < max_cpus; ++i) + __raw_writel(virt_to_phys(exynos4_secondary_startup), + cpu_boot_reg(cpu_logical_map(i))); } struct smp_operations exynos_smp_ops __initdata = { diff --git a/arch/arm/mach-exynos/setup-i2c0.c b/arch/arm/mach-exynos/setup-i2c0.c index 5700f23629f7..e2d9dfbf102c 100644 --- a/arch/arm/mach-exynos/setup-i2c0.c +++ b/arch/arm/mach-exynos/setup-i2c0.c @@ -20,7 +20,7 @@ struct platform_device; /* don't need the contents */ void s3c_i2c0_cfg_gpio(struct platform_device *dev) { - if (soc_is_exynos5250()) + if (soc_is_exynos5250() || soc_is_exynos5440()) /* will be implemented with gpio function */ return; |