All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: linux-sh@vger.kernel.org
Subject: Re: [PATCH] ARM: mach-shmobile: sh7372 A4R support V2
Date: Sun, 16 Oct 2011 21:03:16 +0000	[thread overview]
Message-ID: <201110162303.16999.rjw@sisk.pl> (raw)
In-Reply-To: <20110927085408.27727.59395.sendpatchset@w520>

On Tuesday, September 27, 2011, Magnus Damm wrote:
> From: Magnus Damm <damm@opensource.se>
> 
> This patch is V2 of sh7372 A4R power domain support.
> 
> The sh7372 A4R hardware power domain contains the
> SH CPU Core and a set of I/O devices including
> multimedia accelerators and I2C controllers.
> 
> One special case about A4R is the INTCS interrupt
> controller that needs to be saved and restored to
> keep working as expected. Also the LCDC hardware
> blocks are in a different hardware power domain
> but have their IRQs routed only through INTCS. So
> as long as LCDCs are active we cannot power down
> INTCS because that would risk losing interrupts.
> 
> Signed-off-by: Magnus Damm <damm@opensource.se>

Unfortunately, the original patch breaks resume from system suspend,
because it causes the A4R domain be turned off during the _noirq
phase of device suspend.  The domain stays off during syscore_ops
resume, so intc_resume() crashes, because it can't access the
device.  To address this problem it is sufficient to prevent the
domain from being turned off, which is done in my version of the
patch below (on top of my version of the A3SP patch sent a while
ago: http://article.gmane.org/gmane.linux.ports.sh.devel/12565).

Thanks,
Rafael

---
From: Magnus Damm <damm@opensource.se>
Subject: ARM: mach-shmobile: sh7372 A4R support

This change adds support for the sh7372 A4R power domain.

The sh7372 A4R hardware power domain contains the
SH CPU Core and a set of I/O devices including
multimedia accelerators and I2C controllers.

One special case about A4R is the INTCS interrupt
controller that needs to be saved and restored to
keep working as expected. Also the LCDC hardware
blocks are in a different hardware power domain
but have their IRQs routed only through INTCS. So
as long as LCDCs are active we cannot power down
INTCS because that would risk losing interrupts.

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 arch/arm/mach-shmobile/board-ap4evb.c        |    1 
 arch/arm/mach-shmobile/board-mackerel.c      |    1 
 arch/arm/mach-shmobile/include/mach/sh7372.h |    7 +++
 arch/arm/mach-shmobile/intc-sh7372.c         |   52 ++++++++++++++++++++++++++-
 arch/arm/mach-shmobile/pm-sh7372.c           |   29 ++++++++++++++-
 arch/arm/mach-shmobile/setup-sh7372.c        |    8 ++++
 6 files changed, 96 insertions(+), 2 deletions(-)

Index: linux/arch/arm/mach-shmobile/board-ap4evb.c
=================================--- linux.orig/arch/arm/mach-shmobile/board-ap4evb.c
+++ linux/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1412,6 +1412,7 @@ static void __init ap4evb_init(void)
 	sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
 	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
 	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
 
 	hdmi_init_pm_clock();
 	fsi_init_pm_clock();
Index: linux/arch/arm/mach-shmobile/board-mackerel.c
=================================--- linux.orig/arch/arm/mach-shmobile/board-mackerel.c
+++ linux/arch/arm/mach-shmobile/board-mackerel.c
@@ -1596,6 +1596,7 @@ static void __init mackerel_init(void)
 	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
 #endif
 	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
 
 	hdmi_init_pm_clock();
 	sh7372_pm_init();
Index: linux/arch/arm/mach-shmobile/include/mach/sh7372.h
=================================--- linux.orig/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ linux/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -480,8 +480,11 @@ struct platform_device;
 struct sh7372_pm_domain {
 	struct generic_pm_domain genpd;
 	struct dev_power_governor *gov;
+	void (*suspend)(void);
+	void (*resume)(void);
 	unsigned int bit_shift;
 	bool no_debug;
+	bool stay_on;
 };
 
 static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
@@ -493,6 +496,7 @@ static inline struct sh7372_pm_domain *t
 extern struct sh7372_pm_domain sh7372_a4lc;
 extern struct sh7372_pm_domain sh7372_a4mp;
 extern struct sh7372_pm_domain sh7372_d4;
+extern struct sh7372_pm_domain sh7372_a4r;
 extern struct sh7372_pm_domain sh7372_a3rv;
 extern struct sh7372_pm_domain sh7372_a3ri;
 extern struct sh7372_pm_domain sh7372_a3sp;
@@ -512,4 +516,7 @@ extern void sh7372_pm_add_subdomain(stru
 #define sh7372_pm_add_subdomain(pd, sd) do { } while(0)
 #endif /* CONFIG_PM */
 
+extern void sh7372_intcs_suspend(void);
+extern void sh7372_intcs_resume(void);
+
 #endif /* __ASM_SH7372_H__ */
Index: linux/arch/arm/mach-shmobile/intc-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/intc-sh7372.c
+++ linux/arch/arm/mach-shmobile/intc-sh7372.c
@@ -606,9 +606,16 @@ static void intcs_demux(unsigned int irq
 	generic_handle_irq(intcs_evt2irq(evtcodeas));
 }
 
+static void __iomem *intcs_ffd2;
+static void __iomem *intcs_ffd5;
+
 void __init sh7372_init_irq(void)
 {
-	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+	void __iomem *intevtsa;
+
+	intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
+	intevtsa = intcs_ffd2 + 0x100;
+	intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
 	register_intc_controller(&intcs_desc);
@@ -617,3 +624,46 @@ void __init sh7372_init_irq(void)
 	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
 	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
+
+static unsigned short ffd2[0x200];
+static unsigned short ffd5[0x100];
+
+void sh7372_intcs_suspend(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x30; k += 4)
+		ffd2[k] = __raw_readw(intcs_ffd2 + k);
+
+	for (k = 0x80; k <= 0xb0; k += 4)
+		ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+	for (k = 0x180; k <= 0x188; k += 4)
+		ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+	for (k = 0x00; k <= 0x3c; k += 4)
+		ffd5[k] = __raw_readw(intcs_ffd5 + k);
+
+	for (k = 0x80; k <= 0x9c; k += 4)
+		ffd5[k] = __raw_readb(intcs_ffd5 + k);
+}
+
+void sh7372_intcs_resume(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x30; k += 4)
+		__raw_writew(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x80; k <= 0xb0; k += 4)
+		__raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x180; k <= 0x188; k += 4)
+		__raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x00; k <= 0x3c; k += 4)
+		__raw_writew(ffd5[k], intcs_ffd5 + k);
+
+	for (k = 0x80; k <= 0x9c; k += 4)
+		__raw_writeb(ffd5[k], intcs_ffd5 + k);
+}
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -44,6 +44,7 @@
 #define SPDCR 0xe6180008
 #define SWUCR 0xe6180014
 #define SBAR 0xe6180020
