From 699efdd2d34c535f415516e06d3d9f0bed131664 Mon Sep 17 00:00:00 2001 From: JeongHyeon Kim Date: Thu, 21 Jul 2011 16:19:19 +0900 Subject: ARM: EXYNOS4: Add support for ORIGEN board Insignal's ORIGEN board is based Samsung EXYNOS4210 SoC. Signed-off-by: JeongHyeon Kim Signed-off-by: Tushar Behera [kgene.kim@samsung.com: Fixed SoC name to EXYNOS4210] [kgene.kim@samsung.com: Selected MACH_ORIGEN in exynos4_defconfig] Signed-off-by: Kukjin Kim diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig index da53ff3..cd40bb5 100644 --- a/arch/arm/configs/exynos4_defconfig +++ b/arch/arm/configs/exynos4_defconfig @@ -11,6 +11,7 @@ CONFIG_MACH_SMDKV310=y CONFIG_MACH_ARMLEX4210=y CONFIG_MACH_UNIVERSAL_C210=y CONFIG_MACH_NURI=y +CONFIG_MACH_ORIGEN=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index 1435fc3..3ab0f18 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -186,6 +186,16 @@ config MACH_NURI help Machine support for Samsung Mobile NURI Board. +config MACH_ORIGEN + bool "ORIGEN" + select CPU_EXYNOS4210 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C_DEV_HSMMC2 + select EXYNOS4_SETUP_SDHCI + help + Machine support for ORIGEN based on Samsung EXYNOS4210 + endmenu comment "Configuration for HSMMC bus width" diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index 60fe5ec..4b22dc5 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o obj-$(CONFIG_MACH_ARMLEX4210) += mach-armlex4210.o obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o obj-$(CONFIG_MACH_NURI) += mach-nuri.o +obj-$(CONFIG_MACH_ORIGEN) += mach-origen.o # device support diff --git a/arch/arm/mach-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c new file mode 100644 index 0000000..ed59f86 --- /dev/null +++ b/arch/arm/mach-exynos4/mach-origen.c @@ -0,0 +1,108 @@ +/* linux/arch/arm/mach-exynos4/mach-origen.c + * + * Copyright (c) 2011 Insignal Co., Ltd. + * http://www.insignal.co.kr/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* Following are default values for UCON, ULCON and UFCON UART registers */ +#define ORIGEN_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define ORIGEN_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define ORIGEN_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG4 | \ + S5PV210_UFCON_RXTRIG4) + +static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = ORIGEN_UCON_DEFAULT, + .ulcon = ORIGEN_ULCON_DEFAULT, + .ufcon = ORIGEN_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = ORIGEN_UCON_DEFAULT, + .ulcon = ORIGEN_ULCON_DEFAULT, + .ufcon = ORIGEN_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = ORIGEN_UCON_DEFAULT, + .ulcon = ORIGEN_ULCON_DEFAULT, + .ufcon = ORIGEN_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = ORIGEN_UCON_DEFAULT, + .ulcon = ORIGEN_ULCON_DEFAULT, + .ufcon = ORIGEN_UFCON_DEFAULT, + }, +}; + +static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = EXYNOS4_GPK2(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +}; + +static struct platform_device *origen_devices[] __initdata = { + &s3c_device_hsmmc2, + &s3c_device_rtc, + &s3c_device_wdt, +}; + +static void __init origen_map_io(void) +{ + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(24000000); + s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs)); +} + +static void __init origen_machine_init(void) +{ + s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata); + platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices)); +} + +MACHINE_START(ORIGEN, "ORIGEN") + /* Maintainer: JeongHyeon Kim */ + .boot_params = S5P_PA_SDRAM + 0x100, + .init_irq = exynos4_init_irq, + .map_io = origen_map_io, + .init_machine = origen_machine_init, + .timer = &exynos4_timer, +MACHINE_END -- cgit v0.10.2 From c06af3cc6a27991187fd513765fed943684d41bf Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 20 Aug 2011 02:18:18 +0900 Subject: ARM: SAMSUNG: Add support for detecting CPU at runtime The soc_is_[name]() can be used to distinguish cpu at runtime. This patch was originally from Changhwan Youn Acked-by: Changhwan Youn Cc: Ben Dooks Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c64xx/cpu.c b/arch/arm/mach-s3c64xx/cpu.c index 374e45e..7b665f3 100644 --- a/arch/arm/mach-s3c64xx/cpu.c +++ b/arch/arm/mach-s3c64xx/cpu.c @@ -43,16 +43,16 @@ static const char name_s3c6410[] = "S3C6410"; static struct cpu_table cpu_ids[] __initdata = { { - .idcode = 0x36400000, - .idmask = 0xfffff000, + .idcode = S3C6400_CPU_ID, + .idmask = S3C64XX_CPU_MASK, .map_io = s3c6400_map_io, .init_clocks = s3c6400_init_clocks, .init_uarts = s3c6400_init_uarts, .init = s3c6400_init, .name = name_s3c6400, }, { - .idcode = 0x36410100, - .idmask = 0xffffff00, + .idcode = S3C6410_CPU_ID, + .idmask = S3C64XX_CPU_MASK, .map_io = s3c6410_map_io, .init_clocks = s3c6410_init_clocks, .init_uarts = s3c6410_init_uarts, @@ -140,22 +140,20 @@ void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) { - unsigned long idcode; - /* initialise the io descriptors we need for initialisation */ iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); iotable_init(mach_desc, size); - idcode = __raw_readl(S3C_VA_SYS + 0x118); - if (!idcode) { + samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118); + if (!samsung_cpu_id) { /* S3C6400 has the ID register in a different place, * and needs a write before it can be read. */ __raw_writel(0x0, S3C_VA_SYS + 0xA1C); - idcode = __raw_readl(S3C_VA_SYS + 0xA1C); + samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C); } - s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); + s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); } static __init int s3c64xx_sysdev_init(void) diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index c1fc6c6..ead21a4 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -215,19 +215,17 @@ static void s3c24xx_pm_restart(char mode, const char *cmd) void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) { - unsigned long idcode = 0x0; - /* initialise the io descriptors we need for initialisation */ iotable_init(mach_desc, size); iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); if (cpu_architecture() >= CPU_ARCH_ARMv5) { - idcode = s3c24xx_read_idcode_v5(); + samsung_cpu_id = s3c24xx_read_idcode_v5(); } else { - idcode = s3c24xx_read_idcode_v4(); + samsung_cpu_id = s3c24xx_read_idcode_v4(); } arm_pm_restart = s3c24xx_pm_restart; - s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); + s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); } diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c index bbc2aa7..3ef6734 100644 --- a/arch/arm/plat-s5p/cpu.c +++ b/arch/arm/plat-s5p/cpu.c @@ -36,40 +36,40 @@ static const char name_exynos4210[] = "EXYNOS4210"; static struct cpu_table cpu_ids[] __initdata = { { - .idcode = 0x56440100, - .idmask = 0xfffff000, + .idcode = S5P6440_CPU_ID, + .idmask = S5P64XX_CPU_MASK, .map_io = s5p6440_map_io, .init_clocks = s5p6440_init_clocks, .init_uarts = s5p6440_init_uarts, .init = s5p64x0_init, .name = name_s5p6440, }, { - .idcode = 0x36450000, - .idmask = 0xfffff000, + .idcode = S5P6450_CPU_ID, + .idmask = S5P64XX_CPU_MASK, .map_io = s5p6450_map_io, .init_clocks = s5p6450_init_clocks, .init_uarts = s5p6450_init_uarts, .init = s5p64x0_init, .name = name_s5p6450, }, { - .idcode = 0x43100000, - .idmask = 0xfffff000, + .idcode = S5PC100_CPU_ID, + .idmask = S5PC100_CPU_MASK, .map_io = s5pc100_map_io, .init_clocks = s5pc100_init_clocks, .init_uarts = s5pc100_init_uarts, .init = s5pc100_init, .name = name_s5pc100, }, { - .idcode = 0x43110000, - .idmask = 0xfffff000, + .idcode = S5PV210_CPU_ID, + .idmask = S5PV210_CPU_MASK, .map_io = s5pv210_map_io, .init_clocks = s5pv210_init_clocks, .init_uarts = s5pv210_init_uarts, .init = s5pv210_init, .name = name_s5pv210, }, { - .idcode = 0x43210000, - .idmask = 0xfffe0000, + .idcode = EXYNOS4210_CPU_ID, + .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, .init_clocks = exynos4_init_clocks, .init_uarts = exynos4_init_uarts, @@ -114,13 +114,11 @@ static struct map_desc s5p_iodesc[] __initdata = { void __init s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr) { - unsigned long idcode; - /* initialize the io descriptors we need for initialization */ iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc)); if (mach_desc) iotable_init(mach_desc, size); - idcode = __raw_readl(cpuid_addr); - s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); + samsung_cpu_id = __raw_readl(cpuid_addr); + s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); } diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index c0a5741..bdf43ad 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -1,9 +1,12 @@ /* linux/arch/arm/plat-samsung/include/plat/cpu.h * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks * - * Header file for S3C24XX CPU support + * Header file for Samsung CPU support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,6 +18,88 @@ #ifndef __SAMSUNG_PLAT_CPU_H #define __SAMSUNG_PLAT_CPU_H +extern unsigned long samsung_cpu_id; + +#define S3C24XX_CPU_ID 0x32400000 +#define S3C24XX_CPU_MASK 0xFFF00000 + +#define S3C6400_CPU_ID 0x36400000 +#define S3C6410_CPU_ID 0x36410000 +#define S3C64XX_CPU_ID (S3C6400_CPU_ID & S3C6410_CPU_ID) +#define S3C64XX_CPU_MASK 0x1FF40000 + +#define S5P6440_CPU_ID 0x56440000 +#define S5P6450_CPU_ID 0x36450000 +#define S5P64XX_CPU_MASK 0x1FF40000 + +#define S5PC100_CPU_ID 0x43100000 +#define S5PC100_CPU_MASK 0xFFFFF000 + +#define S5PV210_CPU_ID 0x43110000 +#define S5PV210_CPU_MASK 0xFFFFF000 + +#define EXYNOS4210_CPU_ID 0x43210000 +#define EXYNOS4_CPU_MASK 0xFFFE0000 + +#define IS_SAMSUNG_CPU(name, id, mask) \ +static inline int is_samsung_##name(void) \ +{ \ + return ((samsung_cpu_id & mask) == (id & mask)); \ +} + +IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK) +IS_SAMSUNG_CPU(s3c64xx, S3C64XX_CPU_ID, S3C64XX_CPU_MASK) +IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK) +IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK) +IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK) +IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK) +IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) + +#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ + defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \ + defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \ + defined(CONFIG_CPU_S3C2443) +# define soc_is_s3c24xx() is_samsung_s3c24xx() +#else +# define soc_is_s3c24xx() 0 +#endif + +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) +# define soc_is_s3c64xx() is_samsung_s3c64xx() +#else +# define soc_is_s3c64xx() 0 +#endif + +#if defined(CONFIG_CPU_S5P6440) +# define soc_is_s5p6440() is_samsung_s5p6440() +#else +# define soc_is_s5p6440() 0 +#endif + +#if defined(CONFIG_CPU_S5P6450) +# define soc_is_s5p6450() is_samsung_s5p6450() +#else +# define soc_is_s5p6450() 0 +#endif + +#if defined(CONFIG_CPU_S5PC100) +# define soc_is_s5pc100() is_samsung_s5pc100() +#else +# define soc_is_s5pc100() 0 +#endif + +#if defined(CONFIG_CPU_S5PV210) +# define soc_is_s5pv210() is_samsung_s5pv210() +#else +# define soc_is_s5pv210() 0 +#endif + +#if defined(CONFIG_CPU_EXYNOS4210) +# define soc_is_exynos4210() is_samsung_exynos4210() +#else +# define soc_is_exynos4210() 0 +#endif + #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef MHZ diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c index 79d10fc..40b1228 100644 --- a/arch/arm/plat-samsung/init.c +++ b/arch/arm/plat-samsung/init.c @@ -30,6 +30,7 @@ #include static struct cpu_table *cpu; +unsigned long samsung_cpu_id; static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode, struct cpu_table *tab, -- cgit v0.10.2 From a3d9358406b7529373ccafbf6d264f811884959c Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 20 Aug 2011 02:30:08 +0900 Subject: ARM: S5P64X0: Use soc_is_s5p64x0() to distinguish cpu at runtime Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c index ac825e8..1fd9c79 100644 --- a/arch/arm/mach-s5p64x0/dev-spi.c +++ b/arch/arm/mach-s5p64x0/dev-spi.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -185,11 +186,8 @@ struct platform_device s5p64x0_device_spi1 = { void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) { - unsigned int id; struct s3c64xx_spi_info *pd; - id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; - /* Reject invalid configuration */ if (!num_cs || src_clk_nr < 0 || src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) { @@ -199,7 +197,7 @@ void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) switch (cntrlr) { case 0: - if (id == 0x50000) + if (soc_is_s5p6450()) pd = &s5p6450_spi0_pdata; else pd = &s5p6440_spi0_pdata; @@ -207,7 +205,7 @@ void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) s5p64x0_device_spi0.dev.platform_data = pd; break; case 1: - if (id == 0x50000) + if (soc_is_s5p6450()) pd = &s5p6450_spi1_pdata; else pd = &s5p6440_spi1_pdata; diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c index d7ad944..0e5b3e6 100644 --- a/arch/arm/mach-s5p64x0/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -133,11 +134,7 @@ static struct platform_device s5p64x0_device_pdma = { static int __init s5p64x0_dma_init(void) { - unsigned int id; - - id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; - - if (id == 0x50000) + if (soc_is_s5p6450()) s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata; else s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata; diff --git a/arch/arm/mach-s5p64x0/gpiolib.c b/arch/arm/mach-s5p64x0/gpiolib.c index e7fb3b0..700dac6 100644 --- a/arch/arm/mach-s5p64x0/gpiolib.c +++ b/arch/arm/mach-s5p64x0/gpiolib.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -473,14 +474,10 @@ static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, static int __init s5p64x0_gpiolib_init(void) { - unsigned int chipid; - - chipid = __raw_readl(S5P64X0_SYS_ID); - s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs, ARRAY_SIZE(s5p64x0_gpio_cfgs)); - if ((chipid & 0xff000) == 0x50000) { + if (soc_is_s5p6450()) { samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit, ARRAY_SIZE(s5p6450_gpio_2bit)); diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c index 69ed454..94104c4 100644 --- a/arch/arm/mach-s5p64x0/irq-eint.c +++ b/arch/arm/mach-s5p64x0/irq-eint.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -67,7 +68,7 @@ static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type) __raw_writel(ctrl, S5P64X0_EINT0CON0); /* Configure the GPIO pin for 6450 or 6440 based on CPU ID */ - if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000)) + if (soc_is_s5p6450()) s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2)); else s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2)); -- cgit v0.10.2 From e6d1cb9f1fffd7e300af6d8f6731a486d6255e3f Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 20 Aug 2011 12:18:07 +0900 Subject: ARM: SAMSUNG: Add support for handling of cpu revision This patch adds plat-samsung/cpu.c for detecting of cpu id and silicon revision. This patch was originally from Changhwan Youn Acked-by: Changhwan Youn Cc: Ben Dooks Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c64xx/cpu.c b/arch/arm/mach-s3c64xx/cpu.c index 7b665f3..6c498f9 100644 --- a/arch/arm/mach-s3c64xx/cpu.c +++ b/arch/arm/mach-s3c64xx/cpu.c @@ -144,14 +144,8 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); iotable_init(mach_desc, size); - samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118); - if (!samsung_cpu_id) { - /* S3C6400 has the ID register in a different place, - * and needs a write before it can be read. */ - - __raw_writel(0x0, S3C_VA_SYS + 0xA1C); - samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C); - } + /* detect cpu id */ + s3c64xx_init_cpu(); s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); } diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index ead21a4..3c63353 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -224,6 +224,7 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) } else { samsung_cpu_id = s3c24xx_read_idcode_v4(); } + s3c24xx_init_cpu(); arm_pm_restart = s3c24xx_pm_restart; diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c index 3ef6734..04392c7 100644 --- a/arch/arm/plat-s5p/cpu.c +++ b/arch/arm/plat-s5p/cpu.c @@ -119,6 +119,8 @@ void __init s5p_init_io(struct map_desc *mach_desc, if (mach_desc) iotable_init(mach_desc, size); - samsung_cpu_id = __raw_readl(cpuid_addr); + /* detect cpu id and rev. */ + s5p_init_cpu(cpuid_addr); + s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); } diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 853764b..3de756d 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -11,7 +11,7 @@ obj- := # Objects we always build independent of SoC choice -obj-y += init.o +obj-y += init.o cpu.o obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o obj-y += clock.o obj-y += pwm-clock.o diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c new file mode 100644 index 0000000..81c06d4 --- /dev/null +++ b/arch/arm/plat-samsung/cpu.c @@ -0,0 +1,58 @@ +/* linux/arch/arm/plat-samsung/cpu.c + * + * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung CPU Support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include + +#include + +#include +#include + +unsigned long samsung_cpu_id; +static unsigned int samsung_cpu_rev; + +unsigned int samsung_rev(void) +{ + return samsung_cpu_rev; +} +EXPORT_SYMBOL(samsung_rev); + +void __init s3c24xx_init_cpu(void) +{ + /* nothing here yet */ + + samsung_cpu_rev = 0; +} + +void __init s3c64xx_init_cpu(void) +{ + samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118); + if (!samsung_cpu_id) { + /* + * S3C6400 has the ID register in a different place, + * and needs a write before it can be read. + */ + __raw_writel(0x0, S3C_VA_SYS + 0xA1C); + samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C); + } + + samsung_cpu_rev = 0; +} + +void __init s5p_init_cpu(void __iomem *cpuid_addr) +{ + samsung_cpu_id = __raw_readl(cpuid_addr); + samsung_cpu_rev = samsung_cpu_id & 0xFF; +} diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index bdf43ad..c22d110 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -140,6 +140,10 @@ extern void s3c64xx_init_io(struct map_desc *mach_desc, int size); extern void s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr); +extern void s3c24xx_init_cpu(void); +extern void s3c64xx_init_cpu(void); +extern void s5p_init_cpu(void __iomem *cpuid_addr); + extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void s3c24xx_init_clocks(int xtal); diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c index 40b1228..79d10fc 100644 --- a/arch/arm/plat-samsung/init.c +++ b/arch/arm/plat-samsung/init.c @@ -30,7 +30,6 @@ #include static struct cpu_table *cpu; -unsigned long samsung_cpu_id; static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode, struct cpu_table *tab, -- cgit v0.10.2 From 56b209227a87b718450e917df904e627ddfca146 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 20 Aug 2011 13:41:21 +0900 Subject: ARM: EXYNOS4: Use samsung_rev() to distinguish silicon revision This patch uses samsung_rev() to support variable silicon revision of EXYNOS4210 so that can support for EXYNOS4210 REV0, REV1.0 and REV1.1. Note: Need to change timer setting on REV0. Acked-by: Changhwan Youn Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 2d8a40c..dbc358d 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -43,11 +43,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_SYSRAM, - .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM), - .length = SZ_4K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S5P_VA_CMU, .pfn = __phys_to_pfn(EXYNOS4_PA_CMU), .length = SZ_128K, @@ -120,6 +115,24 @@ static struct map_desc exynos4_iodesc[] __initdata = { }, }; +static struct map_desc exynos4_iodesc0[] __initdata = { + { + .virtual = (unsigned long)S5P_VA_SYSRAM, + .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static struct map_desc exynos4_iodesc1[] __initdata = { + { + .virtual = (unsigned long)S5P_VA_SYSRAM, + .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + static void exynos4_idle(void) { if (!need_resched()) @@ -137,6 +150,11 @@ void __init exynos4_map_io(void) { iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); + if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0) + iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0)); + else + iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1)); + /* initialize device information early */ exynos4_default_sdhci0(); exynos4_default_sdhci1(); diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h index d32296d..7073ac7 100644 --- a/arch/arm/mach-exynos4/include/mach/map.h +++ b/arch/arm/mach-exynos4/include/mach/map.h @@ -23,7 +23,8 @@ #include -#define EXYNOS4_PA_SYSRAM 0x02020000 +#define EXYNOS4_PA_SYSRAM0 0x02025000 +#define EXYNOS4_PA_SYSRAM1 0x02020000 #define EXYNOS4_PA_FIMC0 0x11800000 #define EXYNOS4_PA_FIMC1 0x11810000 diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c index 7c2282c..96cc651 100644 --- a/arch/arm/mach-exynos4/platsmp.c +++ b/arch/arm/mach-exynos4/platsmp.c @@ -30,9 +30,12 @@ #include #include +#include + extern void exynos4_secondary_startup(void); -#define CPU1_BOOT_REG S5P_VA_SYSRAM +#define CPU1_BOOT_REG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ + S5P_INFORM5 : S5P_VA_SYSRAM) /* * control for which core is the next to come out of the secondary @@ -216,5 +219,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) * until it receives a soft interrupt, and then the * secondary CPU branches to this address. */ - __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), S5P_VA_SYSRAM); + __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), + CPU1_BOOT_REG); } diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index c22d110..6fdd5ef 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -100,6 +100,10 @@ IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) # define soc_is_exynos4210() 0 #endif +#define EXYNOS4210_REV_0 (0x0) +#define EXYNOS4210_REV_1_0 (0x10) +#define EXYNOS4210_REV_1_1 (0x11) + #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef MHZ @@ -144,6 +148,8 @@ extern void s3c24xx_init_cpu(void); extern void s3c64xx_init_cpu(void); extern void s5p_init_cpu(void __iomem *cpuid_addr); +extern unsigned int samsung_rev(void); + extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void s3c24xx_init_clocks(int xtal); -- cgit v0.10.2 From 2747f5e56564e715810038a1a2d8f4041f866558 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Sep 2011 19:11:40 +0900 Subject: ARM: SAMSUNG: Fix mask for S3C64xx CPU IDs The difference in CPU ID between S3C6400 and S3C6410 is a single bit and that bit wasn't included in the mask causing the S3C6410 to be misdetected as a S3C6400. Signed-off-by: Mark Brown [kgene.kim@samsung.com: changed the value] Signed-off-by: Kukjin Kim diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 6fdd5ef..6070c6b 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -26,7 +26,7 @@ extern unsigned long samsung_cpu_id; #define S3C6400_CPU_ID 0x36400000 #define S3C6410_CPU_ID 0x36410000 #define S3C64XX_CPU_ID (S3C6400_CPU_ID & S3C6410_CPU_ID) -#define S3C64XX_CPU_MASK 0x1FF40000 +#define S3C64XX_CPU_MASK 0xFFFFF000 #define S5P6440_CPU_ID 0x56440000 #define S5P6450_CPU_ID 0x36450000 -- cgit v0.10.2 From b02b5da4d15d7f7a250888d003121e1b5b69d00b Mon Sep 17 00:00:00 2001 From: Ajay Kumar Date: Mon, 5 Sep 2011 19:12:47 +0900 Subject: ARM: SAMSUNG: Fix mask value for S5P64X0 CPU IDs The current value for S5P64XX_CPU_MASK does not include the necessary bits, which causes detection failure. Signed-off-by: Ajay Kumar [kgene.kim@samsung.com: changed the value] Signed-off-by: Kukjin Kim diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 6070c6b..efd920e 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -30,7 +30,7 @@ extern unsigned long samsung_cpu_id; #define S5P6440_CPU_ID 0x56440000 #define S5P6450_CPU_ID 0x36450000 -#define S5P64XX_CPU_MASK 0x1FF40000 +#define S5P64XX_CPU_MASK 0xFFFFF000 #define S5PC100_CPU_ID 0x43100000 #define S5PC100_CPU_MASK 0xFFFFF000 -- cgit v0.10.2 From 684653842b65b98538e5d6198998e68c879bd45e Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 24 Aug 2011 17:25:09 +0900 Subject: ARM: EXYNOS4: Add support new EXYNOS4212 SoC This patch adds Samsung EXYNOS4212 SoC support. The EXYNOS4212 integrates a ARM Cortex A9 multi-core. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index bee8f77..0b40289 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -15,6 +15,11 @@ config CPU_EXYNOS4210 help Enable EXYNOS4210 CPU support +config SOC_EXYNOS4212 + bool + help + Enable EXYNOS4212 SoC support + config EXYNOS4_MCT bool default y diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index e3e93ea..4624457 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -12,8 +12,10 @@ obj- := # Core support for EXYNOS4 system -obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o -obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o irq-eint.o dma.o pmu.o +obj-$(CONFIG_ARCH_EXYNOS4) += cpu.o init.o clock.o irq-combiner.o +obj-$(CONFIG_ARCH_EXYNOS4) += setup-i2c0.o irq-eint.o dma.o pmu.o +obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o +obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 0d281bb..1e1a7a9 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -241,7 +241,11 @@ static int __init exynos4_l2x0_cache_init(void) { /* TAG, Data Latency Control: 2cycle */ __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL); - __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL); + + if (soc_is_exynos4210()) + __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL); + else if (soc_is_exynos4212()) + __raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL); /* L2X0 Prefetch Control */ __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL); diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c index 04392c7..909507b 100644 --- a/arch/arm/plat-s5p/cpu.c +++ b/arch/arm/plat-s5p/cpu.c @@ -33,6 +33,7 @@ static const char name_s5p6450[] = "S5P6450"; static const char name_s5pc100[] = "S5PC100"; static const char name_s5pv210[] = "S5PV210/S5PC110"; static const char name_exynos4210[] = "EXYNOS4210"; +static const char name_exynos4212[] = "EXYNOS4212"; static struct cpu_table cpu_ids[] __initdata = { { @@ -75,6 +76,14 @@ static struct cpu_table cpu_ids[] __initdata = { .init_uarts = exynos4_init_uarts, .init = exynos4_init, .name = name_exynos4210, + }, { + .idcode = EXYNOS4212_CPU_ID, + .idmask = EXYNOS4_CPU_MASK, + .map_io = exynos4_map_io, + .init_clocks = exynos4_init_clocks, + .init_uarts = exynos4_init_uarts, + .init = exynos4_init, + .name = name_exynos4212, }, }; diff --git a/arch/arm/plat-s5p/include/plat/exynos4.h b/arch/arm/plat-s5p/include/plat/exynos4.h index 907caab..4aed130 100644 --- a/arch/arm/plat-s5p/include/plat/exynos4.h +++ b/arch/arm/plat-s5p/include/plat/exynos4.h @@ -16,8 +16,7 @@ extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void exynos4_register_clocks(void); extern void exynos4_setup_clocks(void); -#ifdef CONFIG_CPU_EXYNOS4210 - +#ifdef CONFIG_ARCH_EXYNOS4 extern int exynos4_init(void); extern void exynos4_init_irq(void); extern void exynos4_map_io(void); diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index efd920e..1bbbbb4 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -39,6 +39,7 @@ extern unsigned long samsung_cpu_id; #define S5PV210_CPU_MASK 0xFFFFF000 #define EXYNOS4210_CPU_ID 0x43210000 +#define EXYNOS4212_CPU_ID 0x43220000 #define EXYNOS4_CPU_MASK 0xFFFE0000 #define IS_SAMSUNG_CPU(name, id, mask) \ @@ -54,6 +55,7 @@ IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK) IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK) IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK) IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) +IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK) #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \ @@ -100,6 +102,12 @@ IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) # define soc_is_exynos4210() 0 #endif +#if defined(CONFIG_SOC_EXYNOS4212) +# define soc_is_exynos4212() is_samsung_exynos4212() +#else +# define soc_is_exynos4212() 0 +#endif + #define EXYNOS4210_REV_0 (0x0) #define EXYNOS4210_REV_1_0 (0x10) #define EXYNOS4210_REV_1_1 (0x11) -- cgit v0.10.2 From 2bc02c0daae146283ce1b20da6864a27c848812e Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 24 Aug 2011 17:25:09 +0900 Subject: ARM: EXYNOS4: Add support clock for EXYNOS4212 This patch splits EXYNOS4 clock code to EXYNOS4 common, EXYNOS4210 and EXYNOS4212 for supporting new EXYNOS4212 SoC with one kernel image. Of course, this patch adds some clock codes for EXYNOS4212 SoC. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos4/clock-exynos4210.c b/arch/arm/mach-exynos4/clock-exynos4210.c new file mode 100644 index 0000000..fe74b91 --- /dev/null +++ b/arch/arm/mach-exynos4/clock-exynos4210.c @@ -0,0 +1,101 @@ +/* + * linux/arch/arm/mach-exynos4/clock-exynos4210.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS4210 - Clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct clksrc_clk *sysclks[] = { + /* nothing here yet */ +}; + +static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable); +} + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "sclk_sata", + .id = -1, + .enable = exynos4_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_mout_corebus, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimd", + .devname = "exynos4-fb.1", + .enable = exynos4_clksrc_mask_lcd1_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 }, + }, +}; + +static struct clk init_clocks_off[] = { + { + .name = "sataphy", + .id = -1, + .parent = &clk_aclk_133.clk, + .enable = exynos4_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "sata", + .id = -1, + .parent = &clk_aclk_133.clk, + .enable = exynos4_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 10), + }, { + .name = "fimd", + .devname = "exynos4-fb.1", + .enable = exynos4_clk_ip_lcd1_ctrl, + .ctrlbit = (1 << 0), + }, +}; + +void __init exynos4210_register_clocks(void) +{ + int ptr; + + clk_mout_mpll.reg_src.reg = S5P_CLKSRC_CPU; + clk_mout_mpll.reg_src.shift = 8; + clk_mout_mpll.reg_src.size = 1; + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + + s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); +} diff --git a/arch/arm/mach-exynos4/clock-exynos4212.c b/arch/arm/mach-exynos4/clock-exynos4212.c new file mode 100644 index 0000000..5a47a3f --- /dev/null +++ b/arch/arm/mach-exynos4/clock-exynos4212.c @@ -0,0 +1,84 @@ +/* + * linux/arch/arm/mach-exynos4/clock-exynos4212.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS4212 - Clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct clk *clk_src_mpll_user_list[] = { + [0] = &clk_fin_mpll, + [1] = &clk_mout_mpll.clk, +}; + +static struct clksrc_sources clk_src_mpll_user = { + .sources = clk_src_mpll_user_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_user_list), +}; + +static struct clksrc_clk clk_mout_mpll_user = { + .clk = { + .name = "mout_mpll_user", + }, + .sources = &clk_src_mpll_user, + .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 24, .size = 1 }, +}; + +static struct clksrc_clk *sysclks[] = { + &clk_mout_mpll_user, +}; + +static struct clksrc_clk clksrcs[] = { + /* nothing here yet */ +}; + +static struct clk init_clocks_off[] = { + /* nothing here yet */ +}; + +void __init exynos4212_register_clocks(void) +{ + int ptr; + + /* usbphy1 is removed */ + clkset_group_list[4] = NULL; + + /* mout_mpll_user is used */ + clkset_group_list[6] = &clk_mout_mpll_user.clk; + clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk; + + clk_mout_mpll.reg_src.reg = S5P_CLKSRC_DMC; + clk_mout_mpll.reg_src.shift = 12; + clk_mout_mpll.reg_src.size = 1; + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + + s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); +} diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c index 79d6cd0..eb99467 100644 --- a/arch/arm/mach-exynos4/clock.c +++ b/arch/arm/mach-exynos4/clock.c @@ -20,26 +20,28 @@ #include #include #include +#include #include #include #include +#include -static struct clk clk_sclk_hdmi27m = { +struct clk clk_sclk_hdmi27m = { .name = "sclk_hdmi27m", .rate = 27000000, }; -static struct clk clk_sclk_hdmiphy = { +struct clk clk_sclk_hdmiphy = { .name = "sclk_hdmiphy", }; -static struct clk clk_sclk_usbphy0 = { +struct clk clk_sclk_usbphy0 = { .name = "sclk_usbphy0", .rate = 27000000, }; -static struct clk clk_sclk_usbphy1 = { +struct clk clk_sclk_usbphy1 = { .name = "sclk_usbphy1", }; @@ -58,12 +60,7 @@ static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable); } -static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable); -} - -static int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable) +int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable); } @@ -103,12 +100,12 @@ static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable); } -static int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable) +int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable); } -static int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable) +int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable); } @@ -133,7 +130,7 @@ static struct clksrc_clk clk_mout_apll = { .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 }, }; -static struct clksrc_clk clk_sclk_apll = { +struct clksrc_clk clk_sclk_apll = { .clk = { .name = "sclk_apll", .parent = &clk_mout_apll.clk, @@ -141,7 +138,7 @@ static struct clksrc_clk clk_sclk_apll = { .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 }, }; -static struct clksrc_clk clk_mout_epll = { +struct clksrc_clk clk_mout_epll = { .clk = { .name = "mout_epll", }, @@ -149,12 +146,13 @@ static struct clksrc_clk clk_mout_epll = { .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 }, }; -static struct clksrc_clk clk_mout_mpll = { +struct clksrc_clk clk_mout_mpll = { .clk = { .name = "mout_mpll", }, .sources = &clk_src_mpll, - .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 }, + + /* reg_src will be added in each SoCs' clock */ }; static struct clk *clkset_moutcore_list[] = { @@ -224,12 +222,12 @@ static struct clksrc_clk clk_periphclk = { /* Core list of CMU_CORE side */ -static struct clk *clkset_corebus_list[] = { +struct clk *clkset_corebus_list[] = { [0] = &clk_mout_mpll.clk, [1] = &clk_sclk_apll.clk, }; -static struct clksrc_sources clkset_mout_corebus = { +struct clksrc_sources clkset_mout_corebus = { .sources = clkset_corebus_list, .nr_sources = ARRAY_SIZE(clkset_corebus_list), }; @@ -284,12 +282,12 @@ static struct clksrc_clk clk_pclk_acp = { /* Core list of CMU_TOP side */ -static struct clk *clkset_aclk_top_list[] = { +struct clk *clkset_aclk_top_list[] = { [0] = &clk_mout_mpll.clk, [1] = &clk_sclk_apll.clk, }; -static struct clksrc_sources clkset_aclk = { +struct clksrc_sources clkset_aclk = { .sources = clkset_aclk_top_list, .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), }; @@ -321,7 +319,7 @@ static struct clksrc_clk clk_aclk_160 = { .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 }, }; -static struct clksrc_clk clk_aclk_133 = { +struct clksrc_clk clk_aclk_133 = { .clk = { .name = "aclk_133", }, @@ -360,7 +358,7 @@ static struct clksrc_sources clkset_sclk_vpll = { .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list), }; -static struct clksrc_clk clk_sclk_vpll = { +struct clksrc_clk clk_sclk_vpll = { .clk = { .name = "sclk_vpll", }, @@ -410,16 +408,6 @@ static struct clk init_clocks_off[] = { .enable = exynos4_clk_ip_lcd0_ctrl, .ctrlbit = (1 << 0), }, { - .name = "fimd", - .devname = "exynos4-fb.1", - .enable = exynos4_clk_ip_lcd1_ctrl, - .ctrlbit = (1 << 0), - }, { - .name = "sataphy", - .parent = &clk_aclk_133.clk, - .enable = exynos4_clk_ip_fsys_ctrl, - .ctrlbit = (1 << 3), - }, { .name = "hsmmc", .devname = "s3c-sdhci.0", .parent = &clk_aclk_133.clk, @@ -449,11 +437,6 @@ static struct clk init_clocks_off[] = { .enable = exynos4_clk_ip_fsys_ctrl, .ctrlbit = (1 << 9), }, { - .name = "sata", - .parent = &clk_aclk_133.clk, - .enable = exynos4_clk_ip_fsys_ctrl, - .ctrlbit = (1 << 10), - }, { .name = "pdma", .devname = "s3c-pl330.0", .enable = exynos4_clk_ip_fsys_ctrl, @@ -673,7 +656,7 @@ static struct clk init_clocks[] = { } }; -static struct clk *clkset_group_list[] = { +struct clk *clkset_group_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, [2] = &clk_sclk_hdmi27m, @@ -685,7 +668,7 @@ static struct clk *clkset_group_list[] = { [8] = &clk_sclk_vpll.clk, }; -static struct clksrc_sources clkset_group = { +struct clksrc_sources clkset_group = { .sources = clkset_group_list, .nr_sources = ARRAY_SIZE(clkset_group_list), }; @@ -969,25 +952,6 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 }, }, { .clk = { - .name = "sclk_fimd", - .devname = "exynos4-fb.1", - .enable = exynos4_clksrc_mask_lcd1_ctrl, - .ctrlbit = (1 << 0), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_sata", - .enable = exynos4_clksrc_mask_fsys_ctrl, - .ctrlbit = (1 << 24), - }, - .sources = &clkset_mout_corebus, - .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 }, - .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 }, - }, { - .clk = { .name = "sclk_spi", .devname = "s3c64xx-spi.0", .enable = exynos4_clksrc_mask_peril1_ctrl, @@ -1116,7 +1080,13 @@ static int xtal_rate; static unsigned long exynos4_fout_apll_get_rate(struct clk *clk) { - return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508); + if (soc_is_exynos4210()) + return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), + pll_4508); + else if (soc_is_exynos4212()) + return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0)); + else + return 0; } static struct clk_ops exynos4_fout_apll_ops = { @@ -1126,10 +1096,10 @@ static struct clk_ops exynos4_fout_apll_ops = { void __init_or_cpufreq exynos4_setup_clocks(void) { struct clk *xtal_clk; - unsigned long apll; - unsigned long mpll; - unsigned long epll; - unsigned long vpll; + unsigned long apll = 0; + unsigned long mpll = 0; + unsigned long epll = 0; + unsigned long vpll = 0; unsigned long vpllsrc; unsigned long xtal; unsigned long armclk; @@ -1153,14 +1123,29 @@ void __init_or_cpufreq exynos4_setup_clocks(void) printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); - apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508); - mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508); - epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0), - __raw_readl(S5P_EPLL_CON1), pll_4600); - - vpllsrc = clk_get_rate(&clk_vpllsrc.clk); - vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0), - __raw_readl(S5P_VPLL_CON1), pll_4650c); + if (soc_is_exynos4210()) { + apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), + pll_4508); + mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), + pll_4508); + epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0), + __raw_readl(S5P_EPLL_CON1), pll_4600); + + vpllsrc = clk_get_rate(&clk_vpllsrc.clk); + vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0), + __raw_readl(S5P_VPLL_CON1), pll_4650c); + } else if (soc_is_exynos4212()) { + apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0)); + mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0)); + epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0), + __raw_readl(S5P_EPLL_CON1)); + + vpllsrc = clk_get_rate(&clk_vpllsrc.clk); + vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(S5P_VPLL_CON0), + __raw_readl(S5P_VPLL_CON1)); + } else { + /* nothing */ + } clk_fout_apll.ops = &exynos4_fout_apll_ops; clk_fout_mpll.rate = mpll; diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 1e1a7a9..02ec52a 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -188,6 +188,12 @@ void __init exynos4_init_clocks(int xtal) s3c24xx_register_baseclocks(xtal); s5p_register_clocks(xtal); + + if (soc_is_exynos4210()) + exynos4210_register_clocks(); + else if (soc_is_exynos4212()) + exynos4212_register_clocks(); + exynos4_register_clocks(); exynos4_setup_clocks(); } diff --git a/arch/arm/mach-exynos4/include/mach/exynos4-clock.h b/arch/arm/mach-exynos4/include/mach/exynos4-clock.h new file mode 100644 index 0000000..a07fcbf --- /dev/null +++ b/arch/arm/mach-exynos4/include/mach/exynos4-clock.h @@ -0,0 +1,43 @@ +/* + * linux/arch/arm/mach-exynos4/include/mach/exynos4-clock.h + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file for exynos4 clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_CLOCK_H +#define __ASM_ARCH_CLOCK_H __FILE__ + +#include + +extern struct clk clk_sclk_hdmi27m; +extern struct clk clk_sclk_usbphy0; +extern struct clk clk_sclk_usbphy1; +extern struct clk clk_sclk_hdmiphy; + +extern struct clksrc_clk clk_sclk_apll; +extern struct clksrc_clk clk_mout_mpll; +extern struct clksrc_clk clk_aclk_133; +extern struct clksrc_clk clk_mout_epll; +extern struct clksrc_clk clk_sclk_vpll; + +extern struct clk *clkset_corebus_list[]; +extern struct clksrc_sources clkset_mout_corebus; + +extern struct clk *clkset_aclk_top_list[]; +extern struct clksrc_sources clkset_aclk; + +extern struct clk *clkset_group_list[]; +extern struct clksrc_sources clkset_group; + +extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable); +extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable); +extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable); + +#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h index d493fdb..e75d0f8 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h @@ -13,6 +13,7 @@ #ifndef __ASM_ARCH_REGS_CLOCK_H #define __ASM_ARCH_REGS_CLOCK_H __FILE__ +#include #include #define S5P_CLKREG(x) (S5P_VA_CMU + (x)) @@ -41,12 +42,20 @@ #define S5P_CLKSRC_G3D S5P_CLKREG(0x0C22C) #define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230) #define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234) -#define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238) #define S5P_CLKSRC_MAUDIO S5P_CLKREG(0x0C23C) #define S5P_CLKSRC_FSYS S5P_CLKREG(0x0C240) #define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250) #define S5P_CLKSRC_PERIL1 S5P_CLKREG(0x0C254) +#define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310) +#define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320) +#define S5P_CLKSRC_MASK_TV S5P_CLKREG(0x0C324) +#define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334) +#define S5P_CLKSRC_MASK_MAUDIO S5P_CLKREG(0x0C33C) +#define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340) +#define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) +#define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354) + #define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510) #define S5P_CLKDIV_CAM S5P_CLKREG(0x0C520) #define S5P_CLKDIV_TV S5P_CLKREG(0x0C524) @@ -54,7 +63,6 @@ #define S5P_CLKDIV_G3D S5P_CLKREG(0x0C52C) #define S5P_CLKDIV_IMAGE S5P_CLKREG(0x0C530) #define S5P_CLKDIV_LCD0 S5P_CLKREG(0x0C534) -#define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538) #define S5P_CLKDIV_MAUDIO S5P_CLKREG(0x0C53C) #define S5P_CLKDIV_FSYS0 S5P_CLKREG(0x0C540) #define S5P_CLKDIV_FSYS1 S5P_CLKREG(0x0C544) @@ -68,16 +76,6 @@ #define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564) #define S5P_CLKDIV2_RATIO S5P_CLKREG(0x0C580) -#define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310) -#define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320) -#define S5P_CLKSRC_MASK_TV S5P_CLKREG(0x0C324) -#define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334) -#define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338) -#define S5P_CLKSRC_MASK_MAUDIO S5P_CLKREG(0x0C33C) -#define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340) -#define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) -#define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354) - #define S5P_CLKDIV_STAT_TOP S5P_CLKREG(0x0C610) #define S5P_CLKGATE_SCLKCAM S5P_CLKREG(0x0C820) @@ -85,13 +83,16 @@ #define S5P_CLKGATE_IP_TV S5P_CLKREG(0x0C924) #define S5P_CLKGATE_IP_MFC S5P_CLKREG(0x0C928) #define S5P_CLKGATE_IP_G3D S5P_CLKREG(0x0C92C) -#define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930) +#define S5P_CLKGATE_IP_IMAGE (soc_is_exynos4210() ? \ + S5P_CLKREG(0x0C930) : \ + S5P_CLKREG(0x04930)) #define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934) -#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938) #define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940) #define S5P_CLKGATE_IP_GPS S5P_CLKREG(0x0C94C) #define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950) -#define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960) +#define S5P_CLKGATE_IP_PERIR (soc_is_exynos4210() ? \ + S5P_CLKREG(0x0C960) : \ + S5P_CLKREG(0x08960)) #define S5P_CLKGATE_BLOCK S5P_CLKREG(0x0C970) #define S5P_CLKSRC_MASK_DMC S5P_CLKREG(0x10300) @@ -102,11 +103,17 @@ #define S5P_CLKGATE_IP_DMC S5P_CLKREG(0x10900) #define S5P_APLL_LOCK S5P_CLKREG(0x14000) -#define S5P_MPLL_LOCK S5P_CLKREG(0x14004) +#define S5P_MPLL_LOCK (soc_is_exynos4210() ? \ + S5P_CLKREG(0x14004) : \ + S5P_CLKREG(0x10008)) #define S5P_APLL_CON0 S5P_CLKREG(0x14100) #define S5P_APLL_CON1 S5P_CLKREG(0x14104) -#define S5P_MPLL_CON0 S5P_CLKREG(0x14108) -#define S5P_MPLL_CON1 S5P_CLKREG(0x1410C) +#define S5P_MPLL_CON0 (soc_is_exynos4210() ? \ + S5P_CLKREG(0x14108) : \ + S5P_CLKREG(0x10108)) +#define S5P_MPLL_CON1 (soc_is_exynos4210() ? \ + S5P_CLKREG(0x1410C) : \ + S5P_CLKREG(0x1010C)) #define S5P_CLKSRC_CPU S5P_CLKREG(0x14200) #define S5P_CLKMUX_STATCPU S5P_CLKREG(0x14400) @@ -183,6 +190,13 @@ #define S5P_CLKDIV_BUS_GPLR_SHIFT (4) #define S5P_CLKDIV_BUS_GPLR_MASK (0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT) +/* Only for EXYNOS4210 */ + +#define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238) +#define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338) +#define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538) +#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938) + /* Compatibility defines and inclusion */ #include diff --git a/arch/arm/plat-s5p/include/plat/exynos4.h b/arch/arm/plat-s5p/include/plat/exynos4.h index 4aed130..f680a14 100644 --- a/arch/arm/plat-s5p/include/plat/exynos4.h +++ b/arch/arm/plat-s5p/include/plat/exynos4.h @@ -14,6 +14,8 @@ extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void exynos4_register_clocks(void); +extern void exynos4210_register_clocks(void); +extern void exynos4212_register_clocks(void); extern void exynos4_setup_clocks(void); #ifdef CONFIG_ARCH_EXYNOS4 diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index bf28fad..1bfd61a 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -12,6 +12,59 @@ * published by the Free Software Foundation. */ +#include + +#define PLL35XX_MDIV_MASK (0x3FF) +#define PLL35XX_PDIV_MASK (0x3F) +#define PLL35XX_SDIV_MASK (0x7) +#define PLL35XX_MDIV_SHIFT (16) +#define PLL35XX_PDIV_SHIFT (8) +#define PLL35XX_SDIV_SHIFT (0) + +static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con) +{ + u32 mdiv, pdiv, sdiv; + u64 fvco = baseclk; + + mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK; + pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK; + sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +#define PLL36XX_KDIV_MASK (0xFFFF) +#define PLL36XX_MDIV_MASK (0x1FF) +#define PLL36XX_PDIV_MASK (0x3F) +#define PLL36XX_SDIV_MASK (0x7) +#define PLL36XX_MDIV_SHIFT (16) +#define PLL36XX_PDIV_SHIFT (8) +#define PLL36XX_SDIV_SHIFT (0) + +static inline unsigned long s5p_get_pll36xx(unsigned long baseclk, + u32 pll_con0, u32 pll_con1) +{ + unsigned long result; + u32 mdiv, pdiv, sdiv, kdiv; + u64 tmp; + + mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK; + pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK; + sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK; + kdiv = pll_con1 & PLL36XX_KDIV_MASK; + + tmp = baseclk; + + tmp *= (mdiv << 16) + kdiv; + do_div(tmp, (pdiv << sdiv)); + result = tmp >> 16; + + return result; +} + #define PLL45XX_MDIV_MASK (0x3FF) #define PLL45XX_PDIV_MASK (0x3F) #define PLL45XX_SDIV_MASK (0x7) @@ -19,8 +72,6 @@ #define PLL45XX_PDIV_SHIFT (8) #define PLL45XX_SDIV_SHIFT (0) -#include - enum pll45xx_type_t { pll_4500, pll_4502, -- cgit v0.10.2 From acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Wed, 24 Aug 2011 21:52:45 +0900 Subject: ARM: EXYNOS4: Add support PM for EXYNOS4212 This patch moves regarding clock stuff of PM into clock file to support PM on EXYNOS4210 and EXYNOS4212 with one single kernel image. Because some clock registers are different on each SoCs. Signed-off-by: Jonghwan Choi [kgene.kim@samsung.com: use CONFIG_PM_SLEEP instead of CONFIG_PM] Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos4/clock-exynos4210.c b/arch/arm/mach-exynos4/clock-exynos4210.c index fe74b91..b9d5ef6 100644 --- a/arch/arm/mach-exynos4/clock-exynos4210.c +++ b/arch/arm/mach-exynos4/clock-exynos4210.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -23,12 +24,24 @@ #include #include #include +#include #include #include #include #include +static struct sleep_save exynos4210_clock_save[] = { + SAVE_ITEM(S5P_CLKSRC_IMAGE), + SAVE_ITEM(S5P_CLKSRC_LCD1), + SAVE_ITEM(S5P_CLKDIV_IMAGE), + SAVE_ITEM(S5P_CLKDIV_LCD1), + SAVE_ITEM(S5P_CLKSRC_MASK_LCD1), + SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4210), + SAVE_ITEM(S5P_CLKGATE_IP_LCD1), + SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210), +}; + static struct clksrc_clk *sysclks[] = { /* nothing here yet */ }; @@ -83,6 +96,29 @@ static struct clk init_clocks_off[] = { }, }; +#ifdef CONFIG_PM_SLEEP +static int exynos4210_clock_suspend(void) +{ + s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save)); + + return 0; +} + +static void exynos4210_clock_resume(void) +{ + s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save)); +} + +#else +#define exynos4210_clock_suspend NULL +#define exynos4210_clock_resume NULL +#endif + +struct syscore_ops exynos4210_clock_syscore_ops = { + .suspend = exynos4210_clock_suspend, + .resume = exynos4210_clock_resume, +}; + void __init exynos4210_register_clocks(void) { int ptr; @@ -98,4 +134,6 @@ void __init exynos4210_register_clocks(void) s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + + register_syscore_ops(&exynos4210_clock_syscore_ops); } diff --git a/arch/arm/mach-exynos4/clock-exynos4212.c b/arch/arm/mach-exynos4/clock-exynos4212.c index 5a47a3f..77d5dec 100644 --- a/arch/arm/mach-exynos4/clock-exynos4212.c +++ b/arch/arm/mach-exynos4/clock-exynos4212.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -23,12 +24,20 @@ #include #include #include +#include #include #include #include #include +static struct sleep_save exynos4212_clock_save[] = { + SAVE_ITEM(S5P_CLKSRC_IMAGE), + SAVE_ITEM(S5P_CLKDIV_IMAGE), + SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212), + SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212), +}; + static struct clk *clk_src_mpll_user_list[] = { [0] = &clk_fin_mpll, [1] = &clk_mout_mpll.clk, @@ -59,6 +68,29 @@ static struct clk init_clocks_off[] = { /* nothing here yet */ }; +#ifdef CONFIG_PM_SLEEP +static int exynos4212_clock_suspend(void) +{ + s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save)); + + return 0; +} + +static void exynos4212_clock_resume(void) +{ + s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save)); +} + +#else +#define exynos4212_clock_suspend NULL +#define exynos4212_clock_resume NULL +#endif + +struct syscore_ops exynos4212_clock_syscore_ops = { + .suspend = exynos4212_clock_suspend, + .resume = exynos4212_clock_resume, +}; + void __init exynos4212_register_clocks(void) { int ptr; @@ -81,4 +113,6 @@ void __init exynos4212_register_clocks(void) s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + + register_syscore_ops(&exynos4212_clock_syscore_ops); } diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c index eb99467..f26aea3 100644 --- a/arch/arm/mach-exynos4/clock.c +++ b/arch/arm/mach-exynos4/clock.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -21,12 +22,77 @@ #include #include #include +#include #include #include #include #include +static struct sleep_save exynos4_clock_save[] = { + SAVE_ITEM(S5P_CLKDIV_LEFTBUS), + SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS), + SAVE_ITEM(S5P_CLKDIV_RIGHTBUS), + SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS), + SAVE_ITEM(S5P_CLKSRC_TOP0), + SAVE_ITEM(S5P_CLKSRC_TOP1), + SAVE_ITEM(S5P_CLKSRC_CAM), + SAVE_ITEM(S5P_CLKSRC_TV), + SAVE_ITEM(S5P_CLKSRC_MFC), + SAVE_ITEM(S5P_CLKSRC_G3D), + SAVE_ITEM(S5P_CLKSRC_LCD0), + SAVE_ITEM(S5P_CLKSRC_MAUDIO), + SAVE_ITEM(S5P_CLKSRC_FSYS), + SAVE_ITEM(S5P_CLKSRC_PERIL0), + SAVE_ITEM(S5P_CLKSRC_PERIL1), + SAVE_ITEM(S5P_CLKDIV_CAM), + SAVE_ITEM(S5P_CLKDIV_TV), + SAVE_ITEM(S5P_CLKDIV_MFC), + SAVE_ITEM(S5P_CLKDIV_G3D), + SAVE_ITEM(S5P_CLKDIV_LCD0), + SAVE_ITEM(S5P_CLKDIV_MAUDIO), + SAVE_ITEM(S5P_CLKDIV_FSYS0), + SAVE_ITEM(S5P_CLKDIV_FSYS1), + SAVE_ITEM(S5P_CLKDIV_FSYS2), + SAVE_ITEM(S5P_CLKDIV_FSYS3), + SAVE_ITEM(S5P_CLKDIV_PERIL0), + SAVE_ITEM(S5P_CLKDIV_PERIL1), + SAVE_ITEM(S5P_CLKDIV_PERIL2), + SAVE_ITEM(S5P_CLKDIV_PERIL3), + SAVE_ITEM(S5P_CLKDIV_PERIL4), + SAVE_ITEM(S5P_CLKDIV_PERIL5), + SAVE_ITEM(S5P_CLKDIV_TOP), + SAVE_ITEM(S5P_CLKSRC_MASK_TOP), + SAVE_ITEM(S5P_CLKSRC_MASK_CAM), + SAVE_ITEM(S5P_CLKSRC_MASK_TV), + SAVE_ITEM(S5P_CLKSRC_MASK_LCD0), + SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO), + SAVE_ITEM(S5P_CLKSRC_MASK_FSYS), + SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0), + SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1), + SAVE_ITEM(S5P_CLKDIV2_RATIO), + SAVE_ITEM(S5P_CLKGATE_SCLKCAM), + SAVE_ITEM(S5P_CLKGATE_IP_CAM), + SAVE_ITEM(S5P_CLKGATE_IP_TV), + SAVE_ITEM(S5P_CLKGATE_IP_MFC), + SAVE_ITEM(S5P_CLKGATE_IP_G3D), + SAVE_ITEM(S5P_CLKGATE_IP_LCD0), + SAVE_ITEM(S5P_CLKGATE_IP_FSYS), + SAVE_ITEM(S5P_CLKGATE_IP_GPS), + SAVE_ITEM(S5P_CLKGATE_IP_PERIL), + SAVE_ITEM(S5P_CLKGATE_BLOCK), + SAVE_ITEM(S5P_CLKSRC_MASK_DMC), + SAVE_ITEM(S5P_CLKSRC_DMC), + SAVE_ITEM(S5P_CLKDIV_DMC0), + SAVE_ITEM(S5P_CLKDIV_DMC1), + SAVE_ITEM(S5P_CLKGATE_IP_DMC), + SAVE_ITEM(S5P_CLKSRC_CPU), + SAVE_ITEM(S5P_CLKDIV_CPU), + SAVE_ITEM(S5P_CLKDIV_CPU + 0x4), + SAVE_ITEM(S5P_CLKGATE_SCLKCPU), + SAVE_ITEM(S5P_CLKGATE_IP_CPU), +}; + struct clk clk_sclk_hdmi27m = { .name = "sclk_hdmi27m", .rate = 27000000, @@ -1180,6 +1246,28 @@ static struct clk *clks[] __initdata = { /* Nothing here yet */ }; +#ifdef CONFIG_PM_SLEEP +static int exynos4_clock_suspend(void) +{ + s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save)); + return 0; +} + +static void exynos4_clock_resume(void) +{ + s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save)); +} + +#else +#define exynos4_clock_suspend NULL +#define exynos4_clock_resume NULL +#endif + +struct syscore_ops exynos4_clock_syscore_ops = { + .suspend = exynos4_clock_suspend, + .resume = exynos4_clock_resume, +}; + void __init exynos4_register_clocks(void) { int ptr; @@ -1195,5 +1283,6 @@ void __init exynos4_register_clocks(void) s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + register_syscore_ops(&exynos4_clock_syscore_ops); s3c_pwmclk_init(); } diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h index e75d0f8..6c37ebe 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h @@ -86,6 +86,8 @@ #define S5P_CLKGATE_IP_IMAGE (soc_is_exynos4210() ? \ S5P_CLKREG(0x0C930) : \ S5P_CLKREG(0x04930)) +#define S5P_CLKGATE_IP_IMAGE_4210 S5P_CLKREG(0x0C930) +#define S5P_CLKGATE_IP_IMAGE_4212 S5P_CLKREG(0x04930) #define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934) #define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940) #define S5P_CLKGATE_IP_GPS S5P_CLKREG(0x0C94C) @@ -93,6 +95,8 @@ #define S5P_CLKGATE_IP_PERIR (soc_is_exynos4210() ? \ S5P_CLKREG(0x0C960) : \ S5P_CLKREG(0x08960)) +#define S5P_CLKGATE_IP_PERIR_4210 S5P_CLKREG(0x0C960) +#define S5P_CLKGATE_IP_PERIR_4212 S5P_CLKREG(0x08960) #define S5P_CLKGATE_BLOCK S5P_CLKREG(0x0C970) #define S5P_CLKSRC_MASK_DMC S5P_CLKREG(0x10300) diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c index bc6ca94..62e4f43 100644 --- a/arch/arm/mach-exynos4/pm.c +++ b/arch/arm/mach-exynos4/pm.c @@ -41,7 +41,6 @@ static struct sleep_save exynos4_set_clksrc[] = { { .reg = S5P_CLKSRC_MASK_CAM , .val = 0x11111111, }, { .reg = S5P_CLKSRC_MASK_TV , .val = 0x00000111, }, { .reg = S5P_CLKSRC_MASK_LCD0 , .val = 0x00001111, }, - { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, }, { .reg = S5P_CLKSRC_MASK_MAUDIO , .val = 0x00000001, }, { .reg = S5P_CLKSRC_MASK_FSYS , .val = 0x01011111, }, { .reg = S5P_CLKSRC_MASK_PERIL0 , .val = 0x01111111, }, @@ -49,6 +48,10 @@ static struct sleep_save exynos4_set_clksrc[] = { { .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, }, }; +static struct sleep_save exynos4210_set_clksrc[] = { + { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, }, +}; + static struct sleep_save exynos4_epll_save[] = { SAVE_ITEM(S5P_EPLL_CON0), SAVE_ITEM(S5P_EPLL_CON1), @@ -60,77 +63,6 @@ static struct sleep_save exynos4_vpll_save[] = { }; static struct sleep_save exynos4_core_save[] = { - /* CMU side */ - SAVE_ITEM(S5P_CLKDIV_LEFTBUS), - SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS), - SAVE_ITEM(S5P_CLKDIV_RIGHTBUS), - SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS), - SAVE_ITEM(S5P_CLKSRC_TOP0), - SAVE_ITEM(S5P_CLKSRC_TOP1), - SAVE_ITEM(S5P_CLKSRC_CAM), - SAVE_ITEM(S5P_CLKSRC_TV), - SAVE_ITEM(S5P_CLKSRC_MFC), - SAVE_ITEM(S5P_CLKSRC_G3D), - SAVE_ITEM(S5P_CLKSRC_IMAGE), - SAVE_ITEM(S5P_CLKSRC_LCD0), - SAVE_ITEM(S5P_CLKSRC_LCD1), - SAVE_ITEM(S5P_CLKSRC_MAUDIO), - SAVE_ITEM(S5P_CLKSRC_FSYS), - SAVE_ITEM(S5P_CLKSRC_PERIL0), - SAVE_ITEM(S5P_CLKSRC_PERIL1), - SAVE_ITEM(S5P_CLKDIV_CAM), - SAVE_ITEM(S5P_CLKDIV_TV), - SAVE_ITEM(S5P_CLKDIV_MFC), - SAVE_ITEM(S5P_CLKDIV_G3D), - SAVE_ITEM(S5P_CLKDIV_IMAGE), - SAVE_ITEM(S5P_CLKDIV_LCD0), - SAVE_ITEM(S5P_CLKDIV_LCD1), - SAVE_ITEM(S5P_CLKDIV_MAUDIO), - SAVE_ITEM(S5P_CLKDIV_FSYS0), - SAVE_ITEM(S5P_CLKDIV_FSYS1), - SAVE_ITEM(S5P_CLKDIV_FSYS2), - SAVE_ITEM(S5P_CLKDIV_FSYS3), - SAVE_ITEM(S5P_CLKDIV_PERIL0), - SAVE_ITEM(S5P_CLKDIV_PERIL1), - SAVE_ITEM(S5P_CLKDIV_PERIL2), - SAVE_ITEM(S5P_CLKDIV_PERIL3), - SAVE_ITEM(S5P_CLKDIV_PERIL4), - SAVE_ITEM(S5P_CLKDIV_PERIL5), - SAVE_ITEM(S5P_CLKDIV_TOP), - SAVE_ITEM(S5P_CLKSRC_MASK_TOP), - SAVE_ITEM(S5P_CLKSRC_MASK_CAM), - SAVE_ITEM(S5P_CLKSRC_MASK_TV), - SAVE_ITEM(S5P_CLKSRC_MASK_LCD0), - SAVE_ITEM(S5P_CLKSRC_MASK_LCD1), - SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO), - SAVE_ITEM(S5P_CLKSRC_MASK_FSYS), - SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0), - SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1), - SAVE_ITEM(S5P_CLKDIV2_RATIO), - SAVE_ITEM(S5P_CLKGATE_SCLKCAM), - SAVE_ITEM(S5P_CLKGATE_IP_CAM), - SAVE_ITEM(S5P_CLKGATE_IP_TV), - SAVE_ITEM(S5P_CLKGATE_IP_MFC), - SAVE_ITEM(S5P_CLKGATE_IP_G3D), - SAVE_ITEM(S5P_CLKGATE_IP_IMAGE), - SAVE_ITEM(S5P_CLKGATE_IP_LCD0), - SAVE_ITEM(S5P_CLKGATE_IP_LCD1), - SAVE_ITEM(S5P_CLKGATE_IP_FSYS), - SAVE_ITEM(S5P_CLKGATE_IP_GPS), - SAVE_ITEM(S5P_CLKGATE_IP_PERIL), - SAVE_ITEM(S5P_CLKGATE_IP_PERIR), - SAVE_ITEM(S5P_CLKGATE_BLOCK), - SAVE_ITEM(S5P_CLKSRC_MASK_DMC), - SAVE_ITEM(S5P_CLKSRC_DMC), - SAVE_ITEM(S5P_CLKDIV_DMC0), - SAVE_ITEM(S5P_CLKDIV_DMC1), - SAVE_ITEM(S5P_CLKGATE_IP_DMC), - SAVE_ITEM(S5P_CLKSRC_CPU), - SAVE_ITEM(S5P_CLKDIV_CPU), - SAVE_ITEM(S5P_CLKDIV_CPU + 0x4), - SAVE_ITEM(S5P_CLKGATE_SCLKCPU), - SAVE_ITEM(S5P_CLKGATE_IP_CPU), - /* GIC side */ SAVE_ITEM(S5P_VA_GIC_CPU + 0x000), SAVE_ITEM(S5P_VA_GIC_CPU + 0x004), @@ -268,6 +200,9 @@ static void exynos4_pm_prepare(void) s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc)); + if (soc_is_exynos4210()) + s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc)); + } static int exynos4_pm_add(struct sys_device *sysdev) -- cgit v0.10.2 From be4ab3616839c26caf914449de3a22458f53f6e5 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 24 Aug 2011 17:25:09 +0900 Subject: ARM: EXYNOS4: Add support SMDK4212 Board This patch adds mach-smdk4212.c to support SMDK4212 board. Now it can support HSMMCs, I2Cs, RTC, WDT and Keypad. Other features will be supported next time. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index 0b40289..f4ec583 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -116,6 +116,8 @@ config EXYNOS4_SETUP_USB_PHY menu "EXYNOS4 Machines" +comment "EXYNOS4210 Boards" + config MACH_SMDKC210 bool "SMDKC210" select MACH_SMDKV310 @@ -208,6 +210,29 @@ config MACH_NURI help Machine support for Samsung Mobile NURI Board. +comment "EXYNOS4212 Boards" + +config MACH_SMDK4212 + bool "SMDK4212" + select SOC_EXYNOS4212 + select S3C_DEV_HSMMC2 + select S3C_DEV_HSMMC3 + select S3C_DEV_I2C1 + select S3C_DEV_I2C3 + select S3C_DEV_I2C7 + select S3C_DEV_RTC + select S3C_DEV_WDT + select SAMSUNG_DEV_BACKLIGHT + select SAMSUNG_DEV_KEYPAD + select SAMSUNG_DEV_PWM + select EXYNOS4_SETUP_I2C1 + select EXYNOS4_SETUP_I2C3 + select EXYNOS4_SETUP_I2C7 + select EXYNOS4_SETUP_KEYPAD + select EXYNOS4_SETUP_SDHCI + help + Machine support for Samsung SMDK4212 + endmenu comment "Configuration for HSMMC bus width" diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index 4624457..64ffad4 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -33,6 +33,8 @@ obj-$(CONFIG_MACH_ARMLEX4210) += mach-armlex4210.o obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o obj-$(CONFIG_MACH_NURI) += mach-nuri.o +obj-$(CONFIG_MACH_SMDK4212) += mach-smdk4212.o + # device support obj-y += dev-audio.o diff --git a/arch/arm/mach-exynos4/mach-smdk4212.c b/arch/arm/mach-exynos4/mach-smdk4212.c new file mode 100644 index 0000000..3479a93 --- /dev/null +++ b/arch/arm/mach-exynos4/mach-smdk4212.c @@ -0,0 +1,292 @@ +/* + * linux/arch/arm/mach-exynos4/mach-smdk4212.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Following are default values for UCON, ULCON and UFCON UART registers */ +#define SMDK4212_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define SMDK4212_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define SMDK4212_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG4 | \ + S5PV210_UFCON_RXTRIG4) + +static struct s3c2410_uartcfg smdk4212_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = SMDK4212_UCON_DEFAULT, + .ulcon = SMDK4212_ULCON_DEFAULT, + .ufcon = SMDK4212_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = SMDK4212_UCON_DEFAULT, + .ulcon = SMDK4212_ULCON_DEFAULT, + .ufcon = SMDK4212_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = SMDK4212_UCON_DEFAULT, + .ulcon = SMDK4212_ULCON_DEFAULT, + .ufcon = SMDK4212_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = SMDK4212_UCON_DEFAULT, + .ulcon = SMDK4212_ULCON_DEFAULT, + .ufcon = SMDK4212_UFCON_DEFAULT, + }, +}; + +static struct s3c_sdhci_platdata smdk4212_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_INTERNAL, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdk4212_hsmmc3_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_INTERNAL, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +}; + +static struct regulator_consumer_supply max8997_buck1 = + REGULATOR_SUPPLY("vdd_arm", NULL); + +static struct regulator_consumer_supply max8997_buck2 = + REGULATOR_SUPPLY("vdd_int", NULL); + +static struct regulator_consumer_supply max8997_buck3 = + REGULATOR_SUPPLY("vdd_g3d", NULL); + +static struct regulator_init_data max8997_buck1_data = { + .constraints = { + .name = "VDD_ARM_SMDK4212", + .min_uV = 925000, + .max_uV = 1350000, + .always_on = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .state_mem = { + .disabled = 1, + }, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &max8997_buck1, +}; + +static struct regulator_init_data max8997_buck2_data = { + .constraints = { + .name = "VDD_INT_SMDK4212", + .min_uV = 950000, + .max_uV = 1150000, + .always_on = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .state_mem = { + .disabled = 1, + }, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &max8997_buck2, +}; + +static struct regulator_init_data max8997_buck3_data = { + .constraints = { + .name = "VDD_G3D_SMDK4212", + .min_uV = 950000, + .max_uV = 1150000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .state_mem = { + .disabled = 1, + }, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &max8997_buck3, +}; + +static struct max8997_regulator_data smdk4212_max8997_regulators[] = { + { MAX8997_BUCK1, &max8997_buck1_data }, + { MAX8997_BUCK2, &max8997_buck2_data }, + { MAX8997_BUCK3, &max8997_buck3_data }, +}; + +static struct max8997_platform_data smdk4212_max8997_pdata = { + .num_regulators = ARRAY_SIZE(smdk4212_max8997_regulators), + .regulators = smdk4212_max8997_regulators, + + .buck1_voltage[0] = 1100000, /* 1.1V */ + .buck1_voltage[1] = 1100000, /* 1.1V */ + .buck1_voltage[2] = 1100000, /* 1.1V */ + .buck1_voltage[3] = 1100000, /* 1.1V */ + .buck1_voltage[4] = 1100000, /* 1.1V */ + .buck1_voltage[5] = 1100000, /* 1.1V */ + .buck1_voltage[6] = 1000000, /* 1.0V */ + .buck1_voltage[7] = 950000, /* 0.95V */ + + .buck2_voltage[0] = 1100000, /* 1.1V */ + .buck2_voltage[1] = 1000000, /* 1.0V */ + .buck2_voltage[2] = 950000, /* 0.95V */ + .buck2_voltage[3] = 900000, /* 0.9V */ + .buck2_voltage[4] = 1100000, /* 1.1V */ + .buck2_voltage[5] = 1000000, /* 1.0V */ + .buck2_voltage[6] = 950000, /* 0.95V */ + .buck2_voltage[7] = 900000, /* 0.9V */ + + .buck5_voltage[0] = 1100000, /* 1.1V */ + .buck5_voltage[1] = 1100000, /* 1.1V */ + .buck5_voltage[2] = 1100000, /* 1.1V */ + .buck5_voltage[3] = 1100000, /* 1.1V */ + .buck5_voltage[4] = 1100000, /* 1.1V */ + .buck5_voltage[5] = 1100000, /* 1.1V */ + .buck5_voltage[6] = 1100000, /* 1.1V */ + .buck5_voltage[7] = 1100000, /* 1.1V */ +}; + +static struct i2c_board_info smdk4212_i2c_devs0[] __initdata = { + { + I2C_BOARD_INFO("max8997", 0x66), + .platform_data = &smdk4212_max8997_pdata, + } +}; + +static struct i2c_board_info smdk4212_i2c_devs1[] __initdata = { + { I2C_BOARD_INFO("wm8994", 0x1a), } +}; + +static struct i2c_board_info smdk4212_i2c_devs3[] __initdata = { + /* nothing here yet */ +}; + +static struct i2c_board_info smdk4212_i2c_devs7[] __initdata = { + /* nothing here yet */ +}; + +static struct samsung_bl_gpio_info smdk4212_bl_gpio_info = { + .no = EXYNOS4_GPD0(1), + .func = S3C_GPIO_SFN(2), +}; + +static struct platform_pwm_backlight_data smdk4212_bl_data = { + .pwm_id = 1, + .pwm_period_ns = 1000, +}; + +static uint32_t smdk4212_keymap[] __initdata = { + /* KEY(row, col, keycode) */ + KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B), + KEY(1, 3, KEY_E), KEY(1, 4, KEY_C) +}; + +static struct matrix_keymap_data smdk4212_keymap_data __initdata = { + .keymap = smdk4212_keymap, + .keymap_size = ARRAY_SIZE(smdk4212_keymap), +}; + +static struct samsung_keypad_platdata smdk4212_keypad_data __initdata = { + .keymap_data = &smdk4212_keymap_data, + .rows = 2, + .cols = 5, +}; + +static struct platform_device *smdk4212_devices[] __initdata = { + &s3c_device_hsmmc2, + &s3c_device_hsmmc3, + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_i2c3, + &s3c_device_i2c7, + &s3c_device_rtc, + &s3c_device_wdt, + &samsung_device_keypad, +}; + +static void __init smdk4212_map_io(void) +{ + clk_xusbxti.rate = 24000000; + + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(clk_xusbxti.rate); + s3c24xx_init_uarts(smdk4212_uartcfgs, ARRAY_SIZE(smdk4212_uartcfgs)); +} + +static void __init smdk4212_machine_init(void) +{ + s3c_i2c0_set_platdata(NULL); + i2c_register_board_info(0, smdk4212_i2c_devs0, + ARRAY_SIZE(smdk4212_i2c_devs0)); + + s3c_i2c1_set_platdata(NULL); + i2c_register_board_info(1, smdk4212_i2c_devs1, + ARRAY_SIZE(smdk4212_i2c_devs1)); + + s3c_i2c3_set_platdata(NULL); + i2c_register_board_info(3, smdk4212_i2c_devs3, + ARRAY_SIZE(smdk4212_i2c_devs3)); + + s3c_i2c7_set_platdata(NULL); + i2c_register_board_info(7, smdk4212_i2c_devs7, + ARRAY_SIZE(smdk4212_i2c_devs7)); + + samsung_bl_set(&smdk4212_bl_gpio_info, &smdk4212_bl_data); + + samsung_keypad_set_platdata(&smdk4212_keypad_data); + + s3c_sdhci2_set_platdata(&smdk4212_hsmmc2_pdata); + s3c_sdhci3_set_platdata(&smdk4212_hsmmc3_pdata); + + platform_add_devices(smdk4212_devices, ARRAY_SIZE(smdk4212_devices)); +} + +MACHINE_START(SMDK4212, "SMDK4212") + /* Maintainer: Kukjin Kim */ + .boot_params = S5P_PA_SDRAM + 0x100, + .init_irq = exynos4_init_irq, + .map_io = smdk4212_map_io, + .init_machine = smdk4212_machine_init, + .timer = &exynos4_timer, +MACHINE_END -- cgit v0.10.2