* [PATCH v3 0/2] ARM: Exynos: Adapt to generic power domain
@ 2012-01-12 7:50 Thomas Abraham
2012-01-12 7:50 ` [PATCH v3 1/2] PM / Domains: Add OF support Thomas Abraham
2012-01-12 7:50 ` [PATCH v3 2/2] ARM: Exynos: Hook up power domains to generic power domain infrastructure Thomas Abraham
0 siblings, 2 replies; 4+ messages in thread
From: Thomas Abraham @ 2012-01-12 7:50 UTC (permalink / raw)
To: linux-samsung-soc, linux-pm
Cc: rjw, linux-arm-kernel, devicetree-discuss, rob.herring,
grant.likely, kgene.kim, broonie, kyungmin.park, s.nawrocki,
patches
Changes since v2:
- Added CSIS1 to cam power domain.
- Changed some of the Exynos4 prefix to Exynos.
* no changes in first patch.
Changes since v1:
- Added a OF wrapper around __pm_genpd_add_device as suggested by Rafael.
- Added cpu_relax and usleep_range during waits for power domain to be
enabled/disabled.
- Added static registrations of devices to power domains for non-dt
platforms.
The power domains available on Exynos4 are made controllable using the generic
power domain infrastructure. The Samsung specific power domain control code
for Exynos4 is removed. Support for both DT and non-DT Exynos platforms is
added.
The first patch adds device tree support for generic power domain. A device
node is added to the generic power domain strucure that represents a power
domain node in the device tree. Other device nodes in the device tree can
include a property with a phandle of the power domain node which will enable
that device to be associated with a power domain.
The second patch registers available power domains to generic power domain
framework with support for both dt and non-dt platforms. The Samsung specific
power domain control support is removed.
The patchset is based on the following tree
http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git for-next
with all patches merged from
http://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
Thomas Abraham (2):
PM / Domains: Add OF support
ARM: Exynos: Hook up power domains to generic power domain infrastructure
.../bindings/arm/exynos/power_domain.txt | 21 ++
arch/arm/mach-exynos/Kconfig | 10 +-
arch/arm/mach-exynos/Makefile | 2 +-
arch/arm/mach-exynos/dev-pd.c | 139 --------------
arch/arm/mach-exynos/mach-nuri.c | 11 -
arch/arm/mach-exynos/mach-origen.c | 14 --
arch/arm/mach-exynos/mach-smdkv310.c | 12 --
arch/arm/mach-exynos/mach-universal_c210.c | 17 --
arch/arm/mach-exynos/pm_domains.c | 195 ++++++++++++++++++++
drivers/base/power/domain.c | 32 ++++
include/linux/pm_domain.h | 12 ++
11 files changed, 262 insertions(+), 203 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/exynos/power_domain.txt
delete mode 100644 arch/arm/mach-exynos/dev-pd.c
create mode 100644 arch/arm/mach-exynos/pm_domains.c
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3 1/2] PM / Domains: Add OF support
2012-01-12 7:50 [PATCH v3 0/2] ARM: Exynos: Adapt to generic power domain Thomas Abraham
@ 2012-01-12 7:50 ` Thomas Abraham
2012-01-12 7:50 ` [PATCH v3 2/2] ARM: Exynos: Hook up power domains to generic power domain infrastructure Thomas Abraham
1 sibling, 0 replies; 4+ messages in thread
From: Thomas Abraham @ 2012-01-12 7:50 UTC (permalink / raw)
To: linux-samsung-soc, linux-pm
Cc: rjw, linux-arm-kernel, devicetree-discuss, rob.herring,
grant.likely, kgene.kim, broonie, kyungmin.park, s.nawrocki,
patches
A device node pointer is added to generic pm domain structure to associate
the domain with a node in the device tree. The platform code parses the
device tree to find available nodes representing the generic power domain,
instantiates the available domains and initializes them by calling
pm_genpd_init().
Nodes representing the devices include a phandle of the power domain to
which it belongs. As these devices get instantiated, the driver code
checkes for availability of a power domain phandle, converts the phandle
to a device node and uses the new pm_genpd_of_add_device() api to
associate the device with a power domain.
pm_genpd_of_add_device() runs through its list of registered power domains
and matches the OF node of the domain with the one specified as the
parameter. If a match is found, the device is associated with the matched
domain.
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
drivers/base/power/domain.c | 32 ++++++++++++++++++++++++++++++++
include/linux/pm_domain.h | 12 ++++++++++++
2 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 92e6a90..9ee1f7b 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1171,6 +1171,38 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
}
/**
+ * __pm_genpd_of_add_device - Add a device to an I/O PM domain.
+ * @genpd_node: Device tree node pointer representing a PM domain to which the
+ * the device is added to.
+ * @dev: Device to be added.
+ * @td: Set of PM QoS timing parameters to attach to the device.
+ */
+int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev,
+ struct gpd_timing_data *td)
+{
+ struct generic_pm_domain *genpd = NULL, *gpd;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ if (IS_ERR_OR_NULL(genpd_node) || IS_ERR_OR_NULL(dev))
+ return -EINVAL;
+
+ mutex_lock(&gpd_list_lock);
+ list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+ if (gpd->of_node == genpd_node) {
+ genpd = gpd;
+ break;
+ }
+ }
+ mutex_unlock(&gpd_list_lock);
+
+ if (!genpd)
+ return -EINVAL;
+
+ return __pm_genpd_add_device(genpd, dev, td);
+}
+
+/**
* pm_genpd_remove_device - Remove a device from an I/O PM domain.
* @genpd: PM domain to remove the device from.
* @dev: Device to be removed.
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index a03a0ad..e3ff875 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/of.h>
enum gpd_status {
GPD_STATE_ACTIVE = 0, /* PM domain is active */
@@ -70,6 +71,7 @@ struct generic_pm_domain {
s64 break_even_ns; /* Power break even for the entire domain. */
s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
ktime_t power_off_time;
+ struct device_node *of_node; /* Node in device tree */
};
static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
@@ -117,12 +119,22 @@ extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
struct device *dev,
struct gpd_timing_data *td);
+extern int __pm_genpd_of_add_device(struct device_node *genpd_node,
+ struct device *dev,
+ struct gpd_timing_data *td);
+
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
struct device *dev)
{
return __pm_genpd_add_device(genpd, dev, NULL);
}
+static inline int pm_genpd_of_add_device(struct device_node *genpd_node,
+ struct device *dev)
+{
+ return __pm_genpd_of_add_device(genpd_node, dev, NULL);
+}
+
extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev);
extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] ARM: Exynos: Hook up power domains to generic power domain infrastructure
2012-01-12 7:50 [PATCH v3 0/2] ARM: Exynos: Adapt to generic power domain Thomas Abraham
2012-01-12 7:50 ` [PATCH v3 1/2] PM / Domains: Add OF support Thomas Abraham
@ 2012-01-12 7:50 ` Thomas Abraham
2012-01-16 21:10 ` Rafael J. Wysocki
1 sibling, 1 reply; 4+ messages in thread
From: Thomas Abraham @ 2012-01-12 7:50 UTC (permalink / raw)
To: linux-samsung-soc, linux-pm
Cc: rjw, linux-arm-kernel, devicetree-discuss, rob.herring,
grant.likely, kgene.kim, broonie, kyungmin.park, s.nawrocki,
patches
Add support for generic power domain for Exynos4 platforms and remove the
Samsung specific power domain control for Exynos4.
The generic power domain infrastructure is used to control the power domains
available on Exynos4. For non-dt platforms, the power domains are statically
instantiated. For dt platforms, the power domain nodes found in the device
tree are instantiated.
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
.../bindings/arm/exynos/power_domain.txt | 21 ++
arch/arm/mach-exynos/Kconfig | 10 +-
arch/arm/mach-exynos/Makefile | 2 +-
arch/arm/mach-exynos/dev-pd.c | 139 --------------
arch/arm/mach-exynos/mach-nuri.c | 11 -
arch/arm/mach-exynos/mach-origen.c | 14 --
arch/arm/mach-exynos/mach-smdkv310.c | 12 --
arch/arm/mach-exynos/mach-universal_c210.c | 17 --
arch/arm/mach-exynos/pm_domains.c | 195 ++++++++++++++++++++
9 files changed, 218 insertions(+), 203 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/exynos/power_domain.txt
delete mode 100644 arch/arm/mach-exynos/dev-pd.c
create mode 100644 arch/arm/mach-exynos/pm_domains.c
diff --git a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
new file mode 100644
index 0000000..6528e21
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
@@ -0,0 +1,21 @@
+* Samsung Exynos Power Domains
+
+Exynos processors include support for multiple power domains which are used
+to gate power to one or more peripherals on the processor.
+
+Required Properties:
+- compatiable: should be one of the following.
+ * samsung,exynos4210-pd - for exynos4210 type power domain.
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+Optional Properties:
+- samsung,exynos4210-pd-off: Specifies that the power domain is in turned-off
+ state during boot and remains to be turned-off until explicitly turned-on.
+
+Example:
+
+ lcd0: power-domain-lcd0 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C00 0x10>;
+ };
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index e931924..5dec134 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -32,6 +32,7 @@ config CPU_EXYNOS4210
select ARM_CPU_SUSPEND if PM
select S5P_PM if PM
select S5P_SLEEP if PM
+ select PM_GENERIC_DOMAINS
help
Enable EXYNOS4210 CPU support
@@ -72,11 +73,6 @@ config EXYNOS4_SETUP_FIMD0
help
Common setup code for FIMD0.
-config EXYNOS4_DEV_PD
- bool
- help
- Compile in platform device definitions for Power Domain
-
config EXYNOS4_DEV_SYSMMU
bool
help
@@ -194,7 +190,6 @@ config MACH_SMDKV310
select EXYNOS4_DEV_AHCI
select SAMSUNG_DEV_KEYPAD
select EXYNOS4_DEV_DMA
- select EXYNOS4_DEV_PD
select SAMSUNG_DEV_PWM
select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_DEV_SYSMMU
@@ -243,7 +238,6 @@ config MACH_UNIVERSAL_C210
select S5P_DEV_ONENAND
select S5P_DEV_TV
select EXYNOS4_DEV_DMA
- select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3
@@ -277,7 +271,6 @@ config MACH_NURI
select S5P_DEV_USB_EHCI
select S5P_SETUP_MIPIPHY
select EXYNOS4_DEV_DMA
- select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_FIMC
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
@@ -310,7 +303,6 @@ config MACH_ORIGEN
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
select EXYNOS4_DEV_DMA
- select EXYNOS4_DEV_PD
select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_SDHCI
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index db527ab..b7e4eca 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_EXYNOS4) += irq-eint.o pmu.o
obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o
obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o
obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
@@ -43,7 +44,6 @@ obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o
obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
-obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o
diff --git a/arch/arm/mach-exynos/dev-pd.c b/arch/arm/mach-exynos/dev-pd.c
deleted file mode 100644
index 3273f25..0000000
--- a/arch/arm/mach-exynos/dev-pd.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dev-pd.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4 - 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 exynos4_pd_enable(struct device *dev)
-{
- struct samsung_pd_info *pdata = dev->platform_data;
- u32 timeout;
-
- __raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
-
- /* Wait max 1ms */
- timeout = 10;
- while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
- != S5P_INT_LOCAL_PWR_EN) {
- if (timeout == 0) {
- printk(KERN_ERR "Power domain %s enable failed.\n",
- dev_name(dev));
- return -ETIMEDOUT;
- }
- timeout--;
- udelay(100);
- }
-
- return 0;
-}
-
-static int exynos4_pd_disable(struct device *dev)
-{
- struct samsung_pd_info *pdata = dev->platform_data;
- u32 timeout;
-
- __raw_writel(0, pdata->base);
-
- /* Wait max 1ms */
- timeout = 10;
- while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
- if (timeout == 0) {
- printk(KERN_ERR "Power domain %s disable failed.\n",
- dev_name(dev));
- return -ETIMEDOUT;
- }
- timeout--;
- udelay(100);
- }
-
- return 0;
-}
-
-struct platform_device exynos4_device_pd[] = {
- {
- .name = "samsung-pd",
- .id = 0,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_MFC_CONF,
- },
- },
- }, {
- .name = "samsung-pd",
- .id = 1,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_G3D_CONF,
- },
- },
- }, {
- .name = "samsung-pd",
- .id = 2,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_LCD0_CONF,
- },
- },
- }, {
- .name = "samsung-pd",
- .id = 3,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_LCD1_CONF,
- },
- },
- }, {
- .name = "samsung-pd",
- .id = 4,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_TV_CONF,
- },
- },
- }, {
- .name = "samsung-pd",
- .id = 5,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_CAM_CONF,
- },
- },
- }, {
- .name = "samsung-pd",
- .id = 6,
- .dev = {
- .platform_data = &(struct samsung_pd_info) {
- .enable = exynos4_pd_enable,
- .disable = exynos4_pd_disable,
- .base = S5P_PMU_GPS_CONF,
- },
- },
- },
-};
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 3df8bf4..179a992 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1266,9 +1266,6 @@ static struct platform_device *nuri_devices[] __initdata = {
&s5p_device_mfc,
&s5p_device_mfc_l,
&s5p_device_mfc_r,
- &exynos4_device_pd[PD_MFC],
- &exynos4_device_pd[PD_LCD0],
- &exynos4_device_pd[PD_CAM],
&s5p_device_fimc_md,
/* NURI Devices */
@@ -1319,14 +1316,6 @@ static void __init nuri_machine_init(void)
/* Last */
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
- s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
- s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
-
- s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
}
MACHINE_START(NURI, "NURI")
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 23fc5cb..da871b9 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -639,13 +639,6 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_mfc_r,
&s5p_device_mixer,
&exynos4_device_ohci,
- &exynos4_device_pd[PD_LCD0],
- &exynos4_device_pd[PD_TV],
- &exynos4_device_pd[PD_G3D],
- &exynos4_device_pd[PD_LCD1],
- &exynos4_device_pd[PD_CAM],
- &exynos4_device_pd[PD_GPS],
- &exynos4_device_pd[PD_MFC],
&origen_device_gpiokeys,
&origen_lcd_hv070wsa,
&origen_device_bluetooth,
@@ -724,13 +717,6 @@ static void __init origen_machine_init(void)
platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
- s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
-
- s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
- s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
-
- s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
-
samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
origen_bt_setup();
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index bf2094e..88d1a30 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -275,13 +275,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&s5p_device_mfc,
&s5p_device_mfc_l,
&s5p_device_mfc_r,
- &exynos4_device_pd[PD_MFC],
- &exynos4_device_pd[PD_G3D],
- &exynos4_device_pd[PD_LCD0],
- &exynos4_device_pd[PD_LCD1],
- &exynos4_device_pd[PD_CAM],
- &exynos4_device_pd[PD_TV],
- &exynos4_device_pd[PD_GPS],
&exynos4_device_spdif,
&exynos4_device_sysmmu,
&samsung_asoc_dma,
@@ -334,10 +327,6 @@ static void s5p_tv_setup(void)
WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
-
- /* setup dependencies between TV devices */
- s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
- s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
}
static void __init smdkv310_map_io(void)
@@ -377,7 +366,6 @@ static void __init smdkv310_machine_init(void)
clk_xusbxti.rate = 24000000;
platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
- s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
}
MACHINE_START(SMDKV310, "SMDKV310")
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index c38e18d..28d8f02 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -968,7 +968,6 @@ static struct platform_device *universal_devices[] __initdata = {
&s3c_device_i2c5,
&s5p_device_i2c_hdmiphy,
&hdmi_fixed_voltage,
- &exynos4_device_pd[PD_TV],
&s5p_device_hdmi,
&s5p_device_sdo,
&s5p_device_mixer,
@@ -981,9 +980,6 @@ static struct platform_device *universal_devices[] __initdata = {
&s5p_device_mfc,
&s5p_device_mfc_l,
&s5p_device_mfc_r,
- &exynos4_device_pd[PD_MFC],
- &exynos4_device_pd[PD_LCD0],
- &exynos4_device_pd[PD_CAM],
&cam_i_core_fixed_reg_dev,
&cam_s_if_fixed_reg_dev,
&s5p_device_fimc_md,
@@ -1002,10 +998,6 @@ void s5p_tv_setup(void)
gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
-
- /* setup dependencies between TV devices */
- s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
- s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
}
static void __init universal_reserve(void)
@@ -1039,15 +1031,6 @@ static void __init universal_machine_init(void)
/* Last */
platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
-
- s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
- s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
-
- s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
- s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
}
MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
new file mode 100644
index 0000000..f81c3c7
--- /dev/null
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -0,0 +1,195 @@
+/*
+ * Exynos Generic power domain support.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Implementation of Exynos specific power domain control which is used in
+ * conjunction with runtime-pm. Support for both device-tree and non-device-tree
+ * based power domain support is included.
+ *
+ * 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/err.h>
+#include <linux/slab.h>
+#include <linux/pm_domain.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+
+#include <mach/regs-pmu.h>
+#include <plat/devs.h>
+
+/*
+ * Exynos specific wrapper around the generic power domain
+ */
+struct exynos_pm_domain {
+ void __iomem *base;
+ char const *name;
+ bool is_off;
+ struct generic_pm_domain pd;
+};
+
+static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+ struct exynos_pm_domain *pd;
+ void __iomem *base;
+ u32 timeout, pwr;
+ char *op;
+
+ pd = container_of(domain, struct exynos_pm_domain, pd);
+ base = pd->base;
+
+ pwr = power_on ? S5P_INT_LOCAL_PWR_EN : 0;
+ __raw_writel(pwr, base);
+
+ /* Wait max 1ms */
+ timeout = 10;
+
+ while ((__raw_readl(base + 0x4) & S5P_INT_LOCAL_PWR_EN) != pwr) {
+ if (!timeout) {
+ op = (power_on) ? "enable" : "disable";
+ pr_err("Power domain %s %s failed\n", domain->name, op);
+ return -ETIMEDOUT;
+ }
+ timeout--;
+ cpu_relax();
+ usleep_range(80, 100);
+ }
+ return 0;
+}
+
+static int exynos_pd_power_on(struct generic_pm_domain *domain)
+{
+ return exynos_pd_power(domain, true);
+}
+
+static int exynos_pd_power_off(struct generic_pm_domain *domain)
+{
+ return exynos_pd_power(domain, false);
+}
+
+#define EXYNOS_GPD(PD, BASE, NAME) \
+static struct exynos_pm_domain PD = { \
+ .base = (void __iomem *)BASE, \
+ .name = NAME, \
+ .pd = { \
+ .power_off = exynos_pd_power_off, \
+ .power_on = exynos_pd_power_on, \
+ }, \
+}
+
+#ifdef CONFIG_OF
+static __init int exynos_pm_dt_parse_domains(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
+ struct exynos_pm_domain *pd;
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ pr_err("%s: failed to allocate memory for domain\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (of_get_property(np, "samsung,exynos4210-pd-off", NULL))
+ pd->is_off = true;
+ pd->name = np->name;
+ pd->base = of_iomap(np, 0);
+ pd->pd.power_off = exynos_pd_power_off;
+ pd->pd.power_on = exynos_pd_power_on;
+ pd->pd.of_node = np;
+ pm_genpd_init(&pd->pd, NULL, false);
+ }
+ return 0;
+}
+#else
+static __init int exynos_pm_dt_parse_domains(void)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev,
+ struct exynos_pm_domain *pd)
+{
+ if (pdev->dev.bus) {
+ if (pm_genpd_add_device(&pd->pd, &pdev->dev))
+ pr_info("%s: error in adding %s device to %s power"
+ "domain\n", __func__, dev_name(&pdev->dev),
+ pd->name);
+ }
+}
+
+EXYNOS_GPD(exynos4_pd_mfc, S5P_PMU_MFC_CONF, "pd-mfc");
+EXYNOS_GPD(exynos4_pd_g3d, S5P_PMU_G3D_CONF, "pd-g3d");
+EXYNOS_GPD(exynos4_pd_lcd0, S5P_PMU_LCD0_CONF, "pd-lcd0");
+EXYNOS_GPD(exynos4_pd_lcd1, S5P_PMU_LCD1_CONF, "pd-lcd1");
+EXYNOS_GPD(exynos4_pd_tv, S5P_PMU_TV_CONF, "pd-tv");
+EXYNOS_GPD(exynos4_pd_cam, S5P_PMU_CAM_CONF, "pd-cam");
+EXYNOS_GPD(exynos4_pd_gps, S5P_PMU_GPS_CONF, "pd-gps");
+
+static struct exynos_pm_domain *exynos4_pm_domains[] = {
+ &exynos4_pd_mfc,
+ &exynos4_pd_g3d,
+ &exynos4_pd_lcd0,
+ &exynos4_pd_lcd1,
+ &exynos4_pd_tv,
+ &exynos4_pd_cam,
+ &exynos4_pd_gps,
+};
+
+static __init int exynos4_pm_init_power_domain(void)
+{
+ int idx;
+
+ if (of_have_populated_dt())
+ return exynos_pm_dt_parse_domains();
+
+ for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++)
+ pm_genpd_init(&exynos4_pm_domains[idx]->pd, NULL,
+ exynos4_pm_domains[idx]->is_off);
+
+#ifdef CONFIG_S5P_DEV_FIMD0
+ exynos_pm_add_dev_to_genpd(&s5p_device_fimd0, &exynos4_pd_lcd0);
+#endif
+#ifdef CONFIG_S5P_DEV_TV
+ exynos_pm_add_dev_to_genpd(&s5p_device_hdmi, &exynos4_pd_tv);
+ exynos_pm_add_dev_to_genpd(&s5p_device_mixer, &exynos4_pd_tv);
+#endif
+#ifdef CONFIG_S5P_DEV_MFC
+ exynos_pm_add_dev_to_genpd(&s5p_device_mfc, &exynos4_pd_mfc);
+#endif
+#ifdef CONFIG_S5P_DEV_FIMC0
+ exynos_pm_add_dev_to_genpd(&s5p_device_fimc0, &exynos4_pd_cam);
+#endif
+#ifdef CONFIG_S5P_DEV_FIMC1
+ exynos_pm_add_dev_to_genpd(&s5p_device_fimc1, &exynos4_pd_cam);
+#endif
+#ifdef CONFIG_S5P_DEV_FIMC2
+ exynos_pm_add_dev_to_genpd(&s5p_device_fimc2, &exynos4_pd_cam);
+#endif
+#ifdef CONFIG_S5P_DEV_FIMC3
+ exynos_pm_add_dev_to_genpd(&s5p_device_fimc3, &exynos4_pd_cam);
+#endif
+#ifdef CONFIG_S5P_DEV_CSIS0
+ exynos_pm_add_dev_to_genpd(&s5p_device_mipi_csis0, &exynos4_pd_cam);
+#endif
+#ifdef CONFIG_S5P_DEV_CSIS1
+ exynos_pm_add_dev_to_genpd(&s5p_device_mipi_csis1, &exynos4_pd_cam);
+#endif
+ return 0;
+}
+arch_initcall(exynos4_pm_init_power_domain);
+
+static __init int exynos_pm_late_initcall(void)
+{
+ pm_genpd_poweroff_unused();
+ return 0;
+}
+late_initcall(exynos_pm_late_initcall);
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 2/2] ARM: Exynos: Hook up power domains to generic power domain infrastructure
2012-01-12 7:50 ` [PATCH v3 2/2] ARM: Exynos: Hook up power domains to generic power domain infrastructure Thomas Abraham
@ 2012-01-16 21:10 ` Rafael J. Wysocki
0 siblings, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2012-01-16 21:10 UTC (permalink / raw)
To: Thomas Abraham
Cc: linux-samsung-soc, linux-pm, linux-arm-kernel, devicetree-discuss,
rob.herring, grant.likely, kgene.kim, broonie, kyungmin.park,
s.nawrocki, patches
On Thursday, January 12, 2012, Thomas Abraham wrote:
> Add support for generic power domain for Exynos4 platforms and remove the
> Samsung specific power domain control for Exynos4.
>
> The generic power domain infrastructure is used to control the power domains
> available on Exynos4. For non-dt platforms, the power domains are statically
> instantiated. For dt platforms, the power domain nodes found in the device
> tree are instantiated.
>
> Cc: Rafael J. Wysocki <rjw@sisk.pl>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
As I said before, I'm going to take patch [1/2] from this series for v3.4,
but I need an ACK from the Exynos maintainers for [2/2].
Thanks,
Rafael
> ---
> .../bindings/arm/exynos/power_domain.txt | 21 ++
> arch/arm/mach-exynos/Kconfig | 10 +-
> arch/arm/mach-exynos/Makefile | 2 +-
> arch/arm/mach-exynos/dev-pd.c | 139 --------------
> arch/arm/mach-exynos/mach-nuri.c | 11 -
> arch/arm/mach-exynos/mach-origen.c | 14 --
> arch/arm/mach-exynos/mach-smdkv310.c | 12 --
> arch/arm/mach-exynos/mach-universal_c210.c | 17 --
> arch/arm/mach-exynos/pm_domains.c | 195 ++++++++++++++++++++
> 9 files changed, 218 insertions(+), 203 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/exynos/power_domain.txt
> delete mode 100644 arch/arm/mach-exynos/dev-pd.c
> create mode 100644 arch/arm/mach-exynos/pm_domains.c
>
> diff --git a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
> new file mode 100644
> index 0000000..6528e21
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
> @@ -0,0 +1,21 @@
> +* Samsung Exynos Power Domains
> +
> +Exynos processors include support for multiple power domains which are used
> +to gate power to one or more peripherals on the processor.
> +
> +Required Properties:
> +- compatiable: should be one of the following.
> + * samsung,exynos4210-pd - for exynos4210 type power domain.
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +
> +Optional Properties:
> +- samsung,exynos4210-pd-off: Specifies that the power domain is in turned-off
> + state during boot and remains to be turned-off until explicitly turned-on.
> +
> +Example:
> +
> + lcd0: power-domain-lcd0 {
> + compatible = "samsung,exynos4210-pd";
> + reg = <0x10023C00 0x10>;
> + };
> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
> index e931924..5dec134 100644
> --- a/arch/arm/mach-exynos/Kconfig
> +++ b/arch/arm/mach-exynos/Kconfig
> @@ -32,6 +32,7 @@ config CPU_EXYNOS4210
> select ARM_CPU_SUSPEND if PM
> select S5P_PM if PM
> select S5P_SLEEP if PM
> + select PM_GENERIC_DOMAINS
> help
> Enable EXYNOS4210 CPU support
>
> @@ -72,11 +73,6 @@ config EXYNOS4_SETUP_FIMD0
> help
> Common setup code for FIMD0.
>
> -config EXYNOS4_DEV_PD
> - bool
> - help
> - Compile in platform device definitions for Power Domain
> -
> config EXYNOS4_DEV_SYSMMU
> bool
> help
> @@ -194,7 +190,6 @@ config MACH_SMDKV310
> select EXYNOS4_DEV_AHCI
> select SAMSUNG_DEV_KEYPAD
> select EXYNOS4_DEV_DMA
> - select EXYNOS4_DEV_PD
> select SAMSUNG_DEV_PWM
> select EXYNOS4_DEV_USB_OHCI
> select EXYNOS4_DEV_SYSMMU
> @@ -243,7 +238,6 @@ config MACH_UNIVERSAL_C210
> select S5P_DEV_ONENAND
> select S5P_DEV_TV
> select EXYNOS4_DEV_DMA
> - select EXYNOS4_DEV_PD
> select EXYNOS4_SETUP_FIMD0
> select EXYNOS4_SETUP_I2C1
> select EXYNOS4_SETUP_I2C3
> @@ -277,7 +271,6 @@ config MACH_NURI
> select S5P_DEV_USB_EHCI
> select S5P_SETUP_MIPIPHY
> select EXYNOS4_DEV_DMA
> - select EXYNOS4_DEV_PD
> select EXYNOS4_SETUP_FIMC
> select EXYNOS4_SETUP_FIMD0
> select EXYNOS4_SETUP_I2C1
> @@ -310,7 +303,6 @@ config MACH_ORIGEN
> select SAMSUNG_DEV_BACKLIGHT
> select SAMSUNG_DEV_PWM
> select EXYNOS4_DEV_DMA
> - select EXYNOS4_DEV_PD
> select EXYNOS4_DEV_USB_OHCI
> select EXYNOS4_SETUP_FIMD0
> select EXYNOS4_SETUP_SDHCI
> diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
> index db527ab..b7e4eca 100644
> --- a/arch/arm/mach-exynos/Makefile
> +++ b/arch/arm/mach-exynos/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_EXYNOS4) += irq-eint.o pmu.o
> obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o
> obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o
> obj-$(CONFIG_PM) += pm.o
> +obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
> obj-$(CONFIG_CPU_IDLE) += cpuidle.o
>
> obj-$(CONFIG_SMP) += platsmp.o headsmp.o
> @@ -43,7 +44,6 @@ obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
>
> obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o
> obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
> -obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
> obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
> obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
> obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o
> diff --git a/arch/arm/mach-exynos/dev-pd.c b/arch/arm/mach-exynos/dev-pd.c
> deleted file mode 100644
> index 3273f25..0000000
> --- a/arch/arm/mach-exynos/dev-pd.c
> +++ /dev/null
> @@ -1,139 +0,0 @@
> -/* linux/arch/arm/mach-exynos4/dev-pd.c
> - *
> - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
> - * http://www.samsung.com
> - *
> - * EXYNOS4 - 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 exynos4_pd_enable(struct device *dev)
> -{
> - struct samsung_pd_info *pdata = dev->platform_data;
> - u32 timeout;
> -
> - __raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
> -
> - /* Wait max 1ms */
> - timeout = 10;
> - while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
> - != S5P_INT_LOCAL_PWR_EN) {
> - if (timeout == 0) {
> - printk(KERN_ERR "Power domain %s enable failed.\n",
> - dev_name(dev));
> - return -ETIMEDOUT;
> - }
> - timeout--;
> - udelay(100);
> - }
> -
> - return 0;
> -}
> -
> -static int exynos4_pd_disable(struct device *dev)
> -{
> - struct samsung_pd_info *pdata = dev->platform_data;
> - u32 timeout;
> -
> - __raw_writel(0, pdata->base);
> -
> - /* Wait max 1ms */
> - timeout = 10;
> - while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
> - if (timeout == 0) {
> - printk(KERN_ERR "Power domain %s disable failed.\n",
> - dev_name(dev));
> - return -ETIMEDOUT;
> - }
> - timeout--;
> - udelay(100);
> - }
> -
> - return 0;
> -}
> -
> -struct platform_device exynos4_device_pd[] = {
> - {
> - .name = "samsung-pd",
> - .id = 0,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_MFC_CONF,
> - },
> - },
> - }, {
> - .name = "samsung-pd",
> - .id = 1,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_G3D_CONF,
> - },
> - },
> - }, {
> - .name = "samsung-pd",
> - .id = 2,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_LCD0_CONF,
> - },
> - },
> - }, {
> - .name = "samsung-pd",
> - .id = 3,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_LCD1_CONF,
> - },
> - },
> - }, {
> - .name = "samsung-pd",
> - .id = 4,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_TV_CONF,
> - },
> - },
> - }, {
> - .name = "samsung-pd",
> - .id = 5,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_CAM_CONF,
> - },
> - },
> - }, {
> - .name = "samsung-pd",
> - .id = 6,
> - .dev = {
> - .platform_data = &(struct samsung_pd_info) {
> - .enable = exynos4_pd_enable,
> - .disable = exynos4_pd_disable,
> - .base = S5P_PMU_GPS_CONF,
> - },
> - },
> - },
> -};
> diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
> index 3df8bf4..179a992 100644
> --- a/arch/arm/mach-exynos/mach-nuri.c
> +++ b/arch/arm/mach-exynos/mach-nuri.c
> @@ -1266,9 +1266,6 @@ static struct platform_device *nuri_devices[] __initdata = {
> &s5p_device_mfc,
> &s5p_device_mfc_l,
> &s5p_device_mfc_r,
> - &exynos4_device_pd[PD_MFC],
> - &exynos4_device_pd[PD_LCD0],
> - &exynos4_device_pd[PD_CAM],
> &s5p_device_fimc_md,
>
> /* NURI Devices */
> @@ -1319,14 +1316,6 @@ static void __init nuri_machine_init(void)
>
> /* Last */
> platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
> - s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
> - s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
> -
> - s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> }
>
> MACHINE_START(NURI, "NURI")
> diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
> index 23fc5cb..da871b9 100644
> --- a/arch/arm/mach-exynos/mach-origen.c
> +++ b/arch/arm/mach-exynos/mach-origen.c
> @@ -639,13 +639,6 @@ static struct platform_device *origen_devices[] __initdata = {
> &s5p_device_mfc_r,
> &s5p_device_mixer,
> &exynos4_device_ohci,
> - &exynos4_device_pd[PD_LCD0],
> - &exynos4_device_pd[PD_TV],
> - &exynos4_device_pd[PD_G3D],
> - &exynos4_device_pd[PD_LCD1],
> - &exynos4_device_pd[PD_CAM],
> - &exynos4_device_pd[PD_GPS],
> - &exynos4_device_pd[PD_MFC],
> &origen_device_gpiokeys,
> &origen_lcd_hv070wsa,
> &origen_device_bluetooth,
> @@ -724,13 +717,6 @@ static void __init origen_machine_init(void)
>
> platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
>
> - s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
> -
> - s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
> - s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
> -
> - s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
> -
> samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
>
> origen_bt_setup();
> diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
> index bf2094e..88d1a30 100644
> --- a/arch/arm/mach-exynos/mach-smdkv310.c
> +++ b/arch/arm/mach-exynos/mach-smdkv310.c
> @@ -275,13 +275,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
> &s5p_device_mfc,
> &s5p_device_mfc_l,
> &s5p_device_mfc_r,
> - &exynos4_device_pd[PD_MFC],
> - &exynos4_device_pd[PD_G3D],
> - &exynos4_device_pd[PD_LCD0],
> - &exynos4_device_pd[PD_LCD1],
> - &exynos4_device_pd[PD_CAM],
> - &exynos4_device_pd[PD_TV],
> - &exynos4_device_pd[PD_GPS],
> &exynos4_device_spdif,
> &exynos4_device_sysmmu,
> &samsung_asoc_dma,
> @@ -334,10 +327,6 @@ static void s5p_tv_setup(void)
> WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
> s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
> s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
> -
> - /* setup dependencies between TV devices */
> - s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
> - s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
> }
>
> static void __init smdkv310_map_io(void)
> @@ -377,7 +366,6 @@ static void __init smdkv310_machine_init(void)
> clk_xusbxti.rate = 24000000;
>
> platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
> - s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
> }
>
> MACHINE_START(SMDKV310, "SMDKV310")
> diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
> index c38e18d..28d8f02 100644
> --- a/arch/arm/mach-exynos/mach-universal_c210.c
> +++ b/arch/arm/mach-exynos/mach-universal_c210.c
> @@ -968,7 +968,6 @@ static struct platform_device *universal_devices[] __initdata = {
> &s3c_device_i2c5,
> &s5p_device_i2c_hdmiphy,
> &hdmi_fixed_voltage,
> - &exynos4_device_pd[PD_TV],
> &s5p_device_hdmi,
> &s5p_device_sdo,
> &s5p_device_mixer,
> @@ -981,9 +980,6 @@ static struct platform_device *universal_devices[] __initdata = {
> &s5p_device_mfc,
> &s5p_device_mfc_l,
> &s5p_device_mfc_r,
> - &exynos4_device_pd[PD_MFC],
> - &exynos4_device_pd[PD_LCD0],
> - &exynos4_device_pd[PD_CAM],
> &cam_i_core_fixed_reg_dev,
> &cam_s_if_fixed_reg_dev,
> &s5p_device_fimc_md,
> @@ -1002,10 +998,6 @@ void s5p_tv_setup(void)
> gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
> s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
> s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
> -
> - /* setup dependencies between TV devices */
> - s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
> - s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
> }
>
> static void __init universal_reserve(void)
> @@ -1039,15 +1031,6 @@ static void __init universal_machine_init(void)
>
> /* Last */
> platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
> -
> - s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
> - s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
> -
> - s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> - s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
> }
>
> MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
> diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
> new file mode 100644
> index 0000000..f81c3c7
> --- /dev/null
> +++ b/arch/arm/mach-exynos/pm_domains.c
> @@ -0,0 +1,195 @@
> +/*
> + * Exynos Generic power domain support.
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * Implementation of Exynos specific power domain control which is used in
> + * conjunction with runtime-pm. Support for both device-tree and non-device-tree
> + * based power domain support is included.
> + *
> + * 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/err.h>
> +#include <linux/slab.h>
> +#include <linux/pm_domain.h>
> +#include <linux/delay.h>
> +#include <linux/of_address.h>
> +
> +#include <mach/regs-pmu.h>
> +#include <plat/devs.h>
> +
> +/*
> + * Exynos specific wrapper around the generic power domain
> + */
> +struct exynos_pm_domain {
> + void __iomem *base;
> + char const *name;
> + bool is_off;
> + struct generic_pm_domain pd;
> +};
> +
> +static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
> +{
> + struct exynos_pm_domain *pd;
> + void __iomem *base;
> + u32 timeout, pwr;
> + char *op;
> +
> + pd = container_of(domain, struct exynos_pm_domain, pd);
> + base = pd->base;
> +
> + pwr = power_on ? S5P_INT_LOCAL_PWR_EN : 0;
> + __raw_writel(pwr, base);
> +
> + /* Wait max 1ms */
> + timeout = 10;
> +
> + while ((__raw_readl(base + 0x4) & S5P_INT_LOCAL_PWR_EN) != pwr) {
> + if (!timeout) {
> + op = (power_on) ? "enable" : "disable";
> + pr_err("Power domain %s %s failed\n", domain->name, op);
> + return -ETIMEDOUT;
> + }
> + timeout--;
> + cpu_relax();
> + usleep_range(80, 100);
> + }
> + return 0;
> +}
> +
> +static int exynos_pd_power_on(struct generic_pm_domain *domain)
> +{
> + return exynos_pd_power(domain, true);
> +}
> +
> +static int exynos_pd_power_off(struct generic_pm_domain *domain)
> +{
> + return exynos_pd_power(domain, false);
> +}
> +
> +#define EXYNOS_GPD(PD, BASE, NAME) \
> +static struct exynos_pm_domain PD = { \
> + .base = (void __iomem *)BASE, \
> + .name = NAME, \
> + .pd = { \
> + .power_off = exynos_pd_power_off, \
> + .power_on = exynos_pd_power_on, \
> + }, \
> +}
> +
> +#ifdef CONFIG_OF
> +static __init int exynos_pm_dt_parse_domains(void)
> +{
> + struct device_node *np;
> +
> + for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
> + struct exynos_pm_domain *pd;
> +
> + pd = kzalloc(sizeof(*pd), GFP_KERNEL);
> + if (!pd) {
> + pr_err("%s: failed to allocate memory for domain\n",
> + __func__);
> + return -ENOMEM;
> + }
> +
> + if (of_get_property(np, "samsung,exynos4210-pd-off", NULL))
> + pd->is_off = true;
> + pd->name = np->name;
> + pd->base = of_iomap(np, 0);
> + pd->pd.power_off = exynos_pd_power_off;
> + pd->pd.power_on = exynos_pd_power_on;
> + pd->pd.of_node = np;
> + pm_genpd_init(&pd->pd, NULL, false);
> + }
> + return 0;
> +}
> +#else
> +static __init int exynos_pm_dt_parse_domains(void)
> +{
> + return 0;
> +}
> +#endif /* CONFIG_OF */
> +
> +static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev,
> + struct exynos_pm_domain *pd)
> +{
> + if (pdev->dev.bus) {
> + if (pm_genpd_add_device(&pd->pd, &pdev->dev))
> + pr_info("%s: error in adding %s device to %s power"
> + "domain\n", __func__, dev_name(&pdev->dev),
> + pd->name);
> + }
> +}
> +
> +EXYNOS_GPD(exynos4_pd_mfc, S5P_PMU_MFC_CONF, "pd-mfc");
> +EXYNOS_GPD(exynos4_pd_g3d, S5P_PMU_G3D_CONF, "pd-g3d");
> +EXYNOS_GPD(exynos4_pd_lcd0, S5P_PMU_LCD0_CONF, "pd-lcd0");
> +EXYNOS_GPD(exynos4_pd_lcd1, S5P_PMU_LCD1_CONF, "pd-lcd1");
> +EXYNOS_GPD(exynos4_pd_tv, S5P_PMU_TV_CONF, "pd-tv");
> +EXYNOS_GPD(exynos4_pd_cam, S5P_PMU_CAM_CONF, "pd-cam");
> +EXYNOS_GPD(exynos4_pd_gps, S5P_PMU_GPS_CONF, "pd-gps");
> +
> +static struct exynos_pm_domain *exynos4_pm_domains[] = {
> + &exynos4_pd_mfc,
> + &exynos4_pd_g3d,
> + &exynos4_pd_lcd0,
> + &exynos4_pd_lcd1,
> + &exynos4_pd_tv,
> + &exynos4_pd_cam,
> + &exynos4_pd_gps,
> +};
> +
> +static __init int exynos4_pm_init_power_domain(void)
> +{
> + int idx;
> +
> + if (of_have_populated_dt())
> + return exynos_pm_dt_parse_domains();
> +
> + for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++)
> + pm_genpd_init(&exynos4_pm_domains[idx]->pd, NULL,
> + exynos4_pm_domains[idx]->is_off);
> +
> +#ifdef CONFIG_S5P_DEV_FIMD0
> + exynos_pm_add_dev_to_genpd(&s5p_device_fimd0, &exynos4_pd_lcd0);
> +#endif
> +#ifdef CONFIG_S5P_DEV_TV
> + exynos_pm_add_dev_to_genpd(&s5p_device_hdmi, &exynos4_pd_tv);
> + exynos_pm_add_dev_to_genpd(&s5p_device_mixer, &exynos4_pd_tv);
> +#endif
> +#ifdef CONFIG_S5P_DEV_MFC
> + exynos_pm_add_dev_to_genpd(&s5p_device_mfc, &exynos4_pd_mfc);
> +#endif
> +#ifdef CONFIG_S5P_DEV_FIMC0
> + exynos_pm_add_dev_to_genpd(&s5p_device_fimc0, &exynos4_pd_cam);
> +#endif
> +#ifdef CONFIG_S5P_DEV_FIMC1
> + exynos_pm_add_dev_to_genpd(&s5p_device_fimc1, &exynos4_pd_cam);
> +#endif
> +#ifdef CONFIG_S5P_DEV_FIMC2
> + exynos_pm_add_dev_to_genpd(&s5p_device_fimc2, &exynos4_pd_cam);
> +#endif
> +#ifdef CONFIG_S5P_DEV_FIMC3
> + exynos_pm_add_dev_to_genpd(&s5p_device_fimc3, &exynos4_pd_cam);
> +#endif
> +#ifdef CONFIG_S5P_DEV_CSIS0
> + exynos_pm_add_dev_to_genpd(&s5p_device_mipi_csis0, &exynos4_pd_cam);
> +#endif
> +#ifdef CONFIG_S5P_DEV_CSIS1
> + exynos_pm_add_dev_to_genpd(&s5p_device_mipi_csis1, &exynos4_pd_cam);
> +#endif
> + return 0;
> +}
> +arch_initcall(exynos4_pm_init_power_domain);
> +
> +static __init int exynos_pm_late_initcall(void)
> +{
> + pm_genpd_poweroff_unused();
> + return 0;
> +}
> +late_initcall(exynos_pm_late_initcall);
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-01-16 21:10 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-12 7:50 [PATCH v3 0/2] ARM: Exynos: Adapt to generic power domain Thomas Abraham
2012-01-12 7:50 ` [PATCH v3 1/2] PM / Domains: Add OF support Thomas Abraham
2012-01-12 7:50 ` [PATCH v3 2/2] ARM: Exynos: Hook up power domains to generic power domain infrastructure Thomas Abraham
2012-01-16 21:10 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).