Hello, On Wednesday, October 13, 2010 1:47 PM Kukjin Kim wrote: > From: Changhwan Youn <chaos.youn@xxxxxxxxxxx> > > This patch adds support Power Domain for S5PV310 and S5PC210. > > Signed-off-by: Changhwan Youn <chaos.youn@xxxxxxxxxxx> > Signed-off-by: Kukjin Kim <kgene.kim@xxxxxxxxxxx> > --- > arch/arm/mach-s5pv310/Kconfig | 7 + > arch/arm/mach-s5pv310/Makefile | 2 + > arch/arm/mach-s5pv310/cpu.c | 5 + > arch/arm/mach-s5pv310/dev-pd.c | 249 +++++++++++++++++++++++++ > arch/arm/mach-s5pv310/include/mach/map.h | 2 + > arch/arm/mach-s5pv310/include/mach/regs-pmu.h | 40 ++++ > arch/arm/mach-s5pv310/mach-smdkc210.c | 9 + > arch/arm/mach-s5pv310/mach-smdkv310.c | 9 + > arch/arm/plat-s5p/include/plat/map-s5p.h | 1 + > arch/arm/plat-samsung/include/plat/devs.h | 2 + > 10 files changed, 326 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-s5pv310/dev-pd.c > create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-pmu.h > > diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig > index 1150b36..3bf72a6 100644 > --- a/arch/arm/mach-s5pv310/Kconfig > +++ b/arch/arm/mach-s5pv310/Kconfig > @@ -14,6 +14,11 @@ config CPU_S5PV310 > help > Enable S5PV310 CPU support > > +config S5PV310_DEV_PD > + bool > + help > + Compile in platform device definitions for Power Domain > + > config S5PV310_SETUP_I2C1 > bool > help > @@ -73,6 +78,7 @@ config MACH_SMDKC210 > select S3C_DEV_HSMMC1 > select S3C_DEV_HSMMC2 > select S3C_DEV_HSMMC3 > + select S5PV310_DEV_PD > select S5PV310_SETUP_SDHCI > help > Machine support for Samsung SMDKC210 > @@ -101,6 +107,7 @@ config MACH_SMDKV310 > select S3C_DEV_HSMMC1 > select S3C_DEV_HSMMC2 > select S3C_DEV_HSMMC3 > + select S5PV310_DEV_PD > select S5PV310_SETUP_SDHCI > help > Machine support for Samsung SMDKV310 > diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile > index 97aba6d..74beb47 100644 > --- a/arch/arm/mach-s5pv310/Makefile > +++ b/arch/arm/mach-s5pv310/Makefile > @@ -28,6 +28,8 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o > > # device support > > +obj-$(CONFIG_S5PV310_DEV_PD) += dev-pd.o > + > obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o > obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o > obj-$(CONFIG_S5PV310_SETUP_I2C3) += setup-i2c3.o > diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c > index ffed262..44ddad6 100644 > --- a/arch/arm/mach-s5pv310/cpu.c > +++ b/arch/arm/mach-s5pv310/cpu.c > @@ -42,6 +42,11 @@ static struct map_desc s5pv310_iodesc[] __initdata = { > .length = SZ_128K, > .type = MT_DEVICE, > }, { > + .virtual = (unsigned long)S5P_VA_PMU, > + .pfn = __phys_to_pfn(S5PV310_PA_PMU), > + .length = SZ_64K, > + .type = MT_DEVICE, > + }, { > .virtual = (unsigned long)S5P_VA_COMBINER_BASE, > .pfn = __phys_to_pfn(S5PV310_PA_COMBINER), > .length = SZ_4K, > diff --git a/arch/arm/mach-s5pv310/dev-pd.c b/arch/arm/mach-s5pv310/dev-pd.c > new file mode 100644 > index 0000000..ac5a1f8 > --- /dev/null > +++ b/arch/arm/mach-s5pv310/dev-pd.c > @@ -0,0 +1,249 @@ > +/* linux/arch/arm/mach-s5pv310/dev-pd.c > + * > + * Copyright (c) 2010 Samsung Electronics Co., Ltd. > + * http://www.samsung.com > + * > + * S5PV310 - Power Domain 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 <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/platform_device.h> > +#include <linux/delay.h> > + > +#include <mach/regs-pmu.h> > + > +#include <plat/pd.h> > + > +static int s5pv310_pd_enable(enum s5pv310_pd_block pd) > +{ > + void __iomem *status; > + u32 timeout; > + > + switch (pd) { > + case PD_MFC: > + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_MFC_CONFIGURATION); > + status = S5P_MFC_STATUS; > + break; > + case PD_G3D: > + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_G3D_CONFIGURATION); > + status = S5P_G3D_STATUS; > + break; > + case PD_LCD0: > + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_LCD0_CONFIGURATION); > + status = S5P_LCD0_STATUS; > + break; > + case PD_LCD1: > + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_LCD1_CONFIGURATION); > + status = S5P_LCD1_STATUS; > + break; > + case PD_CAM: > + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_CAM_CONFIGURATION); > + status = S5P_CAM_STATUS; > + break; > + case PD_TV: > + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_TV_CONFIGURATION); > + status = S5P_TV_STATUS; > + break; > + default: > + printk(KERN_WARNING "Wrong PD enable request %d\n", pd); > + return -EINVAL; > + } > + > + /* Wait max 1ms */ > + timeout = 10; > + while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) > + != S5P_INT_LOCAL_PWR_EN) { > + if (timeout == 0) { > + printk(KERN_ERR "Power domain %d enable failed.\n", pd); > + return -ETIMEDOUT; > + } > + timeout--; > + udelay(100); > + } > + > + return 0; > +} > + > +static int s5pv310_pd_disable(enum s5pv310_pd_block pd) > +{ > + void __iomem *status; > + u32 timeout; > + > + switch (pd) { > + case PD_MFC: > + __raw_writel(0, S5P_MFC_CONFIGURATION); > + status = S5P_MFC_STATUS; > + break; > + case PD_G3D: > + __raw_writel(0, S5P_G3D_CONFIGURATION); > + status = S5P_G3D_STATUS; > + break; > + case PD_LCD0: > + __raw_writel(0, S5P_LCD0_CONFIGURATION); > + status = S5P_LCD0_STATUS; > + break; > + case PD_LCD1: > + __raw_writel(0, S5P_LCD1_CONFIGURATION); > + status = S5P_LCD1_STATUS; > + break; > + case PD_CAM: > + __raw_writel(0, S5P_CAM_CONFIGURATION); > + status = S5P_CAM_STATUS; > + break; > + case PD_TV: > + __raw_writel(0, S5P_TV_CONFIGURATION); > + status = S5P_TV_STATUS; > + break; > + default: > + printk(KERN_WARNING "Wrong PD disable request %d\n", pd); > + return -EINVAL; > + } > + > + /* Wait max 1ms */ > + timeout = 10; > + while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) { > + if (timeout == 0) { > + printk(KERN_ERR "PD %d disable failed.\n", pd); > + return -ETIMEDOUT; > + } > + timeout--; > + udelay(100); > + } > + > + return 0; > +} > + > +static int s5pv310_pd_mfc_enable(void) > +{ > + return s5pv310_pd_enable(PD_MFC); > +} > + > +static int s5pv310_pd_mfc_disable(void) > +{ > + return s5pv310_pd_disable(PD_MFC); > +} > + > +static int s5pv310_pd_g3d_enable(void) > +{ > + return s5pv310_pd_enable(PD_G3D); > +} > + > +static int s5pv310_pd_g3d_disable(void) > +{ > + return s5pv310_pd_disable(PD_G3D); > +} > + > +static int s5pv310_pd_lcd0_enable(void) > +{ > + return s5pv310_pd_enable(PD_LCD0); > +} > + > +static int s5pv310_pd_lcd0_disable(void) > +{ > + return s5pv310_pd_disable(PD_LCD0); > +} > + > +static int s5pv310_pd_lcd1_enable(void) > +{ > + return s5pv310_pd_enable(PD_LCD1); > +} > + > +static int s5pv310_pd_lcd1_disable(void) > +{ > + return s5pv310_pd_disable(PD_LCD1); > +} > + > +static int s5pv310_pd_cam_enable(void) > +{ > + return s5pv310_pd_enable(PD_CAM); > +} > + > +static int s5pv310_pd_cam_disable(void) > +{ > + return s5pv310_pd_disable(PD_CAM); > +} > + > +static int s5pv310_pd_tv_enable(void) > +{ > + return s5pv310_pd_enable(PD_TV); > +} > + > +static int s5pv310_pd_tv_disable(void) > +{ > + return s5pv310_pd_disable(PD_TV); > +} > + > +static struct samsung_pd_info s5pv310_pd_mfc_pdata = { > + .enable = s5pv310_pd_mfc_enable, > + .disable = s5pv310_pd_mfc_disable, > +}; > + > +static struct samsung_pd_info s5pv310_pd_g3d_pdata = { > + .enable = s5pv310_pd_g3d_enable, > + .disable = s5pv310_pd_g3d_disable, > +}; > + > +static struct samsung_pd_info s5pv310_pd_lcd0_pdata = { > + .enable = s5pv310_pd_lcd0_enable, > + .disable = s5pv310_pd_lcd0_disable, > +}; > + > +static struct samsung_pd_info s5pv310_pd_lcd1_pdata = { > + .enable = s5pv310_pd_lcd1_enable, > + .disable = s5pv310_pd_lcd1_disable, > +}; > + > +static struct samsung_pd_info s5pv310_pd_tv_pdata = { > + .enable = s5pv310_pd_tv_enable, > + .disable = s5pv310_pd_tv_disable, > +}; > + > +static struct samsung_pd_info s5pv310_pd_cam_pdata = { > + .enable = s5pv310_pd_cam_enable, > + .disable = s5pv310_pd_cam_disable, > +}; You can probably get rid of all the above by adding a few more entries to struct samsung_pd_info. Just think of adding a u32 reg, status, on_value, off_value and maybe a mask. In such case all power domain devices can be handled by the same function which will read all needed data from device's platform_data. > +struct platform_device s5pv310_device_pd[] = { > + { > + .name = "samsung-pd", > + .id = 0, > + .dev = { > + .platform_data = &s5pv310_pd_mfc_pdata, > + }, You can use embedded structure definition to make the code a bit easier to read (I've also added the entries from the previous comment): .dev = { .platform_data = &(struct samsung_pd_info) { .enable = s5pv310_pd_enable, .disable = s5pv310_pd_disable, .reg = S5P_MFC_CONFIGURATION, .status = S5P_MFC_STATUS, .on_value = S5P_INT_LOCAL_PWR_EN, .mask = 0x7, }, }, > + }, { > + .name = "samsung-pd", > + .id = 1, > + .dev = { > + .platform_data = &s5pv310_pd_g3d_pdata, > + }, > + }, { > + .name = "samsung-pd", > + .id = 2, > + .dev = { > + .platform_data = &s5pv310_pd_lcd0_pdata, > + }, > + }, { > + .name = "samsung-pd", > + .id = 3, > + .dev = { > + .platform_data = &s5pv310_pd_lcd1_pdata, > + }, > + }, { > + .name = "samsung-pd", > + .id = 4, > + .dev = { > + .platform_data = &s5pv310_pd_tv_pdata, > + }, > + }, { > + .name = "samsung-pd", > + .id = 5, > + .dev = { > + .platform_data = &s5pv310_pd_cam_pdata, > + }, > + }, > +}; > diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h > index 1429510..9decf02 100644 > --- a/arch/arm/mach-s5pv310/include/mach/map.h > +++ b/arch/arm/mach-s5pv310/include/mach/map.h > @@ -37,6 +37,8 @@ > #define S5PV310_PA_SYSCON (0x10010000) > #define S5P_PA_SYSCON S5PV310_PA_SYSCON > > +#define S5PV310_PA_PMU (0x10020000) > + > #define S5PV310_PA_CMU (0x10030000) > > #define S5PV310_PA_WATCHDOG (0x10060000) > diff --git a/arch/arm/mach-s5pv310/include/mach/regs-pmu.h b/arch/arm/mach-s5pv310/include/mach/regs- > pmu.h > new file mode 100644 > index 0000000..f4b2229 > --- /dev/null > +++ b/arch/arm/mach-s5pv310/include/mach/regs-pmu.h > @@ -0,0 +1,40 @@ > +/* linux/arch/arm/mach-s5pv310/include/mach/regs-pmu.h > + * > + * Copyright (c) 2010 Samsung Electronics Co., Ltd. > + * http://www.samsung.com > + * > + * S5PV310 - Power management unit definition > + * > + * 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_REGS_PMU_H > +#define __ASM_ARCH_REGS_PMU_H __FILE__ > + > +#include <mach/map.h> > + > +#define S5P_PMUREG(x) (S5P_VA_PMU + (x)) > + > +#define S5P_CAM_CONFIGURATION S5P_PMUREG(0x3C00) > +#define S5P_CAM_STATUS S5P_PMUREG(0x3C04) > + > +#define S5P_TV_CONFIGURATION S5P_PMUREG(0x3C20) > +#define S5P_TV_STATUS S5P_PMUREG(0x3C24) > + > +#define S5P_MFC_CONFIGURATION S5P_PMUREG(0x3C40) > +#define S5P_MFC_STATUS S5P_PMUREG(0x3C44) > + > +#define S5P_G3D_CONFIGURATION S5P_PMUREG(0x3C60) > +#define S5P_G3D_STATUS S5P_PMUREG(0x3C64) > + > +#define S5P_LCD0_CONFIGURATION S5P_PMUREG(0x3C80) > +#define S5P_LCD0_STATUS S5P_PMUREG(0x3C84) > + > +#define S5P_LCD1_CONFIGURATION S5P_PMUREG(0x3CA0) > +#define S5P_LCD1_STATUS S5P_PMUREG(0x3CA4) > + > +#define S5P_INT_LOCAL_PWR_EN 0x7 > + > +#endif /* __ASM_ARCH_REGS_PMU_H */ > diff --git a/arch/arm/mach-s5pv310/mach-smdkc210.c b/arch/arm/mach-s5pv310/mach-smdkc210.c > index d2cf694..390befd 100644 > --- a/arch/arm/mach-s5pv310/mach-smdkc210.c > +++ b/arch/arm/mach-s5pv310/mach-smdkc210.c > @@ -22,6 +22,7 @@ > #include <plat/cpu.h> > #include <plat/devs.h> > #include <plat/sdhci.h> > +#include <plat/pd.h> > > #include <mach/map.h> > > @@ -113,6 +114,12 @@ static struct platform_device *smdkc210_devices[] __initdata = { > &s3c_device_hsmmc3, > &s3c_device_rtc, > &s3c_device_wdt, > + &s5pv310_device_pd[PD_MFC], > + &s5pv310_device_pd[PD_G3D], > + &s5pv310_device_pd[PD_LCD0], > + &s5pv310_device_pd[PD_LCD1], > + &s5pv310_device_pd[PD_CAM], > + &s5pv310_device_pd[PD_TV], > }; > > static void __init smdkc210_map_io(void) > @@ -124,6 +131,8 @@ static void __init smdkc210_map_io(void) > > static void __init smdkc210_machine_init(void) > { > + samsung_pd_init(); > + > s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata); > s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata); > s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata); > diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c > index 10f8056..c6690cf 100644 > --- a/arch/arm/mach-s5pv310/mach-smdkv310.c > +++ b/arch/arm/mach-s5pv310/mach-smdkv310.c > @@ -22,6 +22,7 @@ > #include <plat/cpu.h> > #include <plat/devs.h> > #include <plat/sdhci.h> > +#include <plat/pd.h> > > #include <mach/map.h> > > @@ -113,6 +114,12 @@ static struct platform_device *smdkv310_devices[] __initdata = { > &s3c_device_hsmmc3, > &s3c_device_rtc, > &s3c_device_wdt, > + &s5pv310_device_pd[PD_MFC], > + &s5pv310_device_pd[PD_G3D], > + &s5pv310_device_pd[PD_LCD0], > + &s5pv310_device_pd[PD_LCD1], > + &s5pv310_device_pd[PD_CAM], > + &s5pv310_device_pd[PD_TV], > }; > > static void __init smdkv310_map_io(void) > @@ -124,6 +131,8 @@ static void __init smdkv310_map_io(void) > > static void __init smdkv310_machine_init(void) > { > + samsung_pd_init(); > + > s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata); > s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata); > s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata); > diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h > index fef353d..d973d39 100644 > --- a/arch/arm/plat-s5p/include/plat/map-s5p.h > +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h > @@ -15,6 +15,7 @@ > > #define S5P_VA_CHIPID S3C_ADDR(0x02000000) > #define S5P_VA_CMU S3C_ADDR(0x02100000) > +#define S5P_VA_PMU S3C_ADDR(0x02180000) > #define S5P_VA_GPIO S3C_ADDR(0x02200000) > #define S5P_VA_GPIO1 S5P_VA_GPIO > #define S5P_VA_GPIO2 S3C_ADDR(0x02240000) > diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h > index 71bcc0f..c483480 100644 > --- a/arch/arm/plat-samsung/include/plat/devs.h > +++ b/arch/arm/plat-samsung/include/plat/devs.h > @@ -118,6 +118,8 @@ extern struct platform_device s5p_device_fimc0; > extern struct platform_device s5p_device_fimc1; > extern struct platform_device s5p_device_fimc2; > > +extern struct platform_device s5pv310_device_pd[]; > + > /* s3c2440 specific devices */ > > #ifdef CONFIG_CPU_S3C2440 > -- > 1.6.2.5 Best regards -- Marek Szyprowski Samsung Poland R&D Center -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html