linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/13] ARM: at91; pm: cleanup
@ 2017-02-02 14:45 Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 01/13] ARM: at91: pm: cleanup headers Alexandre Belloni
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Hi,

The following patch set is a cleanup of the AT91 PM code.

The main feautres is that it is now using a struct to pass arguments
between the C and the assembly code, allowing for more than 4 variables
to be passed.
It also removes instructions so it is actually faster.

The standby path is also faster now because it is only handled using C,
removing the need for a few comparisons before enabling DRAM self
refresh. This also allows to always propose standby, even when the sram
allocation failed.

Finally, the PM initialization functions are merge, removing the need
for separate paths on at91sam9*

Alexandre Belloni (13):
  ARM: at91: pm: cleanup headers
  ARM: at91: pm: move at91_ramc_read/write to pm.c
  ARM: at91: pm: Move global variables into at91_pm_data
  ARM: at91: pm: use struct at91_pm_data in pm_suspend.S
  ARM: at91: pm: use struct members directly
  ARM: at91: pm: simplify at91rm9200_standby
  ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1
    memories.
  ARM: at91: pm: tie the memory controller type to the ramc id
  ARM: at91: pm: tie the USB clock mask to the pmc
  ARM: at91: pm: merge all at91sam9*_pm_init
  ARM: at91: pm: remove at91_pm_set_standby
  ARM: at91: pm: use C functions for standby
  ARM: at91: pm: Allow PM even if SRAM allocation failed

 arch/arm/mach-at91/Makefile          |  33 ++++++
 arch/arm/mach-at91/at91sam9.c        |  45 +-------
 arch/arm/mach-at91/generic.h         |   8 +-
 arch/arm/mach-at91/pm.c              | 212 +++++++++++++++++------------------
 arch/arm/mach-at91/pm.h              |  27 ++---
 arch/arm/mach-at91/pm_data-offsets.c |  12 ++
 arch/arm/mach-at91/pm_suspend.S      |  55 ++-------
 7 files changed, 176 insertions(+), 216 deletions(-)
 create mode 100644 arch/arm/mach-at91/pm_data-offsets.c

-- 
2.11.0

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

* [PATCH 01/13] ARM: at91: pm: cleanup headers
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 02/13] ARM: at91: pm: move at91_ramc_read/write to pm.c Alexandre Belloni
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Remove unnecessary header inclusions and reorder the remaining ones.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index b4332b727e9c..3d28d1957e41 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,28 +10,17 @@
  * (at your option) any later version.
  */
 
-#include <linux/gpio.h>
-#include <linux/suspend.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
 #include <linux/genalloc.h>
-#include <linux/interrupt.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/atmel.h>
-#include <linux/io.h>
+#include <linux/suspend.h>
+
 #include <linux/clk/at91_pmc.h>
 
-#include <asm/irq.h>
-#include <linux/atomic.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-#include <asm/fncpy.h>
 #include <asm/cacheflush.h>
+#include <asm/fncpy.h>
 #include <asm/system_misc.h>
 
 #include "generic.h"
-- 
2.11.0

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

* [PATCH 02/13] ARM: at91: pm: move at91_ramc_read/write to pm.c
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 01/13] ARM: at91: pm: cleanup headers Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 03/13] ARM: at91: pm: Move global variables into at91_pm_data Alexandre Belloni
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Those macros are only used in pm.c, move them there so we can remove the
test on __ASSEMBLY__.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c |  6 ++++++
 arch/arm/mach-at91/pm.h | 10 ----------
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3d28d1957e41..ca141f9873f2 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -45,6 +45,12 @@ static struct {
 } at91_pm_data;
 
 void __iomem *at91_ramc_base[2];
+#define at91_ramc_read(id, field) \
+	__raw_readl(at91_ramc_base[id] + field)
+
+#define at91_ramc_write(id, field, value) \
+	__raw_writel(value, at91_ramc_base[id] + field)
+
 
 static int at91_pm_valid_state(suspend_state_t state)
 {
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 3fcf8810f14e..8eed156ef19a 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -17,16 +17,6 @@
 #include <soc/at91/at91sam9_ddrsdr.h>
 #include <soc/at91/at91sam9_sdramc.h>
 
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_ramc_base[];
-
-#define at91_ramc_read(id, field) \
-	__raw_readl(at91_ramc_base[id] + field)
-
-#define at91_ramc_write(id, field, value) \
-	__raw_writel(value, at91_ramc_base[id] + field)
-#endif
-
 #define AT91_MEMCTRL_MC		0
 #define AT91_MEMCTRL_SDRAMC	1
 #define AT91_MEMCTRL_DDRSDR	2
-- 
2.11.0

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

* [PATCH 03/13] ARM: at91: pm: Move global variables into at91_pm_data
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 01/13] ARM: at91: pm: cleanup headers Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 02/13] ARM: at91: pm: move at91_ramc_read/write to pm.c Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 04/13] ARM: at91: pm: use struct at91_pm_data in pm_suspend.S Alexandre Belloni
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Instead of having separate global variables to hold IP dresses, move them
to struct at91_pm_data.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 44 +++++++++++++++++++++-----------------------
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ca141f9873f2..4253cd775738 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -26,8 +26,6 @@
 #include "generic.h"
 #include "pm.h"
 
-static void __iomem *pmc;
-
 /*
  * FIXME: this is needed to communicate between the pinctrl driver and
  * the PM implementation in the machine. Possibly part of the PM
@@ -40,17 +38,17 @@ extern void at91_pinctrl_gpio_resume(void);
 #endif
 
 static struct {
+	void __iomem *pmc;
+	void __iomem *ramc[2];
 	unsigned long uhp_udp_mask;
 	int memctrl;
 } at91_pm_data;
 
-void __iomem *at91_ramc_base[2];
 #define at91_ramc_read(id, field) \
-	__raw_readl(at91_ramc_base[id] + field)
+	__raw_readl(at91_pm_data.ramc[id] + field)
 
 #define at91_ramc_write(id, field, value) \
-	__raw_writel(value, at91_ramc_base[id] + field)
-
+	__raw_writel(value, at91_pm_data.ramc[id] + field)
 
 static int at91_pm_valid_state(suspend_state_t state)
 {
@@ -86,7 +84,7 @@ static int at91_pm_verify_clocks(void)
 	unsigned long scsr;
 	int i;
 
-	scsr = readl(pmc + AT91_PMC_SCSR);
+	scsr = readl(at91_pm_data.pmc + AT91_PMC_SCSR);
 
 	/* USB must not be using PLLB */
 	if ((scsr & at91_pm_data.uhp_udp_mask) != 0) {
@@ -100,7 +98,7 @@ static int at91_pm_verify_clocks(void)
 
 		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
 			continue;
-		css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+		css = readl(at91_pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
 		if (css != AT91_PMC_CSS_SLOW) {
 			pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
 			return 0;
@@ -143,8 +141,8 @@ static void at91_pm_suspend(suspend_state_t state)
 	flush_cache_all();
 	outer_disable();
 
-	at91_suspend_sram_fn(pmc, at91_ramc_base[0],
-			     at91_ramc_base[1], pm_data);
+	at91_suspend_sram_fn(at91_pm_data.pmc, at91_pm_data.ramc[0],
+			     at91_pm_data.ramc[1], pm_data);
 
 	outer_resume();
 }
@@ -247,7 +245,7 @@ static void at91rm9200_standby(void)
 		"    mcr    p15, 0, %0, c7, c0, 4\n\t"
 		"    str    %5, [%1, %2]"
 		:
-		: "r" (0), "r" (at91_ramc_base[0]), "r" (AT91_MC_SDRAMC_LPR),
+		: "r" (0), "r" (at91_pm_data.ramc[0]), "r" (AT91_MC_SDRAMC_LPR),
 		  "r" (1), "r" (AT91_MC_SDRAMC_SRR),
 		  "r" (lpr));
 }
