Hi,
This is v2 of the at91 PM cleanup.
The main goal is to use a struct to pass arguments between the C and the
assembly part. This is required to add further functionalities (coming in a
later series).
A bit of refactorization also allows to remove a some initialization in
at91sam9.c
Changes in v2:
- rebased on top of v4.11-rc4 because of a dependency on a fix
- added a patch to correct a typo
- due to an errata on sama5d4, I've left out the following patches for now:
ARM: at91: pm: use struct members directly
ARM: at91: pm: use C functions for standby
ARM: at91: pm: Allow PM even if SRAM allocation failed
I'll get back to those later.
- in preparation of the sama5d4 workaround, renamed standby to idle as the
standby functions are actually used for cpuidle but not standby
Alexandre Belloni (11):
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: 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: correct typo
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 | 199 +++++++++++++++++------------------
arch/arm/mach-at91/pm.h | 24 ++---
arch/arm/mach-at91/pm_data-offsets.c | 13 +++
arch/arm/mach-at91/pm_suspend.S | 31 +++---
7 files changed, 172 insertions(+), 181 deletions(-)
create mode 100644 arch/arm/mach-at91/pm_data-offsets.c
--
2.11.0
Those macros are only used in pm.c, move them there so we can remove the
test on __ASSEMBLY__.
Signed-off-by: Alexandre Belloni <[email protected]>
---
arch/arm/mach-at91/pm.c | 6 ++++++
arch/arm/mach-at91/pm.h | 8 --------
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 9e2b5c1e503e..41789aa4df86 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -45,6 +45,12 @@ static struct {
} at91_pm_data;
static 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 bf980c6ef294..8eed156ef19a 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -17,14 +17,6 @@
#include <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.h>
-#ifndef __ASSEMBLY__
-#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
Instead of having separate global variables to hold IP addresses, move them
to struct at91_pm_data.
Signed-off-by: Alexandre Belloni <[email protected]>
---
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 41789aa4df86..c780dda3b604 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;
-static 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);
}
@@ -308,7 +306,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;
@@ -320,13 +318,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);
}
@@ -346,8 +344,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)
@@ -373,12 +371,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();
}
@@ -447,8 +445,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
Add a missing bracket at the end of Anti's email
Signed-off-by: Alexandre Belloni <[email protected]>
---
arch/arm/mach-at91/pm_suspend.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index ed317657e760..96781daa671a 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -4,7 +4,7 @@
* Copyright (C) 2006 Savin Zlobec
*
* AT91SAM9 support:
- * Copyright (C) 2007 Anti Sullin <[email protected]
+ * Copyright (C) 2007 Anti Sullin <[email protected]>
*
* 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
--
2.11.0
The PM initialization is now identical for all at91sam9. Merge the
functions.
Signed-off-by: Alexandre Belloni <[email protected]>
---
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 a7c047f0d21f..dedfe9038336 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -505,19 +505,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
The USB clocks mask (uhp_udp_mask) depends on the pmc. Tie it to the pmc id
instead of the SoC.
Signed-off-by: Alexandre Belloni <[email protected]>
---
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 ddf62a006635..a7c047f0d21f 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -442,31 +442,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;
@@ -487,35 +502,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
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 <[email protected]>
---
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 a35b1541b328..3d68d93c11c7 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
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 <[email protected]>
---
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 c780dda3b604..a35b1541b328 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);
}
@@ -306,7 +294,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;
@@ -318,13 +306,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);
}
@@ -344,8 +332,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)
@@ -371,12 +359,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();
}
@@ -445,8 +433,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;
}
@@ -471,8 +459,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);
}
@@ -480,31 +468,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
Remove unnecessary header inclusions and reorder the remaining ones.
Signed-off-by: Alexandre Belloni <[email protected]>
---
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 a277981f414d..9e2b5c1e503e 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
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 <[email protected]>
---
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 dedfe9038336..2cd27c830ab6 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.
@@ -354,7 +348,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) {
@@ -378,7 +372,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
Instead of relying 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 <[email protected]>
---
arch/arm/mach-at91/pm.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 488549bc2bed..ddf62a006635 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -329,11 +329,23 @@ static void at91sam9_sdram_standby(void)
at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
}
+struct ramc_info {
+ void (*idle)(void);
+ unsigned int memctrl;
+};
+
+static const struct ramc_info ramc_infos[] __initconst = {
+ { .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC},
+ { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC},
+ { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
+ { .idle = sama5d3_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 = sama5d3_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[3] },
{ /*sentinel*/ }
};
@@ -343,14 +355,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->idle;
+ pm_data.memctrl = ramc->memctrl;
idx++;
}
@@ -473,7 +488,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);
}
@@ -481,7 +495,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);
}
@@ -490,7 +503,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);
}
@@ -498,7 +510,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);
}
@@ -506,6 +517,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
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 <[email protected]>
---
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 3d68d93c11c7..488549bc2bed 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);
+ }
}
static void sama5d3_ddr_standby(void)
--
2.11.0
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:19
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 01/11] ARM: at91: pm: Cleanup headers
>
> Remove unnecessary header inclusions and reorder the remaining ones.
>
> Signed-off-by: Alexandre Belloni <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> a277981f414d..9e2b5c1e503e 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
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:19
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 02/11] ARM: at91: pm: Move at91_ramc_read/write to pm.c
>
> Those macros are only used in pm.c, move them there so we can remove the test
> on __ASSEMBLY__.
>
> Signed-off-by: Alexandre Belloni <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> arch/arm/mach-at91/pm.c | 6 ++++++
> arch/arm/mach-at91/pm.h | 8 --------
> 2 files changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
> 9e2b5c1e503e..41789aa4df86 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -45,6 +45,12 @@ static struct {
> } at91_pm_data;
>
> static 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
> bf980c6ef294..8eed156ef19a 100644
> --- a/arch/arm/mach-at91/pm.h
> +++ b/arch/arm/mach-at91/pm.h
> @@ -17,14 +17,6 @@
> #include <soc/at91/at91sam9_ddrsdr.h>
> #include <soc/at91/at91sam9_sdramc.h>
>
> -#ifndef __ASSEMBLY__
> -#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
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 03/11] ARM: at91: pm: Move global variables into
> at91_pm_data
>
> Instead of having separate global variables to hold IP addresses, move them to
> struct at91_pm_data.
>
> Signed-off-by: Alexandre Belloni <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> 41789aa4df86..c780dda3b604 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;
>
> -static 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); }
>
> @@ -308,7 +306,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; @@ -320,13
> +318,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); }
>
> @@ -346,8 +344,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)
> @@ -373,12 +371,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();
> }
>
> @@ -447,8 +445,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
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 10/11] ARM: at91: pm: Remove at91_pm_set_standby
>
> 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 <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> dedfe9038336..2cd27c830ab6 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.
> @@ -354,7 +348,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) { @@ -378,7
> +372,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
Best Regards,
Wenyou Yang
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 08/11] ARM: at91: pm: Tie the USB clock mask to the pmc
>
> The USB clocks mask (uhp_udp_mask) depends on the pmc. Tie it to the pmc id
> instead of the SoC.
>
> Signed-off-by: Alexandre Belloni <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> ddf62a006635..a7c047f0d21f 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -442,31 +442,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;
>
> @@ -487,35 +502,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
Best Regards,
Wenyou Yang
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 09/11] ARM: at91: pm: Merge all at91sam9*_pm_init
>
> The PM initialization is now identical for all at91sam9. Merge the functions.
>
> Signed-off-by: Alexandre Belloni <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> a7c047f0d21f..dedfe9038336 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -505,19 +505,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
Best Regards,
Wenyou Yang
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 04/11] ARM: at91: pm: Use struct at91_pm_data in
> pm_suspend.S
>
> 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 <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> c780dda3b604..a35b1541b328 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); }
>
> @@ -306,7 +294,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; @@ -318,13
> +306,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); }
>
> @@ -344,8 +332,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)
> @@ -371,12 +359,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();
> }
>
> @@ -445,8 +433,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;
> }
> @@ -471,8 +459,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);
> }
> @@ -480,31 +468,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
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 06/11] ARM: at91: pm: Workaround DDRSDRC self-refresh
> bug with LPDDR1 memories.
>
> 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 <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> 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
> 3d68d93c11c7..488549bc2bed 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);
> + }
> }
>
> static void sama5d3_ddr_standby(void)
> --
> 2.11.0
> -----Original Message-----
> From: Alexandre Belloni [mailto:[email protected]]
> Sent: 2017??3??28?? 19:20
> To: Nicolas Ferre - M43238 <[email protected]>
> Cc: [email protected]; [email protected]; Boris
> Brezillon <[email protected]>; Wenyou Yang - A41535
> <[email protected]>; Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> Subject: [PATCH v2 07/11] ARM: at91: pm: Tie the memory controller type to the
> ramc id
>
> Instead of relying 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 <[email protected]>
Acked-by: Wenyou Yang <[email protected]>
> ---
> arch/arm/mach-at91/pm.c | 30 ++++++++++++++++++++----------
> 1 file changed, 20 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
> 488549bc2bed..ddf62a006635 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -329,11 +329,23 @@ static void at91sam9_sdram_standby(void)
> at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); }
>
> +struct ramc_info {
> + void (*idle)(void);
> + unsigned int memctrl;
> +};
> +
> +static const struct ramc_info ramc_infos[] __initconst = {
> + { .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC},
> + { .idle = at91sam9_sdram_standby, .memctrl =
> AT91_MEMCTRL_SDRAMC},
> + { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
> + { .idle = sama5d3_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 = sama5d3_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[3] },
> { /*sentinel*/ }
> };
>
> @@ -343,14 +355,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->idle;
> + pm_data.memctrl = ramc->memctrl;
>
> idx++;
> }
> @@ -473,7 +488,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);
> }
> @@ -481,7 +495,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);
> }
> @@ -490,7 +503,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);
> }
>
> @@ -498,7 +510,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);
> }
>
> @@ -506,6 +517,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
Best Regards,
Wenyou Yang