+#define WUPRMSK 0xe6180028
 #define WUPSMSK 0xe618002c
 #define WUPSMSK2 0xe6180048
 #define PSTR 0xe6180080
@@ -80,6 +81,12 @@ static int pd_power_down(struct generic_
 	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
 	unsigned int mask = 1 << sh7372_pd->bit_shift;
 
+	if (sh7372_pd->suspend)
+		sh7372_pd->suspend();
+
+	if (sh7372_pd->stay_on)
+		return 0;
+
 	if (__raw_readl(PSTR) & mask) {
 		unsigned int retry_count;
 
@@ -106,6 +113,9 @@ static int pd_power_up(struct generic_pm
 	unsigned int retry_count;
 	int ret = 0;
 
+	if (sh7372_pd->stay_on)
+		goto out;
+
 	if (__raw_readl(PSTR) & mask)
 		goto out;
 
@@ -122,14 +132,23 @@ static int pd_power_up(struct generic_pm
 	if (__raw_readl(SWUCR) & mask)
 		ret = -EIO;
 
- out:
 	if (!sh7372_pd->no_debug)
 		pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
 			 mask, __raw_readl(PSTR));
 
+ out:
+	if (ret = 0 && sh7372_pd->resume)
+		sh7372_pd->resume();
+
 	return ret;
 }
 
+static void sh7372_a4r_suspend(void)
+{
+	sh7372_intcs_suspend();
+	__raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
+}
+
 static bool pd_active_wakeup(struct device *dev)
 {
 	return true;
@@ -214,6 +233,14 @@ struct sh7372_pm_domain sh7372_d4 = {
 	.bit_shift = 3,
 };
 
+struct sh7372_pm_domain sh7372_a4r = {
+	.bit_shift = 5,
+	.gov = &sh7372_always_on_gov,
+	.suspend = sh7372_a4r_suspend,
+	.resume = sh7372_intcs_resume,
+	.stay_on = true,
+};
+
 struct sh7372_pm_domain sh7372_a3rv = {
 	.bit_shift = 6,
 };
Index: linux/arch/arm/mach-shmobile/setup-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/setup-sh7372.c
+++ linux/arch/arm/mach-shmobile/setup-sh7372.c
@@ -991,12 +991,14 @@ void __init sh7372_add_standard_devices(
 	sh7372_init_pm_domain(&sh7372_a4lc);
 	sh7372_init_pm_domain(&sh7372_a4mp);
 	sh7372_init_pm_domain(&sh7372_d4);
+	sh7372_init_pm_domain(&sh7372_a4r);
 	sh7372_init_pm_domain(&sh7372_a3rv);
 	sh7372_init_pm_domain(&sh7372_a3ri);
 	sh7372_init_pm_domain(&sh7372_a3sg);
 	sh7372_init_pm_domain(&sh7372_a3sp);
 
 	sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
+	sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
 
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
@@ -1020,6 +1022,12 @@ void __init sh7372_add_standard_devices(
 	sh7372_add_special_dev_to_domain(&sh7372_a3sp, &dma2_device);
 	sh7372_add_special_dev_to_domain(&sh7372_a3sp, &usb_dma0_device);
 	sh7372_add_special_dev_to_domain(&sh7372_a3sp, &usb_dma1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
 }
 
 void __init sh7372_add_early_devices(void)

  reply	other threads:[~2011-10-16 21:03 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-27  8:54 [PATCH] ARM: mach-shmobile: sh7372 A4R support V2 Magnus Damm
2011-10-16 21:03 ` Rafael J. Wysocki [this message]
2011-11-10 12:05 ` [PATCH] ARM: mach-shmobile: sh7372 A4R suspend/resume order fix Rafael J. Wysocki
2011-11-11  1:07 ` Magnus Damm
2011-11-11  7:49 ` Guennadi Liakhovetski
2011-11-11 11:58 ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201110162303.16999.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=linux-sh@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.