@@ -262,7 +260,7 @@ static void at91_ddr_standby(void)
 	u32 lpr0, lpr1 = 0;
 	u32 saved_lpr0, saved_lpr1 = 0;
 
-	if (at91_ramc_base[1]) {
+	if (at91_pm_data.ramc[1]) {
 		saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
 		lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
 		lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
@@ -274,13 +272,13 @@ static void at91_ddr_standby(void)
 
 	/* self-refresh mode now */
 	at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
-	if (at91_ramc_base[1])
+	if (at91_pm_data.ramc[1])
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
 
 	cpu_do_idle();
 
 	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-	if (at91_ramc_base[1])
+	if (at91_pm_data.ramc[1])
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
 }
 
@@ -292,7 +290,7 @@ static void at91sam9_sdram_standby(void)
 	u32 lpr0, lpr1 = 0;
 	u32 saved_lpr0, saved_lpr1 = 0;
 
-	if (at91_ramc_base[1]) {
+	if (at91_pm_data.ramc[1]) {
 		saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
 		lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
 		lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
@@ -304,13 +302,13 @@ static void at91sam9_sdram_standby(void)
 
 	/* self-refresh mode now */
 	at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
-	if (at91_ramc_base[1])
+	if (at91_pm_data.ramc[1])
 		at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
 
 	cpu_do_idle();
 
 	at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
-	if (at91_ramc_base[1])
+	if (at91_pm_data.ramc[1])
 		at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
@@ -330,8 +328,8 @@ static __init void at91_dt_ramc(void)
 	const void *standby = NULL;
 
 	for_each_matching_node_and_match(np, ramc_ids, &of_id) {
-		at91_ramc_base[idx] = of_iomap(np, 0);
-		if (!at91_ramc_base[idx])
+		at91_pm_data.ramc[idx] = of_iomap(np, 0);
+		if (!at91_pm_data.ramc[idx])
 			panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
 
 		if (!standby)
@@ -357,12 +355,12 @@ static void at91rm9200_idle(void)
 	 * Disable the processor clock.  The processor will be automatically
 	 * re-enabled by an interrupt or by a reset.
 	 */
-	writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	writel(AT91_PMC_PCK, at91_pm_data.pmc + AT91_PMC_SCDR);
 }
 
 static void at91sam9_idle(void)
 {
-	writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	writel(AT91_PMC_PCK, at91_pm_data.pmc + AT91_PMC_SCDR);
 	cpu_do_idle();
 }
 
@@ -431,8 +429,8 @@ static void __init at91_pm_init(void (*pm_idle)(void))
 		platform_device_register(&at91_cpuidle_device);
 
 	pmc_np = of_find_matching_node(NULL, atmel_pmc_ids);
-	pmc = of_iomap(pmc_np, 0);
-	if (!pmc) {
+	at91_pm_data.pmc = of_iomap(pmc_np, 0);
+	if (!at91_pm_data.pmc) {
 		pr_err("AT91: PM not supported, PMC not found\n");
 		return;
 	}
-- 
2.11.0

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

* [PATCH 04/13] ARM: at91: pm: use struct at91_pm_data in pm_suspend.S
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (2 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 03/13] ARM: at91: pm: Move global variables into at91_pm_data Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 05/13] ARM: at91: pm: use struct members directly Alexandre Belloni
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

The number of register we can safely pass to at91_pm_suspend_in_sram is
limited. Instead, pass the address to the at91_pm_data structure.

The offsets are automatically generated to avoid hardcoding them.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/Makefile          | 33 +++++++++++++++
 arch/arm/mach-at91/pm.c              | 78 +++++++++++++++---------------------
 arch/arm/mach-at91/pm.h              | 16 +++++---
 arch/arm/mach-at91/pm_data-offsets.c | 13 ++++++
 arch/arm/mach-at91/pm_suspend.S      | 29 ++++++--------
 5 files changed, 102 insertions(+), 67 deletions(-)
 create mode 100644 arch/arm/mach-at91/pm_data-offsets.c

diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index c5bbf8bb8c0f..858ef14f961c 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -18,3 +18,36 @@ endif
 ifeq ($(CONFIG_PM_DEBUG),y)
 CFLAGS_pm.o += -DDEBUG
 endif
+
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+	"/^->/{s:->#\(.*\):/* \1 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:->::; p;}"
+endef
+
+# Use filechk to avoid rebuilds when a header changes, but the resulting file
+# does not
+define filechk_offsets
+	(set -e; \
+	 echo "#ifndef $2"; \
+	 echo "#define $2"; \
+	 echo "/*"; \
+	 echo " * DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " * This file was generated by Kbuild"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y); \
+	 echo ""; \
+	 echo "#endif" )
+endef
+
+arch/arm/mach-at91/pm_data-offsets.s: arch/arm/mach-at91/pm_data-offsets.c
+	$(call if_changed_dep,cc_s_c)
+
+include/generated/at91_pm_data-offsets.h: arch/arm/mach-at91/pm_data-offsets.s FORCE
+	$(call filechk,offsets,__PM_DATA_OFFSETS_H__)
+
+arch/arm/mach-at91/pm_suspend.o: include/generated/at91_pm_data-offsets.h
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 4253cd775738..90b78ad20a97 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -37,18 +37,13 @@ extern void at91_pinctrl_gpio_suspend(void);
 extern void at91_pinctrl_gpio_resume(void);
 #endif
 
-static struct {
-	void __iomem *pmc;
-	void __iomem *ramc[2];
-	unsigned long uhp_udp_mask;
-	int memctrl;
-} at91_pm_data;
+static struct at91_pm_data pm_data;
 
 #define at91_ramc_read(id, field) \
-	__raw_readl(at91_pm_data.ramc[id] + field)
+	__raw_readl(pm_data.ramc[id] + field)
 
 #define at91_ramc_write(id, field, value) \
-	__raw_writel(value, at91_pm_data.ramc[id] + field)
+	__raw_writel(value, pm_data.ramc[id] + field)
 
 static int at91_pm_valid_state(suspend_state_t state)
 {
@@ -84,10 +79,10 @@ static int at91_pm_verify_clocks(void)
 	unsigned long scsr;
 	int i;
 
-	scsr = readl(at91_pm_data.pmc + AT91_PMC_SCSR);
+	scsr = readl(pm_data.pmc + AT91_PMC_SCSR);
 
 	/* USB must not be using PLLB */
-	if ((scsr & at91_pm_data.uhp_udp_mask) != 0) {
+	if ((scsr & pm_data.uhp_udp_mask) != 0) {
 		pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
 		return 0;
 	}
@@ -98,7 +93,7 @@ static int at91_pm_verify_clocks(void)
 
 		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
 			continue;
-		css = readl(at91_pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+		css = readl(pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
 		if (css != AT91_PMC_CSS_SLOW) {
 			pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
 			return 0;
@@ -124,25 +119,18 @@ int at91_suspend_entering_slow_clock(void)
 }
 EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
-static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0,
-			  void __iomem *ramc1, int memctrl);
-
-extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0,
-			    void __iomem *ramc1, int memctrl);
+static void (*at91_suspend_sram_fn)(struct at91_pm_data *);
+extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data);
 extern u32 at91_pm_suspend_in_sram_sz;
 
 static void at91_pm_suspend(suspend_state_t state)
 {
-	unsigned int pm_data = at91_pm_data.memctrl;
-
-	pm_data |= (state == PM_SUSPEND_MEM) ?
-				AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
+	pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0;
 
 	flush_cache_all();
 	outer_disable();
 
-	at91_suspend_sram_fn(at91_pm_data.pmc, at91_pm_data.ramc[0],
-			     at91_pm_data.ramc[1], pm_data);
+	at91_suspend_sram_fn(&pm_data);
 
 	outer_resume();
 }
@@ -245,7 +233,7 @@ static void at91rm9200_standby(void)
 		"    mcr    p15, 0, %0, c7, c0, 4\n\t"
 		"    str    %5, [%1, %2]"
 		:
-		: "r" (0), "r" (at91_pm_data.ramc[0]), "r" (AT91_MC_SDRAMC_LPR),
+		: "r" (0), "r" (pm_data.ramc[0]), "r" (AT91_MC_SDRAMC_LPR),
 		  "r" (1), "r" (AT91_MC_SDRAMC_SRR),
 		  "r" (lpr));
 }
@@ -260,7 +248,7 @@ static void at91_ddr_standby(void)
 	u32 lpr0, lpr1 = 0;
 	u32 saved_lpr0, saved_lpr1 = 0;
 
-	if (at91_pm_data.ramc[1]) {
+	if (pm_data.ramc[1]) {
 		saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
 		lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
 		lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
@@ -272,13 +260,13 @@ static void at91_ddr_standby(void)
 
 	/* self-refresh mode now */
 	at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
-	if (at91_pm_data.ramc[1])
+	if (pm_data.ramc[1])
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
 
 	cpu_do_idle();
 
 	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-	if (at91_pm_data.ramc[1])
+	if (pm_data.ramc[1])
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
 }
 
@@ -290,7 +278,7 @@ static void at91sam9_sdram_standby(void)
 	u32 lpr0, lpr1 = 0;
 	u32 saved_lpr0, saved_lpr1 = 0;
 
-	if (at91_pm_data.ramc[1]) {
+	if (pm_data.ramc[1]) {
 		saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
 		lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
 		lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
@@ -302,13 +290,13 @@ static void at91sam9_sdram_standby(void)
 
 	/* self-refresh mode now */
 	at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
-	if (at91_pm_data.ramc[1])
+	if (pm_data.ramc[1])
 		at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
 
 	cpu_do_idle();
 
 	at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
-	if (at91_pm_data.ramc[1])
+	if (pm_data.ramc[1])
 		at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
@@ -328,8 +316,8 @@ static __init void at91_dt_ramc(void)
 	const void *standby = NULL;
 
 	for_each_matching_node_and_match(np, ramc_ids, &of_id) {
-		at91_pm_data.ramc[idx] = of_iomap(np, 0);
-		if (!at91_pm_data.ramc[idx])
+		pm_data.ramc[idx] = of_iomap(np, 0);
+		if (!pm_data.ramc[idx])
 			panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
 
 		if (!standby)
@@ -355,12 +343,12 @@ static void at91rm9200_idle(void)
 	 * Disable the processor clock.  The processor will be automatically
 	 * re-enabled by an interrupt or by a reset.
 	 */
-	writel(AT91_PMC_PCK, at91_pm_data.pmc + AT91_PMC_SCDR);
+	writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR);
 }
 
 static void at91sam9_idle(void)
 {
-	writel(AT91_PMC_PCK, at91_pm_data.pmc + AT91_PMC_SCDR);
+	writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR);
 	cpu_do_idle();
 }
 
@@ -429,8 +417,8 @@ static void __init at91_pm_init(void (*pm_idle)(void))
 		platform_device_register(&at91_cpuidle_device);
 
 	pmc_np = of_find_matching_node(NULL, atmel_pmc_ids);
-	at91_pm_data.pmc = of_iomap(pmc_np, 0);
-	if (!at91_pm_data.pmc) {
+	pm_data.pmc = of_iomap(pmc_np, 0);
+	if (!pm_data.pmc) {
 		pr_err("AT91: PM not supported, PMC not found\n");
 		return;
 	}
@@ -455,8 +443,8 @@ void __init at91rm9200_pm_init(void)
 	 */
 	at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0);
 
-	at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP;
-	at91_pm_data.memctrl = AT91_MEMCTRL_MC;
+	pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP;
+	pm_data.memctrl = AT91_MEMCTRL_MC;
 
 	at91_pm_init(at91rm9200_idle);
 }
@@ -464,31 +452,31 @@ void __init at91rm9200_pm_init(void)
 void __init at91sam9260_pm_init(void)
 {
 	at91_dt_ramc();
-	at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC;
-	at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
+	pm_data.memctrl = AT91_MEMCTRL_SDRAMC;
+	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
 	at91_pm_init(at91sam9_idle);
 }
 
 void __init at91sam9g45_pm_init(void)
 {
 	at91_dt_ramc();
-	at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP;
-	at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
+	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP;
+	pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
 	at91_pm_init(at91sam9_idle);
 }
 
 void __init at91sam9x5_pm_init(void)
 {
 	at91_dt_ramc();
-	at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-	at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
+	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
+	pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
 	at91_pm_init(at91sam9_idle);
 }
 
 void __init sama5_pm_init(void)
 {
 	at91_dt_ramc();
-	at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-	at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
+	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
+	pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
 	at91_pm_init(NULL);
 }
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 8eed156ef19a..fc0f7d048187 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,12 +21,16 @@
 #define AT91_MEMCTRL_SDRAMC	1
 #define AT91_MEMCTRL_DDRSDR	2
 
-#define	AT91_PM_MEMTYPE_MASK	0x0f
-
-#define	AT91_PM_MODE_OFFSET	4
-#define	AT91_PM_MODE_MASK	0x01
-#define	AT91_PM_MODE(x)		(((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET)
-
 #define	AT91_PM_SLOW_CLOCK	0x01
 
+#ifndef __ASSEMBLY__
+struct at91_pm_data {
+	void __iomem *pmc;
+	void __iomem *ramc[2];
+	unsigned long uhp_udp_mask;
+	unsigned int memctrl;
+	unsigned int mode;
+};
+#endif
+
 #endif
diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c
new file mode 100644
index 000000000000..30302cb16df0
--- /dev/null
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -0,0 +1,13 @@
+#include <linux/stddef.h>
+#include <linux/kbuild.h>
+#include "pm.h"
+
+int main(void)
+{
+	DEFINE(PM_DATA_PMC,		offsetof(struct at91_pm_data, pmc));
+	DEFINE(PM_DATA_RAMC0,		offsetof(struct at91_pm_data, ramc[0]));
+	DEFINE(PM_DATA_RAMC1,		offsetof(struct at91_pm_data, ramc[1]));
+	DEFINE(PM_DATA_MEMCTRL,	offsetof(struct at91_pm_data, memctrl));
+	DEFINE(PM_DATA_MODE,		offsetof(struct at91_pm_data, mode));
+	return 0;
+}
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index a25defda3d22..ed317657e760 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -14,6 +14,7 @@
 #include <linux/linkage.h>
 #include <linux/clk/at91_pmc.h>
 #include "pm.h"
+#include "generated/at91_pm_data-offsets.h"
 
 #define	SRAMC_SELF_FRESH_ACTIVE		0x01
 #define	SRAMC_SELF_FRESH_EXIT		0x00
@@ -72,13 +73,9 @@ tmp2	.req	r5
 	.arm
 
 /*
- * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
- *			void __iomem *ramc1, int memctrl)
+ * void at91_suspend_sram_fn(struct at91_pm_data*)
  * @input param:
- * 	@r0: base address of AT91_PMC
- *  	@r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
- *	@r2: base address of second SDRAM Controller or 0 if not present
- *	@r3: pm information
+ * 	@r0: base address of struct at91_pm_data
  */
 /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
 	.align 3
@@ -90,16 +87,16 @@ ENTRY(at91_pm_suspend_in_sram)
 	mov	tmp1, #0
 	mcr	p15, 0, tmp1, c7, c10, 4
 
-	str	r0, .pmc_base
-	str	r1, .sramc_base
-	str	r2, .sramc1_base
-
-	and	r0, r3, #AT91_PM_MEMTYPE_MASK
-	str	r0, .memtype
-
-	lsr	r0, r3, #AT91_PM_MODE_OFFSET
-	and	r0, r0, #AT91_PM_MODE_MASK
-	str	r0, .pm_mode
+	ldr	tmp1, [r0, #PM_DATA_PMC]
+	str	tmp1, .pmc_base
+	ldr	tmp1, [r0, #PM_DATA_RAMC0]
+	str	tmp1, .sramc_base
+	ldr	tmp1, [r0, #PM_DATA_RAMC1]
+	str	tmp1, .sramc1_base
+	ldr	tmp1, [r0, #PM_DATA_MEMCTRL]
+	str	tmp1, .memtype
+	ldr	tmp1, [r0, #PM_DATA_MODE]
+	str	tmp1, .pm_mode
 
 	/* Active the self-refresh mode */
 	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
-- 
2.11.0

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

* [PATCH 05/13] ARM: at91: pm: use struct members directly
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (3 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 04/13] ARM: at91: pm: use struct at91_pm_data in pm_suspend.S Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 06/13] ARM: at91: pm: simplify at91rm9200_standby Alexandre Belloni
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Use the pm_data struct members directly instead of caching them. This saves
a few load and store operations.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm_suspend.S | 40 +++++++++++-----------------------------
 1 file changed, 11 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index ed317657e760..3ee282c051e0 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -22,6 +22,7 @@
 pmc	.req	r0
 tmp1	.req	r4
 tmp2	.req	r5
+pm_data	.req	r9
 
 /*
  * Wait until master clock is ready (after switching master clock source)
@@ -87,26 +88,17 @@ ENTRY(at91_pm_suspend_in_sram)
 	mov	tmp1, #0
 	mcr	p15, 0, tmp1, c7, c10, 4
 
-	ldr	tmp1, [r0, #PM_DATA_PMC]
-	str	tmp1, .pmc_base
-	ldr	tmp1, [r0, #PM_DATA_RAMC0]
-	str	tmp1, .sramc_base
-	ldr	tmp1, [r0, #PM_DATA_RAMC1]
-	str	tmp1, .sramc1_base
-	ldr	tmp1, [r0, #PM_DATA_MEMCTRL]
-	str	tmp1, .memtype
-	ldr	tmp1, [r0, #PM_DATA_MODE]
-	str	tmp1, .pm_mode
+	mov	pm_data, r0
 
 	/* Active the self-refresh mode */
 	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
 	bl	at91_sramc_self_refresh
 
-	ldr	r0, .pm_mode
+	ldr	r0, [pm_data, #PM_DATA_MODE]
 	tst	r0, #AT91_PM_SLOW_CLOCK
 	beq	skip_disable_main_clock
 
-	ldr	pmc, .pmc_base
+	ldr	pmc, [pm_data, #PM_DATA_PMC]
 
 	/* Save Master clock setting */
 	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
@@ -135,16 +127,16 @@ ENTRY(at91_pm_suspend_in_sram)
 	str	tmp1, [pmc, #AT91_CKGR_MOR]
 
 skip_disable_main_clock:
-	ldr	pmc, .pmc_base
+	ldr	pmc, [pm_data, #PM_DATA_PMC]
 
 	/* Wait for interrupt */
 	at91_cpu_idle
 
-	ldr	r0, .pm_mode
+	ldr	r0, [pm_data, #PM_DATA_MODE]
 	tst	r0, #AT91_PM_SLOW_CLOCK
 	beq	skip_enable_main_clock
 
-	ldr	pmc, .pmc_base
+	ldr	pmc, [pm_data, #PM_DATA_PMC]
 
 	/* Turn on the main oscillator */
 	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
@@ -195,8 +187,8 @@ ENDPROC(at91_pm_suspend_in_sram)
  */
 
 ENTRY(at91_sramc_self_refresh)
-	ldr	r1, .memtype
-	ldr	r2, .sramc_base
+	ldr	r1, [pm_data, #PM_DATA_MEMCTRL]
+	ldr	r2, [pm_data, #PM_DATA_RAMC0]
 
 	cmp	r1, #AT91_MEMCTRL_MC
 	bne	ddrc_sf
@@ -245,7 +237,7 @@ ddrc_sf:
 	str	r3, [r2, #AT91_DDRSDRC_LPR]
 
 	/* If using the 2nd ddr controller */
-	ldr	r2, .sramc1_base
+	ldr	r2, [pm_data, #PM_DATA_RAMC1]
 	cmp	r2, #0
 	beq	no_2nd_ddrc
 
@@ -277,7 +269,7 @@ ddrc_exit_sf:
 	str	r3, [r2, #AT91_DDRSDRC_LPR]
 
 	/* If using the 2nd ddr controller */
-	ldr	r2, .sramc1_base
+	ldr	r2, [pm_data, #PM_DATA_RAMC1]
 	cmp	r2, #0
 	ldrne	r3, .saved_sam9_mdr1
 	strne	r3, [r2, #AT91_DDRSDRC_MDR]
@@ -308,16 +300,6 @@ exit_sramc_sf:
 	mov	pc, lr
 ENDPROC(at91_sramc_self_refresh)
 
-.pmc_base:
-	.word 0
-.sramc_base:
-	.word 0
-.sramc1_base:
-	.word 0
-.memtype:
-	.word 0
-.pm_mode:
-	.word 0
 .saved_mckr:
 	.word 0
 .saved_pllar:
-- 
2.11.0

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

* [PATCH 06/13] ARM: at91: pm: simplify at91rm9200_standby
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (4 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 05/13] ARM: at91: pm: use struct members directly Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 07/13] ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1 memories Alexandre Belloni
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Since 2008, AT91_MC_SDRAMC_LPR is set to 0 at kernel initialization. There
is no use saving, changing and restoring it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 90b78ad20a97..d673996bed77 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -222,20 +222,15 @@ static void at91_pm_set_standby(void (*at91_standby)(void))
  */
 static void at91rm9200_standby(void)
 {
-	u32 lpr = at91_ramc_read(0, AT91_MC_SDRAMC_LPR);
-
 	asm volatile(
 		"b    1f\n\t"
 		".align    5\n\t"
 		"1:  mcr    p15, 0, %0, c7, c10, 4\n\t"
-		"    str    %0, [%1, %2]\n\t"
-		"    str    %3, [%1, %4]\n\t"
+		"    str    %2, [%1, %3]\n\t"
 		"    mcr    p15, 0, %0, c7, c0, 4\n\t"
-		"    str    %5, [%1, %2]"
 		:
-		: "r" (0), "r" (pm_data.ramc[0]), "r" (AT91_MC_SDRAMC_LPR),
-		  "r" (1), "r" (AT91_MC_SDRAMC_SRR),
-		  "r" (lpr));
+		: "r" (0), "r" (pm_data.ramc[0]),
+		  "r" (1), "r" (AT91_MC_SDRAMC_SRR));
 }
 
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
-- 
2.11.0

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

* [PATCH 07/13] ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1 memories.
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (5 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 06/13] ARM: at91: pm: simplify at91rm9200_standby Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 08/13] ARM: at91: pm: tie the memory controller type to the ramc id Alexandre Belloni
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

As already explained for pm_suspend.S, the DDRSDR controller fails to put
LPDDR1 memories in self-refresh. Force the controller to think it has DDR2
memories during the self-refresh period, as the DDR2 self-refresh spec is
equivalent to LPDDR1, and is correctly implemented in the controller.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index d673996bed77..d4a444c4c38f 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -241,12 +241,27 @@ static void at91_ddr_standby(void)
 	/* Those two values allow us to delay self-refresh activation
 	 * to the maximum. */
 	u32 lpr0, lpr1 = 0;
+	u32 mdr, saved_mdr0, saved_mdr1 = 0;
 	u32 saved_lpr0, saved_lpr1 = 0;
 
+	/* LPDDR1 --> force DDR2 mode during self-refresh */
+	saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR);
+	if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
+		mdr = saved_mdr0 & ~AT91_DDRSDRC_MD;
+		mdr |= AT91_DDRSDRC_MD_DDR2;
+		at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr);
+	}
+
 	if (pm_data.ramc[1]) {
 		saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
 		lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
 		lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+		saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR);
+		if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
+			mdr = saved_mdr1 & ~AT91_DDRSDRC_MD;
+			mdr |= AT91_DDRSDRC_MD_DDR2;
+			at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr);
+		}
 	}
 
 	saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
@@ -260,9 +275,12 @@ static void at91_ddr_standby(void)
 
 	cpu_do_idle();
 
+	at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0);
 	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-	if (pm_data.ramc[1])
+	if (pm_data.ramc[1]) {
+		at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1);
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
+	}
 }
 
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
-- 
2.11.0

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

* [PATCH 08/13] ARM: at91: pm: tie the memory controller type to the ramc id
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (6 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 07/13] ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1 memories Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 09/13] ARM: at91: pm: tie the USB clock mask to the pmc Alexandre Belloni
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Instead of rely on the SoC type to select the memory controller type, use
the device tree ids as they are parsed anyway.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index d4a444c4c38f..b6448043ee7a 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -313,11 +313,22 @@ static void at91sam9_sdram_standby(void)
 		at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
+struct ramc_info {
+	void (*standby)(void);
+	unsigned int memctrl;
+};
+
+static const struct ramc_info ramc_infos[] __initconst = {
+	{ .standby = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC},
+	{ .standby = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC},
+	{ .standby = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
+};
+
 static const struct of_device_id const ramc_ids[] __initconst = {
-	{ .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
-	{ .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
-	{ .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
-	{ .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
+	{ .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] },
+	{ .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
+	{ .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
+	{ .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[2] },
 	{ /*sentinel*/ }
 };
 
@@ -327,14 +338,17 @@ static __init void at91_dt_ramc(void)
 	const struct of_device_id *of_id;
 	int idx = 0;
 	const void *standby = NULL;
+	const struct ramc_info *ramc;
 
 	for_each_matching_node_and_match(np, ramc_ids, &of_id) {
 		pm_data.ramc[idx] = of_iomap(np, 0);
 		if (!pm_data.ramc[idx])
 			panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
 
+		ramc = of_id->data;
 		if (!standby)
-			standby = of_id->data;
+			standby = ramc->standby;
+		pm_data.memctrl = ramc->memctrl;
 
 		idx++;
 	}
@@ -457,7 +471,6 @@ void __init at91rm9200_pm_init(void)
 	at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0);
 
 	pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP;
-	pm_data.memctrl = AT91_MEMCTRL_MC;
 
 	at91_pm_init(at91rm9200_idle);
 }
@@ -465,7 +478,6 @@ void __init at91rm9200_pm_init(void)
 void __init at91sam9260_pm_init(void)
 {
 	at91_dt_ramc();
-	pm_data.memctrl = AT91_MEMCTRL_SDRAMC;
 	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
 	at91_pm_init(at91sam9_idle);
 }
@@ -474,7 +486,6 @@ void __init at91sam9g45_pm_init(void)
 {
 	at91_dt_ramc();
 	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP;
-	pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
 	at91_pm_init(at91sam9_idle);
 }
 
@@ -482,7 +493,6 @@ void __init at91sam9x5_pm_init(void)
 {
 	at91_dt_ramc();
 	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-	pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
 	at91_pm_init(at91sam9_idle);
 }
 
@@ -490,6 +500,5 @@ void __init sama5_pm_init(void)
 {
 	at91_dt_ramc();
 	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-	pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
 	at91_pm_init(NULL);
 }
-- 
2.11.0

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

* [PATCH 09/13] ARM: at91: pm: tie the USB clock mask to the pmc
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (7 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 08/13] ARM: at91: pm: tie the memory controller type to the ramc id Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 10/13] ARM: at91: pm: merge all at91sam9*_pm_init Alexandre Belloni
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

The USB clocks mask (uhp_udp_mask) depend on the pmc. Tie it to the pmc id
instead of the SoC.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index b6448043ee7a..c0ef1742135c 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -425,31 +425,46 @@ static void __init at91_pm_sram_init(void)
 			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
 }
 
+struct pmc_info {
+	unsigned long uhp_udp_mask;
+};
+
+static const struct pmc_info pmc_infos[] __initconst = {
+	{ .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP },
+	{ .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP },
+	{ .uhp_udp_mask = AT91SAM926x_PMC_UHP },
+};
+
 static const struct of_device_id atmel_pmc_ids[] __initconst = {
-	{ .compatible = "atmel,at91rm9200-pmc"  },
-	{ .compatible = "atmel,at91sam9260-pmc" },
-	{ .compatible = "atmel,at91sam9g45-pmc" },
-	{ .compatible = "atmel,at91sam9n12-pmc" },
-	{ .compatible = "atmel,at91sam9x5-pmc" },
-	{ .compatible = "atmel,sama5d3-pmc" },
-	{ .compatible = "atmel,sama5d2-pmc" },
+	{ .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] },
+	{ .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] },
+	{ .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] },
+	{ .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] },
+	{ .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] },
+	{ .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
+	{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
 	{ /* sentinel */ },
 };
 
 static void __init at91_pm_init(void (*pm_idle)(void))
 {
 	struct device_node *pmc_np;
+	const struct of_device_id *of_id;
+	const struct pmc_info *pmc;
 
 	if (at91_cpuidle_device.dev.platform_data)
 		platform_device_register(&at91_cpuidle_device);
 
-	pmc_np = of_find_matching_node(NULL, atmel_pmc_ids);
+	pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
 	pm_data.pmc = of_iomap(pmc_np, 0);
 	if (!pm_data.pmc) {
 		pr_err("AT91: PM not supported, PMC not found\n");
 		return;
 	}
 
+	pmc = of_id->data;
+	pm_data.uhp_udp_mask = pmc->uhp_udp_mask;
+
 	if (pm_idle)
 		arm_pm_idle = pm_idle;
 
@@ -470,35 +485,29 @@ void __init at91rm9200_pm_init(void)
 	 */
 	at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0);
 
-	pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP;
-
 	at91_pm_init(at91rm9200_idle);
 }
 
 void __init at91sam9260_pm_init(void)
 {
 	at91_dt_ramc();
-	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
 	at91_pm_init(at91sam9_idle);
 }
 
 void __init at91sam9g45_pm_init(void)
 {
 	at91_dt_ramc();
-	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP;
 	at91_pm_init(at91sam9_idle);
 }
 
 void __init at91sam9x5_pm_init(void)
 {
 	at91_dt_ramc();
-	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
 	at91_pm_init(at91sam9_idle);
 }
 
 void __init sama5_pm_init(void)
 {
 	at91_dt_ramc();
-	pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
 	at91_pm_init(NULL);
 }
-- 
2.11.0

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

* [PATCH 10/13] ARM: at91: pm: merge all at91sam9*_pm_init
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (8 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 09/13] ARM: at91: pm: tie the USB clock mask to the pmc Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 11/13] ARM: at91: pm: remove at91_pm_set_standby Alexandre Belloni
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

The PM initialization is now identical for all at91sam9. Merge the
functions.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/at91sam9.c | 45 +++----------------------------------------
 arch/arm/mach-at91/generic.h  |  8 ++------
 arch/arm/mach-at91/pm.c       | 14 +-------------
 3 files changed, 6 insertions(+), 61 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c
index ba28e9cc584d..c089bfd0dc2f 100644
--- a/arch/arm/mach-at91/at91sam9.c
+++ b/arch/arm/mach-at91/at91sam9.c
@@ -52,7 +52,7 @@ static const struct at91_soc at91sam9_socs[] = {
 	{ /* sentinel */ },
 };
 
-static void __init at91sam9_common_init(void)
+static void __init at91sam9_init(void)
 {
 	struct soc_device *soc;
 	struct device *soc_dev = NULL;
@@ -62,12 +62,8 @@ static void __init at91sam9_common_init(void)
 		soc_dev = soc_device_to_device(soc);
 
 	of_platform_default_populate(NULL, NULL, soc_dev);
-}
 
-static void __init at91sam9_dt_device_init(void)
-{
-	at91sam9_common_init();
-	at91sam9260_pm_init();
+	at91sam9_pm_init();
 }
 
 static const char *const at91_dt_board_compat[] __initconst = {
@@ -77,41 +73,6 @@ static const char *const at91_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9")
 	/* Maintainer: Atmel */
-	.init_machine	= at91sam9_dt_device_init,
+	.init_machine	= at91sam9_init,
 	.dt_compat	= at91_dt_board_compat,
 MACHINE_END
-
-static void __init at91sam9g45_dt_device_init(void)
-{
-	at91sam9_common_init();
-	at91sam9g45_pm_init();
-}
-
-static const char *const at91sam9g45_board_compat[] __initconst = {
-	"atmel,at91sam9g45",
-	NULL
-};
-
-DT_MACHINE_START(at91sam9g45_dt, "Atmel AT91SAM9G45")
-	/* Maintainer: Atmel */
-	.init_machine	= at91sam9g45_dt_device_init,
-	.dt_compat	= at91sam9g45_board_compat,
-MACHINE_END
-
-static void __init at91sam9x5_dt_device_init(void)
-{
-	at91sam9_common_init();
-	at91sam9x5_pm_init();
-}
-
-static const char *const at91sam9x5_board_compat[] __initconst = {
-	"atmel,at91sam9x5",
-	"atmel,at91sam9n12",
-	NULL
-};
-
-DT_MACHINE_START(at91sam9x5_dt, "Atmel AT91SAM9")
-	/* Maintainer: Atmel */
-	.init_machine	= at91sam9x5_dt_device_init,
-	.dt_compat	= at91sam9x5_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 28ca57a2060f..f1ead0f13c19 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -13,15 +13,11 @@
 
 #ifdef CONFIG_PM
 extern void __init at91rm9200_pm_init(void);
-extern void __init at91sam9260_pm_init(void);
-extern void __init at91sam9g45_pm_init(void);
-extern void __init at91sam9x5_pm_init(void);
+extern void __init at91sam9_pm_init(void);
 extern void __init sama5_pm_init(void);
 #else
 static inline void __init at91rm9200_pm_init(void) { }
-static inline void __init at91sam9260_pm_init(void) { }
-static inline void __init at91sam9g45_pm_init(void) { }
-static inline void __init at91sam9x5_pm_init(void) { }
+static inline void __init at91sam9_pm_init(void) { }
 static inline void __init sama5_pm_init(void) { }
 #endif
 
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index c0ef1742135c..009b57f3a62e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -488,19 +488,7 @@ void __init at91rm9200_pm_init(void)
 	at91_pm_init(at91rm9200_idle);
 }
 
-void __init at91sam9260_pm_init(void)
-{
-	at91_dt_ramc();
-	at91_pm_init(at91sam9_idle);
-}
-
-void __init at91sam9g45_pm_init(void)
-{
-	at91_dt_ramc();
-	at91_pm_init(at91sam9_idle);
-}
-
-void __init at91sam9x5_pm_init(void)
+void __init at91sam9_pm_init(void)
 {
 	at91_dt_ramc();
 	at91_pm_init(at91sam9_idle);
-- 
2.11.0

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

* [PATCH 11/13] ARM: at91: pm: remove at91_pm_set_standby
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (9 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 10/13] ARM: at91: pm: merge all at91sam9*_pm_init Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 12/13] ARM: at91: pm: use C functions for standby Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 13/13] ARM: at91: pm: Allow PM even if SRAM allocation failed Alexandre Belloni
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Merge at91_pm_set_standby() in at91_dt_ramc as this is the only callsite.
That moves it to the init section.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 009b57f3a62e..553bcfc5545e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -205,12 +205,6 @@ static struct platform_device at91_cpuidle_device = {
 	.name = "cpuidle-at91",
 };
 
-static void at91_pm_set_standby(void (*at91_standby)(void))
-{
-	if (at91_standby)
-		at91_cpuidle_device.dev.platform_data = at91_standby;
-}
-
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
  * terminate self-refresh automatically on the next SDRAM access.
@@ -337,7 +331,7 @@ static __init void at91_dt_ramc(void)
 	struct device_node *np;
 	const struct of_device_id *of_id;
 	int idx = 0;
-	const void *standby = NULL;
+	void *standby = NULL;
 	const struct ramc_info *ramc;
 
 	for_each_matching_node_and_match(np, ramc_ids, &of_id) {
@@ -361,7 +355,7 @@ static __init void at91_dt_ramc(void)
 		return;
 	}
 
-	at91_pm_set_standby(standby);
+	at91_cpuidle_device.dev.platform_data = standby;
 }
 
 static void at91rm9200_idle(void)
-- 
2.11.0

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

* [PATCH 12/13] ARM: at91: pm: use C functions for standby
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (10 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 11/13] ARM: at91: pm: remove at91_pm_set_standby Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  2017-02-02 14:45 ` [PATCH 13/13] ARM: at91: pm: Allow PM even if SRAM allocation failed Alexandre Belloni
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

When going to standby, there is no point calling the assembly function
at91_pm_suspend_in_sram(). It does exactly the same operations as the C
standby functions.
This allows to remove a few loads and tests in the suspend/resume path.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c              |  8 +++++---
 arch/arm/mach-at91/pm.h              |  4 +---
 arch/arm/mach-at91/pm_data-offsets.c |  1 -
 arch/arm/mach-at91/pm_suspend.S      | 14 --------------
 4 files changed, 6 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 553bcfc5545e..1992ad8b1c3d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -125,12 +125,13 @@ extern u32 at91_pm_suspend_in_sram_sz;
 
 static void at91_pm_suspend(suspend_state_t state)
 {
-	pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0;
-
 	flush_cache_all();
 	outer_disable();
 
-	at91_suspend_sram_fn(&pm_data);
+	if (state == PM_SUSPEND_MEM)
+		at91_suspend_sram_fn(&pm_data);
+	else
+		pm_data.standby();
 
 	outer_resume();
 }
@@ -342,6 +343,7 @@ static __init void at91_dt_ramc(void)
 		ramc = of_id->data;
 		if (!standby)
 			standby = ramc->standby;
+		pm_data.standby = standby;
 		pm_data.memctrl = ramc->memctrl;
 
 		idx++;
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index fc0f7d048187..2317e39248b7 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,15 +21,13 @@
 #define AT91_MEMCTRL_SDRAMC	1
 #define AT91_MEMCTRL_DDRSDR	2
 
-#define	AT91_PM_SLOW_CLOCK	0x01
-
 #ifndef __ASSEMBLY__
 struct at91_pm_data {
 	void __iomem *pmc;
 	void __iomem *ramc[2];
 	unsigned long uhp_udp_mask;
 	unsigned int memctrl;
-	unsigned int mode;
+	void (*standby)(void);
 };
 #endif
 
diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c
index 30302cb16df0..c4e6d648644f 100644
--- a/arch/arm/mach-at91/pm_data-offsets.c
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -8,6 +8,5 @@ int main(void)
 	DEFINE(PM_DATA_RAMC0,		offsetof(struct at91_pm_data, ramc[0]));
 	DEFINE(PM_DATA_RAMC1,		offsetof(struct at91_pm_data, ramc[1]));
 	DEFINE(PM_DATA_MEMCTRL,	offsetof(struct at91_pm_data, memctrl));
-	DEFINE(PM_DATA_MODE,		offsetof(struct at91_pm_data, mode));
 	return 0;
 }
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 3ee282c051e0..a8b32faaea5b 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -94,10 +94,6 @@ ENTRY(at91_pm_suspend_in_sram)
 	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
 	bl	at91_sramc_self_refresh
 
-	ldr	r0, [pm_data, #PM_DATA_MODE]
-	tst	r0, #AT91_PM_SLOW_CLOCK
-	beq	skip_disable_main_clock
-
 	ldr	pmc, [pm_data, #PM_DATA_PMC]
 
 	/* Save Master clock setting */
@@ -126,18 +122,9 @@ ENTRY(at91_pm_suspend_in_sram)
 	orr	tmp1, tmp1, #AT91_PMC_KEY
 	str	tmp1, [pmc, #AT91_CKGR_MOR]
 
-skip_disable_main_clock:
-	ldr	pmc, [pm_data, #PM_DATA_PMC]
-
 	/* Wait for interrupt */
 	at91_cpu_idle
 
-	ldr	r0, [pm_data, #PM_DATA_MODE]
-	tst	r0, #AT91_PM_SLOW_CLOCK
-	beq	skip_enable_main_clock
-
-	ldr	pmc, [pm_data, #PM_DATA_PMC]
-
 	/* Turn on the main oscillator */
 	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
 	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
@@ -166,7 +153,6 @@ skip_disable_main_clock:
 
 	wait_mckrdy
 
-skip_enable_main_clock:
 	/* Exit the self-refresh mode */
 	mov	r0, #SRAMC_SELF_FRESH_EXIT
 	bl	at91_sramc_self_refresh
-- 
2.11.0

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

* [PATCH 13/13] ARM: at91: pm: Allow PM even if SRAM allocation failed
  2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
                   ` (11 preceding siblings ...)
  2017-02-02 14:45 ` [PATCH 12/13] ARM: at91: pm: use C functions for standby Alexandre Belloni
@ 2017-02-02 14:45 ` Alexandre Belloni
  12 siblings, 0 replies; 14+ messages in thread
From: Alexandre Belloni @ 2017-02-02 14:45 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Boris Brezillon, Ludovic Desroches, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

No that C functions are used, we can always enabled PM, putting the SDRAM
in self refresh but not disabling the main clock.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 12 +++++++-----
 arch/arm/mach-at91/pm.h |  3 +++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 1992ad8b1c3d..a4d9f3f76ca4 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -128,7 +128,7 @@ static void at91_pm_suspend(suspend_state_t state)
 	flush_cache_all();
 	outer_disable();
 
-	if (state == PM_SUSPEND_MEM)
+	if ((state == PM_SUSPEND_MEM) && (pm_data.states & AT91_PM_SLOW_CLOCK))
 		at91_suspend_sram_fn(&pm_data);
 	else
 		pm_data.standby();
@@ -466,10 +466,12 @@ static void __init at91_pm_init(void (*pm_idle)(void))
 
 	at91_pm_sram_init();
 
-	if (at91_suspend_sram_fn)
-		suspend_set_ops(&at91_pm_ops);
-	else
-		pr_info("AT91: PM not supported, due to no SRAM allocated\n");
+	if (at91_suspend_sram_fn) {
+		pm_data.states |= AT91_PM_SLOW_CLOCK;
+		pr_info("AT91: PM: Slow clock mode enabled\n");
+	}
+
+	suspend_set_ops(&at91_pm_ops);
 }
 
 void __init at91rm9200_pm_init(void)
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 2317e39248b7..2f5ec4da3416 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,6 +21,8 @@
 #define AT91_MEMCTRL_SDRAMC	1
 #define AT91_MEMCTRL_DDRSDR	2
 
+#define AT91_PM_SLOW_CLOCK	BIT(0)
+
 #ifndef __ASSEMBLY__
 struct at91_pm_data {
 	void __iomem *pmc;
@@ -28,6 +30,7 @@ struct at91_pm_data {
 	unsigned long uhp_udp_mask;
 	unsigned int memctrl;
 	void (*standby)(void);
+	unsigned int states;
 };
 #endif
 
-- 
2.11.0

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

end of thread, other threads:[~2017-02-02 14:49 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-02 14:45 [PATCH 00/13] ARM: at91; pm: cleanup Alexandre Belloni
2017-02-02 14:45 ` [PATCH 01/13] ARM: at91: pm: cleanup headers Alexandre Belloni
2017-02-02 14:45 ` [PATCH 02/13] ARM: at91: pm: move at91_ramc_read/write to pm.c Alexandre Belloni
2017-02-02 14:45 ` [PATCH 03/13] ARM: at91: pm: Move global variables into at91_pm_data Alexandre Belloni
2017-02-02 14:45 ` [PATCH 04/13] ARM: at91: pm: use struct at91_pm_data in pm_suspend.S Alexandre Belloni
2017-02-02 14:45 ` [PATCH 05/13] ARM: at91: pm: use struct members directly Alexandre Belloni
2017-02-02 14:45 ` [PATCH 06/13] ARM: at91: pm: simplify at91rm9200_standby Alexandre Belloni
2017-02-02 14:45 ` [PATCH 07/13] ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1 memories Alexandre Belloni
2017-02-02 14:45 ` [PATCH 08/13] ARM: at91: pm: tie the memory controller type to the ramc id Alexandre Belloni
2017-02-02 14:45 ` [PATCH 09/13] ARM: at91: pm: tie the USB clock mask to the pmc Alexandre Belloni
2017-02-02 14:45 ` [PATCH 10/13] ARM: at91: pm: merge all at91sam9*_pm_init Alexandre Belloni
2017-02-02 14:45 ` [PATCH 11/13] ARM: at91: pm: remove at91_pm_set_standby Alexandre Belloni
2017-02-02 14:45 ` [PATCH 12/13] ARM: at91: pm: use C functions for standby Alexandre Belloni
2017-02-02 14:45 ` [PATCH 13/13] ARM: at91: pm: Allow PM even if SRAM allocation failed Alexandre Belloni

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).