SUPERH platform development
 help / color / mirror / Atom feed
* [PATCH 2/7] ARM: shmobile: r8a7740: add basic pm domain support
@ 2012-07-04  3:55 Kuninori Morimoto
  2012-07-04 10:45 ` Paul Mundt
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Kuninori Morimoto @ 2012-07-04  3:55 UTC (permalink / raw)
  To: linux-sh

PM domain specification between sh7372 and r8a7740 was very similar.
This patch adds basic PM domain support for r8a7740 based on sh7372.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 arch/arm/mach-shmobile/Makefile               |    1 +
 arch/arm/mach-shmobile/include/mach/r8a7740.h |   33 +++++
 arch/arm/mach-shmobile/pm-r8a7740.c           |  184 +++++++++++++++++++++++++
 arch/arm/mach-shmobile/setup-r8a7740.c        |    5 +
 4 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-shmobile/pm-r8a7740.c

diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 8aa1962..4919d73 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_ARCH_R8A7740)	+= entry-intc.o
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o
+obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
 
 # Board objects
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
index 8bd7b9c..6937352 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_R8A7740_H__
 #define __ASM_R8A7740_H__
 
+#include <linux/pm_domain.h>
+
 /*
  * MD_CKx pin
  */
@@ -604,4 +606,35 @@ enum {
 	SHDMA_SLAVE_USBHS_RX,
 };
 
+struct platform_device;
+
+struct r8a7740_pm_domain {
+	struct generic_pm_domain genpd;
+	struct dev_power_governor *gov;
+	int (*suspend)(void);
+	void (*resume)(void);
+	unsigned int bit_shift;
+	bool no_debug;
+};
+
+static inline
+struct r8a7740_pm_domain *to_r8a7740_pd(struct generic_pm_domain *d)
+{
+	return container_of(d, struct r8a7740_pm_domain, genpd);
+}
+
+#ifdef CONFIG_PM
+extern struct r8a7740_pm_domain r8a7740_a4s;
+
+extern void r8a7740_init_pm_domain(struct r8a7740_pm_domain *r8a7740_pd);
+extern void r8a7740_add_device_to_domain(struct r8a7740_pm_domain *r8a7740_pd,
+					struct platform_device *pdev);
+extern void r8a7740_pm_add_subdomain(struct r8a7740_pm_domain *r8a7740_pd,
+				    struct r8a7740_pm_domain *r8a7740_sd);
+#else
+#define r8a7740_init_pm_domain(pd) do { } while (0)
+#define r8a7740_add_device_to_domain(pd, pdev) do { } while (0)
+#define r8a7740_pm_add_subdomain(pd, sd) do { } while (0)
+#endif /* CONFIG_PM */
+
 #endif /* __ASM_R8A7740_H__ */
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
new file mode 100644
index 0000000..5b0fc91
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -0,0 +1,184 @@
+/*
+ * r8a7740 power management support
+ *
+ * Copyright (C) 2012  Renesas Solutions Corp.
+ * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on pm-sh7372.c
+ *  Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_clock.h>
+#include <asm/io.h>
+#include <mach/r8a7740.h>
+
+/* SYSC */
+#define SPDCR		0xe6180008
+#define SWUCR		0xe6180014
+#define PSTR		0xe6180080
+
+#define PSTR_RETRIES	100
+#define PSTR_DELAY_US	10
+
+#ifdef CONFIG_PM
+static int pd_power_down(struct generic_pm_domain *genpd)
+{
+	struct r8a7740_pm_domain *r8a7740_pd = to_r8a7740_pd(genpd);
+	unsigned int mask = 1 << r8a7740_pd->bit_shift;
+
+	if (r8a7740_pd->suspend) {
+		int ret = r8a7740_pd->suspend();
+
+		if (ret)
+			return ret;
+	}
+
+	if (__raw_readl(PSTR) & mask) {
+		unsigned int retry_count;
+		__raw_writel(mask, SPDCR);
+
+		for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
+			if (!(__raw_readl(SPDCR) & mask))
+				break;
+			cpu_relax();
+		}
+	}
+
+	if (!r8a7740_pd->no_debug)
+		pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
+			 genpd->name, mask, __raw_readl(PSTR));
+
+	return 0;
+}
+
+static int __pd_power_up(struct r8a7740_pm_domain *r8a7740_pd, bool do_resume)
+{
+	unsigned int mask = 1 << r8a7740_pd->bit_shift;
+	unsigned int retry_count;
+	int ret = 0;
+
+	if (__raw_readl(PSTR) & mask)
+		goto out;
+
+	__raw_writel(mask, SWUCR);
+
+	for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
+		if (!(__raw_readl(SWUCR) & mask))
+			break;
+		if (retry_count > PSTR_RETRIES)
+			udelay(PSTR_DELAY_US);
+		else
+			cpu_relax();
+	}
+	if (!retry_count)
+		ret = -EIO;
+
+	if (!r8a7740_pd->no_debug)
+		pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+			 r8a7740_pd->genpd.name, mask, __raw_readl(PSTR));
+
+out:
+	if (ret = 0 && r8a7740_pd->resume && do_resume)
+		r8a7740_pd->resume();
+
+	return ret;
+}
+
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+	return __pd_power_up(to_r8a7740_pd(genpd), true);
+}
+
+static bool pd_active_wakeup(struct device *dev)
+{
+	bool (*active_wakeup)(struct device *dev);
+
+	active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
+	return active_wakeup ? active_wakeup(dev) : true;
+}
+
+static int r8a7740_stop_dev(struct device *dev)
+{
+	int (*stop)(struct device *dev);
+
+	stop = dev_gpd_data(dev)->ops.stop;
+	if (stop) {
+		int ret = stop(dev);
+		if (ret)
+			return ret;
+	}
+	return pm_clk_suspend(dev);
+}
+
+static int r8a7740_start_dev(struct device *dev)
+{
+	int (*start)(struct device *dev);
+	int ret;
+
+	ret = pm_clk_resume(dev);
+	if (ret)
+		return ret;
+
+	start = dev_gpd_data(dev)->ops.start;
+	if (start)
+		ret = start(dev);
+
+	return ret;
+}
+
+void r8a7740_init_pm_domain(struct r8a7740_pm_domain *r8a7740_pd)
+{
+	struct generic_pm_domain *genpd = &r8a7740_pd->genpd;
+	struct dev_power_governor *gov = r8a7740_pd->gov;
+
+	pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
+	genpd->dev_ops.stop		= r8a7740_stop_dev;
+	genpd->dev_ops.start		= r8a7740_start_dev;
+	genpd->dev_ops.active_wakeup	= pd_active_wakeup;
+	genpd->dev_irq_safe		= true;
+	genpd->power_off		= pd_power_down;
+	genpd->power_on			= pd_power_up;
+	__pd_power_up(r8a7740_pd, false);
+}
+
+void r8a7740_add_device_to_domain(struct r8a7740_pm_domain *r8a7740_pd,
+				 struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	pm_genpd_add_device(&r8a7740_pd->genpd, dev);
+	if (pm_clk_no_clocks(dev))
+		pm_clk_add(dev, NULL);
+}
+
+void r8a7740_pm_add_subdomain(struct r8a7740_pm_domain *r8a7740_pd,
+			     struct r8a7740_pm_domain *r8a7740_sd)
+{
+	pm_genpd_add_subdomain(&r8a7740_pd->genpd, &r8a7740_sd->genpd);
+}
+
+static int r8a7740_a4s_suspend(void)
+{
+	/*
+	 * The A4S domain contains the CPU core and therefore it should
+	 * only be turned off if the CPU is in use.
+	 */
+	return -EBUSY;
+}
+
+struct r8a7740_pm_domain r8a7740_a4s = {
+	.genpd.name	= "A4S",
+	.bit_shift	= 10,
+	.gov		= &pm_domain_always_on_gov,
+	.no_debug	= true,
+	.suspend	= r8a7740_a4s_suspend,
+};
+
+#endif /* CONFIG_PM */
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 48d7bbf..c185ae4 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -27,6 +27,7 @@
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
 #include <linux/dma-mapping.h>
+#include <linux/pm_domain.h>
 #include <mach/dma-register.h>
 #include <mach/r8a7740.h>
 #include <mach/common.h>
@@ -671,6 +672,10 @@ void __init r8a7740_add_standard_devices(void)
 	r8a7740_i2c_workaround(&i2c0_device);
 	r8a7740_i2c_workaround(&i2c1_device);
 
+	/* PM domain */
+	r8a7740_init_pm_domain(&r8a7740_a4s);
+
+	/* add devices */
 	platform_add_devices(r8a7740_early_devices,
 			    ARRAY_SIZE(r8a7740_early_devices));
 	platform_add_devices(r8a7740_late_devices,
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-10-29  8:14 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-04  3:55 [PATCH 2/7] ARM: shmobile: r8a7740: add basic pm domain support Kuninori Morimoto
2012-07-04 10:45 ` Paul Mundt
2012-07-04 10:48 ` Magnus Damm
2012-07-04 16:57 ` Paul Mundt
2012-07-05  0:05 ` Kuninori Morimoto
2012-07-05  1:08 ` Kuninori Morimoto
2012-10-29  8:14 ` [PATCH 2/7] ARM: shmobile: r8a7740: add USB24 clock explain Kuninori Morimoto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox