[PATCH v3 24/24] ARM: at91: pm: add sama7g5 shdwc

2021-04-15 Thread Claudiu Beznea
Add SAMA7G5 SHDWC.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 24d5fd06d487..d6cfe7c4bb00 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -794,6 +794,7 @@ static int __init at91_pm_backup_init(void)
 static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
+   { .compatible = "microchip,sama7g5-shdwc" },
{ /* sentinel. */ }
 };
 
-- 
2.25.1



[PATCH v3 22/24] ARM: at91: sama7: introduce sama7 SoC family

2021-04-15 Thread Claudiu Beznea
From: Eugen Hristev 

Introduce new family of SoCs, sama7, and first SoC, sama7g5.

Signed-off-by: Eugen Hristev 
[claudiu.bez...@microchip.com: keep only the sama7_dt]
Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/Makefile |  1 +
 arch/arm/mach-at91/sama7.c  | 32 
 2 files changed, 33 insertions(+)
 create mode 100644 arch/arm/mach-at91/sama7.c

diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index f565490f1b70..522b680b6446 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_AT91RM9200)+= at91rm9200.o
 obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
 obj-$(CONFIG_SOC_SAM9X60)  += sam9x60.o
 obj-$(CONFIG_SOC_SAMA5)+= sama5.o
+obj-$(CONFIG_SOC_SAMA7)+= sama7.o
 obj-$(CONFIG_SOC_SAMV7)+= samv7.o
 
 # Power Management
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
new file mode 100644
index ..19d7bcbc97f1
--- /dev/null
+++ b/arch/arm/mach-at91/sama7.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Setup code for SAMA7
+ *
+ * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "generic.h"
+
+static void __init sama7_dt_device_init(void)
+{
+   of_platform_default_populate(NULL, NULL, NULL);
+}
+
+static const char *const sama7_dt_board_compat[] __initconst = {
+   "microchip,sama7",
+   NULL
+};
+
+DT_MACHINE_START(sama7_dt, "Microchip SAMA7")
+   /* Maintainer: Microchip */
+   .init_machine   = sama7_dt_device_init,
+   .dt_compat  = sama7_dt_board_compat,
+MACHINE_END
+
-- 
2.25.1



[PATCH v3 23/24] ARM: at91: pm: add pm support for SAMA7G5

2021-04-15 Thread Claudiu Beznea
Add support for SAMA7G5 power management modes: standby, ulp0, ulp1, backup.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/generic.h |  2 ++
 arch/arm/mach-at91/pm.c  | 37 
 arch/arm/mach-at91/sama7.c   |  1 +
 3 files changed, 40 insertions(+)

diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 0a4cdcb4985b..0c3960a8b3eb 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -14,12 +14,14 @@ extern void __init at91sam9_pm_init(void);
 extern void __init sam9x60_pm_init(void);
 extern void __init sama5_pm_init(void);
 extern void __init sama5d2_pm_init(void);
+extern void __init sama7_pm_init(void);
 #else
 static inline void __init at91rm9200_pm_init(void) { }
 static inline void __init at91sam9_pm_init(void) { }
 static inline void __init sam9x60_pm_init(void) { }
 static inline void __init sama5_pm_init(void) { }
 static inline void __init sama5d2_pm_init(void) { }
+static inline void __init sama7_pm_init(void) { }
 #endif
 
 #endif /* _AT91_GENERIC_H */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index f4e66a7c7d18..24d5fd06d487 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -152,6 +152,17 @@ static const struct of_device_id sam9x60_ws_ids[] = {
{ /* sentinel */ }
 };
 
+static const struct of_device_id sama7g5_ws_ids[] = {
+   { .compatible = "atmel,at91sam9x5-rtc", .data = _info[1] },
+   { .compatible = "microchip,sama7g5-ohci",   .data = _info[2] },
+   { .compatible = "usb-ohci", .data = _info[2] },
+   { .compatible = "atmel,at91sam9g45-ehci",   .data = _info[2] },
+   { .compatible = "usb-ehci", .data = _info[2] },
+   { .compatible = "microchip,sama7g5-sdhci",  .data = _info[3] },
+   { .compatible = "atmel,at91sam9260-rtt",.data = _info[4] },
+   { /* sentinel */ }
+};
+
 static int at91_pm_config_ws(unsigned int pm_mode, bool set)
 {
const struct wakeup_source_info *wsi;
@@ -1103,6 +1114,32 @@ void __init sama5d2_pm_init(void)
soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
 }
 
+void __init sama7_pm_init(void)
+{
+   static const int modes[] __initconst = {
+   AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP1, AT91_PM_BACKUP,
+   };
+   static const u32 iomaps[] __initconst = {
+   [AT91_PM_ULP0]  = AT91_PM_IOMAP(SFRBU),
+   [AT91_PM_ULP1]  = AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+   [AT91_PM_BACKUP]= AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+   };
+
+   if (!IS_ENABLED(CONFIG_SOC_SAMA7))
+   return;
+
+   at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
+
+   at91_dt_ramc(true);
+   at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
+   at91_pm_init(NULL);
+
+   soc_pm.ws_ids = sama7g5_ws_ids;
+   soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
+}
+
 static int __init at91_pm_modes_select(char *str)
 {
char *s;
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
index 19d7bcbc97f1..bd43733ede18 100644
--- a/arch/arm/mach-at91/sama7.c
+++ b/arch/arm/mach-at91/sama7.c
@@ -17,6 +17,7 @@
 static void __init sama7_dt_device_init(void)
 {
of_platform_default_populate(NULL, NULL, NULL);
+   sama7_pm_init();
 }
 
 static const char *const sama7_dt_board_compat[] __initconst = {
-- 
2.25.1



[PATCH v3 20/24] ARM: at91: pm: add backup mode support for SAMA7G5

2021-04-15 Thread Claudiu Beznea
Adapt at91_pm_backup_init() to work for SAMA7G5. Also, set the LPM pin
to shutdown controller. This will signal to PMIC that it needs to switch
to the state corresponding to backup mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 3 ++-
 arch/arm/mach-at91/pm_suspend.S | 7 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 91b4014d2e10..fcb20272d65d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -729,7 +729,8 @@ static int __init at91_pm_backup_init(void)
struct platform_device *pdev;
int ret = -ENODEV, located = 0;
 
-   if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
+   if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
+   !IS_ENABLED(CONFIG_SOC_SAMA7G5))
return -EPERM;
 
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 7396e18dd7e5..cbd61a3bcab1 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -106,6 +106,12 @@ lp_done_\ena:
 #endif
.endm
 
+   .macro at91_backup_set_lpm reg
+#ifdef CONFIG_SOC_SAMA7
+   orr \reg, \reg, #0x20
+#endif
+   .endm
+
.text
 
.arm
@@ -989,6 +995,7 @@ ulp_exit:
ldr r0, .shdwc
mov tmp1, #0xA500
add tmp1, tmp1, #0x1
+   at91_backup_set_lpm tmp1
str tmp1, [r0, #0]
 .endm
 
-- 
2.25.1



[PATCH v3 17/24] ARM: at91: pm: add sama7g5 ddr controller

2021-04-15 Thread Claudiu Beznea
Add SAMA7G5 DDR controller to the list of DDR controller compatibles.
At the moment there is no standby support. Adapt the code for this.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 65e13769cf50..5dc942a2012d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -548,6 +548,7 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ .compatible = "atmel,at91sam9260-sdramc", .data = _infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = _infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = _infos[3] },
+   { .compatible = "microchip,sama7g5-uddrc", },
{ /*sentinel*/ }
 };
 
@@ -565,9 +566,11 @@ static __init void at91_dt_ramc(void)
panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), 
idx);
 
ramc = of_id->data;
-   if (!standby)
-   standby = ramc->idle;
-   soc_pm.data.memctrl = ramc->memctrl;
+   if (ramc) {
+   if (!standby)
+   standby = ramc->idle;
+   soc_pm.data.memctrl = ramc->memctrl;
+   }
 
idx++;
}
-- 
2.25.1



[PATCH v3 19/24] ARM: at91: pm: save ddr phy calibration data to securam

2021-04-15 Thread Claudiu Beznea
The resuming from backup mode is done with the help of bootloader.
The bootloader reconfigure the DDR controller and DDR PHY controller.
To speed-up the resuming process save the PHY calibration data into
SECURAM before suspending (securam is powered on backup mode).
This data will be later used by bootloader in DDR PHY reconfiguration
process. Also, in the process or recalibration the first 8 words of
the memory may get corrupted. To solve this, these 8 words are saved
in the securam and restored by bootloader in the process of PHY
configuration.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 60 -
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 4dec7216a80e..91b4014d2e10 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,18 +28,23 @@
 #include "generic.h"
 #include "pm.h"
 
+#define BACKUP_DDR_PHY_CALIBRATION (9)
+
 /**
  * struct at91_pm_bu - AT91 power management backup unit data structure
  * @suspended: true if suspended to backup mode
  * @reserved: reserved
  * @canary: canary data for memory checking after exit from backup mode
  * @resume: resume API
+ * @ddr_phy_calibration: DDR PHY calibration data: ZQ0CR0, first 8 words
+ * of the memory
  */
 struct at91_pm_bu {
int suspended;
unsigned long reserved;
phys_addr_t canary;
phys_addr_t resume;
+   unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
 };
 
 /**
@@ -48,6 +54,7 @@ struct at91_pm_bu {
  * @ws_ids: wakup sources of_device_id array
  * @data: PM data to be used on last phase of suspend
  * @bu: backup unit mapped data (for backup mode)
+ * @memcs: memory chip select
  */
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
@@ -55,6 +62,7 @@ struct at91_soc_pm {
const struct of_device_id *ws_ids;
struct at91_pm_bu *bu;
struct at91_pm_data data;
+   void *memcs;
 };
 
 /**
@@ -316,6 +324,19 @@ extern u32 at91_pm_suspend_in_sram_sz;
 
 static int at91_suspend_finish(unsigned long val)
 {
+   int i;
+
+   if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
+   /*
+* The 1st 8 words of memory might get corrupted in the process
+* of DDR PHY recalibration; it is saved here in securam and it
+* will be restored later, after recalibration, by bootloader
+*/
+   for (i = 1; i < BACKUP_DDR_PHY_CALIBRATION; i++)
+   soc_pm.bu->ddr_phy_calibration[i] =
+   *((unsigned int *)soc_pm.memcs + (i - 1));
+   }
+
flush_cache_all();
outer_disable();
 
@@ -673,12 +694,40 @@ static bool __init at91_is_pm_mode_active(int pm_mode)
soc_pm.data.suspend_mode == pm_mode);
 }
 
+static int __init at91_pm_backup_scan_memcs(unsigned long node,
+   const char *uname, int depth,
+   void *data)
+{
+   const char *type;
+   const __be32 *reg;
+   int *located = data;
+   int size;
+
+   /* Memory node already located. */
+   if (*located)
+   return 0;
+
+   type = of_get_flat_dt_prop(node, "device_type", NULL);
+
+   /* We are scanning "memory" nodes only. */
+   if (!type || strcmp(type, "memory"))
+   return 0;
+
+   reg = of_get_flat_dt_prop(node, "reg", );
+   if (reg) {
+   soc_pm.memcs = __va((phys_addr_t)be32_to_cpu(*reg));
+   *located = 1;
+   }
+
+   return 0;
+}
+
 static int __init at91_pm_backup_init(void)
 {
struct gen_pool *sram_pool;
struct device_node *np;
struct platform_device *pdev;
-   int ret = -ENODEV;
+   int ret = -ENODEV, located = 0;
 
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return -EPERM;
@@ -713,6 +762,15 @@ static int __init at91_pm_backup_init(void)
soc_pm.bu->suspended = 0;
soc_pm.bu->canary = __pa_symbol();
soc_pm.bu->resume = __pa_symbol(cpu_resume);
+   if (soc_pm.data.ramc_phy) {
+   of_scan_flat_dt(at91_pm_backup_scan_memcs, );
+   if (!located)
+   goto securam_fail;
+
+   /* DDR3PHY_ZQ0SR0 */
+   soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
+ 0x188);
+   }
 
return 0;
 
-- 
2.25.1



[PATCH v3 18/24] ARM: at91: pm: add sama7g5 ddr phy controller

2021-04-15 Thread Claudiu Beznea
SAMA7G5 self-refresh procedure accesses also the DDR PHY registers.
Adapt the code so that the at91_dt_ramc() to look also for DDR PHYs,
in case it is mandatory.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 27 +--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5dc942a2012d..4dec7216a80e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -552,7 +552,12 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ /*sentinel*/ }
 };
 
-static __init void at91_dt_ramc(void)
+static const struct of_device_id ramc_phy_ids[] __initconst = {
+   { .compatible = "microchip,sama7g5-ddr3phy", },
+   { /* Sentinel. */ },
+};
+
+static __init void at91_dt_ramc(bool phy_mandatory)
 {
struct device_node *np;
const struct of_device_id *of_id;
@@ -578,6 +583,16 @@ static __init void at91_dt_ramc(void)
if (!idx)
panic(pr_fmt("unable to find compatible ram controller node in 
dtb\n"));
 
+   /* Lookup for DDR PHY node, if any. */
+   for_each_matching_node_and_match(np, ramc_phy_ids, _id) {
+   soc_pm.data.ramc_phy = of_iomap(np, 0);
+   if (!soc_pm.data.ramc_phy)
+   panic(pr_fmt("unable to map ramc phy cpu registers\n"));
+   }
+
+   if (phy_mandatory && !soc_pm.data.ramc_phy)
+   panic(pr_fmt("DDR PHY is mandatory!\n"));
+
if (!standby) {
pr_warn("ramc no standby function available\n");
return;
@@ -936,7 +951,7 @@ void __init at91rm9200_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
 
-   at91_dt_ramc();
+   at91_dt_ramc(false);
 
/*
 * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
@@ -960,7 +975,7 @@ void __init sam9x60_pm_init(void)
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 
soc_pm.ws_ids = sam9x60_ws_ids;
@@ -980,7 +995,7 @@ void __init at91sam9_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
 
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(at91sam9_idle);
 }
 
@@ -994,7 +1009,7 @@ void __init sama5_pm_init(void)
return;
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 }
 
@@ -1015,7 +1030,7 @@ void __init sama5d2_pm_init(void)
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 
soc_pm.ws_ids = sama5d2_ws_ids;
-- 
2.25.1



[PATCH v3 21/24] ARM: at91: pm: add sama7g5's pmc

2021-04-15 Thread Claudiu Beznea
Add SAMA7G5's PMC to compatible list.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index fcb20272d65d..f4e66a7c7d18 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -897,6 +897,11 @@ static const struct pmc_info pmc_infos[] __initconst = {
.mckr = 0x28,
.version = AT91_PMC_V2,
},
+   {
+   .mckr = 0x28,
+   .version = AT91_PMC_V2,
+   },
+
 };
 
 static const struct of_device_id atmel_pmc_ids[] __initconst = {
@@ -912,6 +917,7 @@ static const struct of_device_id atmel_pmc_ids[] 
__initconst = {
{ .compatible = "atmel,sama5d4-pmc", .data = _infos[1] },
{ .compatible = "atmel,sama5d2-pmc", .data = _infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = _infos[4] },
+   { .compatible = "microchip,sama7g5-pmc", .data = _infos[5] },
{ /* sentinel */ },
 };
 
-- 
2.25.1



[PATCH v3 16/24] dt-bindings: atmel-sysreg: add bindings for sama7g5

2021-04-15 Thread Claudiu Beznea
Add RAM controller and RAM PHY controller DT bindings.

Signed-off-by: Claudiu Beznea 
---
 .../devicetree/bindings/arm/atmel-sysregs.txt  | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt 
b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
index 807264a78edc..16eef600d599 100644
--- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
@@ -45,7 +45,8 @@ RAMC SDRAM/DDR Controller required properties:
"atmel,at91sam9260-sdramc",
"atmel,at91sam9g45-ddramc",
"atmel,sama5d3-ddramc",
-   "microchip,sam9x60-ddramc"
+   "microchip,sam9x60-ddramc",
+   "microchip,sama7g5-uddrc"
 - reg: Should contain registers location and length
 
 Examples:
@@ -55,6 +56,17 @@ Examples:
reg = <0xe800 0x200>;
};
 
+RAMC PHY Controller required properties:
+- compatible: Should be "microchip,sama7g5-ddr3phy", "syscon"
+- reg: Should contain registers location and length
+
+Example:
+
+   ddr3phy: ddr3phy@e3804000 {
+   compatible = "microchip,sama7g5-ddr3phy", "syscon";
+   reg = <0xe3804000 0x1000>;
+};
+
 SHDWC Shutdown Controller
 
 required properties:
-- 
2.25.1



[PATCH v3 15/24] ARM: at91: pm: wait for ddr power mode off

2021-04-15 Thread Claudiu Beznea
Wait for DDR power mode off before shutting down the core.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 9c9e08fd8300..7396e18dd7e5 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -980,6 +980,11 @@ ulp_exit:
mov tmp1, #0x1
str tmp1, [r0, #0x10]
 
+   /* Wait for it. */
+1: ldr tmp1, [r0, #0x10]
+   tst tmp1, #0x1
+   beq 1b
+
/* Shutdown */
ldr r0, .shdwc
mov tmp1, #0xA500
-- 
2.25.1



[PATCH v3 14/24] ARM: at91: pm: add support for 2.5V LDO regulator control

2021-04-15 Thread Claudiu Beznea
Add support to disable/enable 2.5V LDO regulator when entering/exiting
any ULP mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.h |  1 +
 arch/arm/mach-at91/pm_suspend.S | 29 +
 2 files changed, 30 insertions(+)

diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 666474088d55..53bdc9000e44 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AT91_MEMCTRL_MC0
 #define AT91_MEMCTRL_SDRAMC1
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 8b0b8619ee8a..9c9e08fd8300 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -83,6 +83,29 @@ tmp3 .reqr6
 
.endm
 
+/**
+ * Set state for 2.5V low power regulator
+ * @ena: 0 - disable regulator
+ *  1 - enable regulator
+ *
+ * Side effects: overwrites r7, r8, r9, r10
+ */
+   .macro at91_2_5V_reg_set_low_power ena
+#ifdef CONFIG_SOC_SAMA7
+   ldr r7, .sfrbu
+   mov r8, #\ena
+   ldr r9, [r7, #AT91_SFRBU_25LDOCR]
+   orr r9, r9, #AT91_SFRBU_25LDOCR_LP
+   cmp r8, #1
+   beq lp_done_\ena
+   bic r9, r9, #AT91_SFRBU_25LDOCR_LP
+lp_done_\ena:
+   ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY
+   orr r9, r9, r10
+   str r9, [r7, #AT91_SFRBU_25LDOCR]
+#endif
+   .endm
+
.text
 
.arm
@@ -906,6 +929,9 @@ save_mck:
 
at91_plla_disable
 
+   /* Enable low power mode for 2.5V regulator. */
+   at91_2_5V_reg_set_low_power 1
+
ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
@@ -918,6 +944,9 @@ ulp1_mode:
b   ulp_exit
 
 ulp_exit:
+   /* Disable low power mode for 2.5V regulator. */
+   at91_2_5V_reg_set_low_power 0
+
ldr pmc, .pmc_base
 
at91_plla_enable
-- 
2.25.1



[PATCH v3 12/24] ARM: at91: pm: add self-refresh support for sama7g5

2021-04-15 Thread Claudiu Beznea
Add self-refresh support for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.h  |   2 +
 arch/arm/mach-at91/pm_data-offsets.c |   2 +
 arch/arm/mach-at91/pm_suspend.S  | 199 +++
 3 files changed, 203 insertions(+)

diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index bfb260be371e..666474088d55 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AT91_MEMCTRL_MC0
 #define AT91_MEMCTRL_SDRAMC1
@@ -27,6 +28,7 @@
 struct at91_pm_data {
void __iomem *pmc;
void __iomem *ramc[2];
+   void __iomem *ramc_phy;
unsigned long uhp_udp_mask;
unsigned int memctrl;
unsigned int mode;
diff --git a/arch/arm/mach-at91/pm_data-offsets.c 
b/arch/arm/mach-at91/pm_data-offsets.c
index 82089ff258c0..40bd4e8fe40a 100644
--- a/arch/arm/mach-at91/pm_data-offsets.c
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -8,6 +8,8 @@ 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_RAMC_PHY,offsetof(struct at91_pm_data,
+ramc_phy));
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
DEFINE(PM_DATA_MODE,offsetof(struct at91_pm_data, mode));
DEFINE(PM_DATA_SHDWC,   offsetof(struct at91_pm_data, shdwc));
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 7669b32d5257..84418120ba67 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -87,6 +87,200 @@ tmp3.reqr6
 
.arm
 
+#ifdef CONFIG_SOC_SAMA7
+/**
+ * Enable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
+ */
+.macro at91_sramc_self_refresh_ena
+   ldr r2, .sramc_base
+   ldr r3, .sramc_phy_base
+   ldr r7, .pm_mode
+
+   dsb
+
+   /* Disable all AXI ports. */
+   ldr tmp1, [r2, #UDDRC_PCTRL_0]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_0]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_1]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_1]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_2]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_2]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_3]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_3]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_4]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_4]
+
+sr_ena_1:
+   /* Wait for all ports to disable. */
+   ldr tmp1, [r2, #UDDRC_PSTAT]
+   ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
+   tst tmp1, tmp2
+   bne sr_ena_1
+
+   /* Switch to self-refresh. */
+   ldr tmp1, [r2, #UDDRC_PWRCTL]
+   orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
+   str tmp1, [r2, #UDDRC_PWRCTL]
+
+sr_ena_2:
+   /* Wait for self-refresh enter. */
+   ldr tmp1, [r2, #UDDRC_STAT]
+   bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
+   cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
+   bne sr_ena_2
+
+   /* Put DDR PHY's DLL in bypass mode for non-backup modes. */
+   cmp r7, #AT91_PM_BACKUP
+   beq sr_ena_3
+   ldr tmp1, [r3, #DDR3PHY_PIR]
+   orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
+   str tmp1, [r3, #DDR3PHY_PIR]
+
+sr_ena_3:
+   /* Power down DDR PHY data receivers. */
+   ldr tmp1, [r3, #DDR3PHY_DXCCR]
+   orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+   str tmp1, [r3, #DDR3PHY_DXCCR]
+
+   /* Power down ADDR/CMD IO. */
+   ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+   orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+   orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+   orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+   str tmp1, [r3, #DDR3PHY_ACIOCR]
+
+   /* Power down ODT. */
+   ldr tmp1, [r3, #DDR3PHY_DSGCR]
+   orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+   str tmp1, [r3, #DDR3PHY_DSGCR]
+.endm
+
+/**
+ * Disable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
+ */
+.macro at91_sramc_self_refresh_dis
+   ldr r2, .sramc_base
+   ldr r3, .sramc_phy_base
+
+   /* Power up DDR PHY data receivers. */
+   ldr tmp1, [r3, #DDR3PHY_DXCCR]
+   bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+   str tmp1, [r3, #DDR3PHY_DXCCR]
+
+   /* Power up the output of CK and CS pins. */
+   ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+   bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+   bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+   bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+   str

[PATCH v3 11/24] ARM: at91: ddr: add registers definitions for sama7g5's ddr

2021-04-15 Thread Claudiu Beznea
Add registers and bits definitions for SAMA7G5's UDDRC and DDR3PHY.

Signed-off-by: Claudiu Beznea 
---
 include/soc/at91/sama7-ddr.h | 80 
 1 file changed, 80 insertions(+)
 create mode 100644 include/soc/at91/sama7-ddr.h

diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h
new file mode 100644
index ..f6542584ca13
--- /dev/null
+++ b/include/soc/at91/sama7-ddr.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets
+ * and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea 
+ */
+
+#ifndef __SAMA7_DDR_H__
+#define __SAMA7_DDR_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+/* DDR3PHY */
+#define DDR3PHY_PIR(0x04)  /* DDR3PHY PHY 
Initialization Register  */
+#defineDDR3PHY_PIR_DLLBYP  (1 << 17)   /* DLL Bypass */
+#defineDDR3PHY_PIR_ITMSRST (1 << 4)/* 
Interface Timing Module Soft Reset */
+#defineDDR3PHY_PIR_DLLLOCK (1 << 2)/* DLL Lock */
+#defineDDR3PHY_PIR_DLLSRST (1 << 1)/* DLL 
Soft Rest */
+#defineDDR3PHY_PIR_INIT(1 << 0)/* 
Initialization Trigger */
+
+#define DDR3PHY_PGCR   (0x08)  /* DDR3PHY PHY 
General Configuration Register */
+#defineDDR3PHY_PGCR_CKDV1  (1 << 13)   /* CK# 
Disable Value */
+#defineDDR3PHY_PGCR_CKDV0  (1 << 12)   /* CK 
Disable Value */
+
+#defineDDR3PHY_PGSR(0x0C)  /* 
DDR3PHY PHY General Status Register */
+#defineDDR3PHY_PGSR_IDONE  (1 << 0)/* 
Initialization Done */
+
+#define DDR3PHY_ACIOCR (0x24)  /*  DDR3PHY AC 
I/O Configuration Register */
+#defineDDR3PHY_ACIOCR_CSPDD_CS0(1 << 18)   /* 
CS#[0] Power Down Driver */
+#defineDDR3PHY_ACIOCR_CKPDD_CK0(1 << 8)/* 
CK[0] Power Down Driver */
+#defineDDR3PHY_ACIORC_ACPDD(1 << 3)/* AC 
Power Down Driver */
+
+#define DDR3PHY_DXCCR  (0x28)  /* DDR3PHY 
DATX8 Common Configuration Register */
+#defineDDR3PHY_DXCCR_DXPDR (1 << 3)/* Data 
Power Down Receiver */
+
+#define DDR3PHY_DSGCR  (0x2C)  /* DDR3PHY DDR 
System General Configuration Register */
+#defineDDR3PHY_DSGCR_ODTPDD_ODT0   (1 << 20)   /* 
ODT[0] Power Down Driver */
+
+#define DDR3PHY_ZQ0SR0 (0x188) /* ZQ status 
register 0 */
+
+/* UDDRC */
+#define UDDRC_STAT (0x04)  /* UDDRC 
Operating Mode Status Register */
+#defineUDDRC_STAT_SELFREF_TYPE_DIS (0x0 << 4)  /* 
SDRAM is not in Self-refresh */
+#defineUDDRC_STAT_SELFREF_TYPE_PHY (0x1 << 4)  /* 
SDRAM is in Self-refresh, which was caused by PHY Master Request */
+#defineUDDRC_STAT_SELFREF_TYPE_SW  (0x2 << 4)  /* 
SDRAM is in Self-refresh, which was not caused solely under Automatic 
Self-refresh control */
+#defineUDDRC_STAT_SELFREF_TYPE_AUTO(0x3 << 4)  /* 
SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
+#defineUDDRC_STAT_SELFREF_TYPE_MSK (0x3 << 4)  /* 
Self-refresh type mask */
+#defineUDDRC_STAT_OPMODE_INIT  (0x0 << 0)  /* Init 
*/
+#defineUDDRC_STAT_OPMODE_NORMAL(0x1 << 0)  /* 
Normal */
+#defineUDDRC_STAT_OPMODE_PWRDOWN   (0x2 << 0)  /* 
Power-down */
+#defineUDDRC_STAT_OPMODE_SELF_REFRESH  (0x3 << 0)  /* 
Self-refresh */
+#defineUDDRC_STAT_OPMODE_MSK   (0x7 << 0)  /* 
Operating mode mask */
+
+#define UDDRC_PWRCTL   (0x30)  /* UDDRC Low 
Power Control Register */
+#defineUDDRC_PWRCTRL_SELFREF_SW(1 << 5)/* 
Software self-refresh */
+
+#define UDDRC_DFIMISC  (0x1B0) /* UDDRC DFI 
Miscellaneous Control Register */
+#defineUDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY 
initialization complete enable signal */
+
+#define UDDRC_SWCTRL   (0x320) /* UDDRC 
Software Register Programming Control Enable */
+#defineUDDRC_SWCTRL_SW_DONE(1 << 0)/* 
Enable quasi-dynamic register programming outside reset */
+
+#define UDDRC

[PATCH v3 13/24] ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes

2021-04-15 Thread Claudiu Beznea
Add support for MCK1..4 save restore for ULP modes.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 126 
 1 file changed, 126 insertions(+)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 84418120ba67..8b0b8619ee8a 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -765,7 +765,122 @@ sr_dis_exit:
 2:
 .endm
 
+/**
+ * at91_mckx_ps_enable:save MCK1..4 settings and switch it to main 
clock
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_enable
+#ifdef CONFIG_SOC_SAMA7
+   ldr pmc, .pmc_base
+
+   /* There are 4 MCKs we need to handle: MCK1..4 */
+   mov tmp1, #1
+e_loop:cmp tmp1, #5
+   beq e_done
+
+   /* Write MCK ID to retrieve the settings. */
+   str tmp1, [pmc, #AT91_PMC_MCR_V2]
+   ldr tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+e_save_mck1:
+   cmp tmp1, #1
+   bne e_save_mck2
+   str tmp2, .saved_mck1
+   b   e_ps
+
+e_save_mck2:
+   cmp tmp1, #2
+   bne e_save_mck3
+   str tmp2, .saved_mck2
+   b   e_ps
+
+e_save_mck3:
+   cmp tmp1, #3
+   bne e_save_mck4
+   str tmp2, .saved_mck3
+   b   e_ps
+
+e_save_mck4:
+   str tmp2, .saved_mck4
+
+e_ps:
+   /* Use CSS=MAINCK and DIV=1. */
+   bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS
+   bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV
+   orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK
+   orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1
+   str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+   wait_mckrdy tmp1
+
+   add tmp1, tmp1, #1
+   b   e_loop
+
+e_done:
+#endif
+.endm
+
+/**
+ * at91_mckx_ps_restore: restore MCK1..4 settings
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_restore
+#ifdef CONFIG_SOC_SAMA7
+   ldr pmc, .pmc_base
+
+   /* There are 4 MCKs we need to handle: MCK1..4 */
+   mov tmp1, #1
+r_loop:cmp tmp1, #5
+   beq r_done
+
+r_save_mck1:
+   cmp tmp1, #1
+   bne r_save_mck2
+   ldr tmp2, .saved_mck1
+   b   r_ps
+
+r_save_mck2:
+   cmp tmp1, #2
+   bne r_save_mck3
+   ldr tmp2, .saved_mck2
+   b   r_ps
+
+r_save_mck3:
+   cmp tmp1, #3
+   bne r_save_mck4
+   ldr tmp2, .saved_mck3
+   b   r_ps
+
+r_save_mck4:
+   ldr tmp2, .saved_mck4
+
+r_ps:
+   /* Write MCK ID to retrieve the settings. */
+   str tmp1, [pmc, #AT91_PMC_MCR_V2]
+   ldr tmp3, [pmc, #AT91_PMC_MCR_V2]
+
+   /* We need to restore CSS and DIV. */
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV
+   orr tmp3, tmp3, tmp2
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK
+   orr tmp3, tmp3, tmp1
+   orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
+   str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+   wait_mckrdy tmp1
+
+   add tmp1, tmp1, #1
+   b   r_loop
+r_done:
+#endif
+.endm
+
 .macro at91_ulp_mode
+   at91_mckx_ps_enable
+
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode
@@ -817,6 +932,7 @@ ulp_exit:
mov tmp3, #0
wait_mckrdy tmp3
 
+   at91_mckx_ps_restore
 .endm
 
 .macro at91_backup_mode
@@ -946,6 +1062,16 @@ ENDPROC(at91_pm_suspend_in_sram)
.word 0
 .saved_osc_status:
.word 0
+#ifdef CONFIG_SOC_SAMA7
+.saved_mck1:
+   .word 0
+.saved_mck2:
+   .word 0
+.saved_mck3:
+   .word 0
+.saved_mck4:
+   .word 0
+#endif
 
 ENTRY(at91_pm_suspend_in_sram_sz)
.word .-at91_pm_suspend_in_sram
-- 
2.25.1



[PATCH v3 10/24] ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5

2021-04-15 Thread Claudiu Beznea
Add SFRBU registers definitions for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 include/soc/at91/sama7-sfrbu.h | 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 include/soc/at91/sama7-sfrbu.h

diff --git a/include/soc/at91/sama7-sfrbu.h b/include/soc/at91/sama7-sfrbu.h
new file mode 100644
index ..76b740810d34
--- /dev/null
+++ b/include/soc/at91/sama7-sfrbu.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 SFRBU registers offsets and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea 
+ */
+
+#ifndef __SAMA7_SFRBU_H__
+#define __SAMA7_SFRBU_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+#define AT91_SFRBU_PSWBU   (0x00)  /* SFRBU Power 
Switch BU Control Register */
+#defineAT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* 
Specific value mandatory to allow writing of other register bits */
+#defineAT91_SFRBU_PSWBU_STATE  (1 << 2)/* 
Power switch BU state */
+#defineAT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1)/* 
Power switch BU source selection */
+#defineAT91_SFRBU_PSWBU_CTRL   (1 << 0)/* 
Power switch BU control */
+
+#define AT91_SFRBU_25LDOCR (0x0C)  /* SFRBU 2.5V 
LDO Control Register */
+#defineAT91_SFRBU_25LDOCR_LDOANAKEY(0x3B6E18 << 8) /* 
Specific value mandatory to allow writing of other register bits. */
+#defineAT91_SFRBU_25LDOCR_STATE(1 << 3)/* 
LDOANA Switch On/Off Control */
+#defineAT91_SFRBU_25LDOCR_LP   (1 << 2)/* 
LDOANA Low-Power Mode Control */
+#defineAT91_SFRBU_PD_VALUE_MSK (0x3)
+#defineAT91_SFRBU_25LDOCR_PD_VALUE(v)  ((v) & 
AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */
+
+#define AT91_FRBU_DDRPWR   (0x10)  /* SFRBU DDR 
Power Control Register */
+#defineAT91_FRBU_DDRPWR_STATE  (1 << 0)/* DDR 
Power Mode State */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_SFRBU_H__ */
+
-- 
2.25.1



[PATCH v3 09/24] ARM: at91: pm: add support for waiting MCK1..4

2021-04-15 Thread Claudiu Beznea
SAMA7G5 has 5 master clocks 0..4. MCK0 is controlled differently than
MCK 1..4. MCK 1..4 should also be saved/restored in the last phase of
suspend/resume. Thus, adapt wait_mckrdy to support also MCK1..4.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 48 -
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 1f63bbfad728..7669b32d5257 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -22,11 +22,23 @@ tmp3.reqr6
 
 /*
  * Wait until master clock is ready (after switching master clock source)
+ *
+ * @r_mckid:   register holding master clock identifier
+ *
+ * Side effects: overwrites r7, r8
  */
-   .macro wait_mckrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MCKRDY
-   beq 1b
+   .macro wait_mckrdy r_mckid
+#ifdef CONFIG_SOC_SAMA7
+   cmp \r_mckid, #0
+   beq 1f
+   mov r7, #AT91_PMC_MCKXRDY
+   b   2f
+#endif
+1: mov r7, #AT91_PMC_MCKRDY
+2: ldr r8, [pmc, #AT91_PMC_SR]
+   and r8, r7
+   cmp r8, r7
+   bne 2b
.endm
 
 /*
@@ -231,7 +243,9 @@ sr_dis_exit:
bic tmp1, tmp1, #AT91_PMC_PRES
orr tmp1, tmp1, #AT91_PMC_PRES_64
str tmp1, [pmc, tmp3]
-   wait_mckrdy
+
+   mov tmp3, #0
+   wait_mckrdy tmp3
b   1f
 
 0:
@@ -267,10 +281,13 @@ sr_dis_exit:
bne 5f
 
/* Set lowest prescaler for fast resume. */
+   ldr tmp3, .mckr_offset
ldr tmp1, [pmc, tmp3]
bic tmp1, tmp1, #AT91_PMC_PRES
str tmp1, [pmc, tmp3]
-   wait_mckrdy
+
+   mov tmp3, #0
+   wait_mckrdy tmp3
b   6f
 
 5: /* Restore RC oscillator state */
@@ -307,6 +324,7 @@ sr_dis_exit:
 .macro at91_pm_ulp1_mode
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
+   mov tmp3, #0
 
/* Save RC oscillator state and check if it is enabled. */
ldr tmp1, [pmc, #AT91_PMC_SR]
@@ -348,7 +366,7 @@ sr_dis_exit:
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -361,7 +379,7 @@ sr_dis_exit:
nop
nop
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Enable the crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -377,7 +395,7 @@ sr_dis_exit:
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Switch main clock source to crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -394,7 +412,7 @@ sr_dis_exit:
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Restore RC oscillator state */
ldr tmp1, .saved_osc_status
@@ -573,10 +591,12 @@ sr_dis_exit:
 save_mck:
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
at91_plla_disable
 
+   ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
 
@@ -599,7 +619,8 @@ ulp_exit:
ldr tmp2, .saved_mckr
str tmp2, [pmc, tmp1]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
 .endm
 
@@ -611,7 +632,8 @@ ulp_exit:
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
/*BUMEN*/
ldr r0, .sfrbu
-- 
2.25.1



[PATCH v3 08/24] ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g

2021-04-15 Thread Claudiu Beznea
Replace CONFIG_SOC_SAM9X60 with CONFIG_HAVE_AT91_SAM9X60_PLL as the
SAM9X60's PLL is also present on SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 960ad29cce51..1f63bbfad728 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -422,7 +422,7 @@ sr_dis_exit:
cmp tmp1, #AT91_PMC_V1
beq 1f
 
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* Save PLLA settings. */
ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
@@ -489,7 +489,7 @@ sr_dis_exit:
cmp tmp3, #AT91_PMC_V1
beq 4f
 
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* step 1. */
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
-- 
2.25.1



[PATCH v3 07/24] ARM: at91: pm: avoid push and pop on stack while memory is in self-refersh

2021-04-15 Thread Claudiu Beznea
For the previous AT91 RAM controller and self-refresh procedure this
had no side effects. However, for SAMA7G5 the self-refresh procedure
doesn't allow this anymore as the RAM controller ports are closed
before switching it to self-refresh. This commits prepares the code
for the following ones adding self-refresh and PM support for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 397 +---
 1 file changed, 205 insertions(+), 192 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 3d20c9880fee..960ad29cce51 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -75,98 +75,147 @@ tmp3   .reqr6
 
.arm
 
-/*
- * void at91_suspend_sram_fn(struct at91_pm_data*)
- * @input param:
- * @r0: base address of struct at91_pm_data
+/**
+ * Enable self-refresh
+ *
+ * register usage:
+ * @r1: memory type
+ * @r2: base address of the sram controller
+ * @r3: temporary
  */
-/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of 
fncpy() */
-   .align 3
-ENTRY(at91_pm_suspend_in_sram)
-   /* Save registers on stack */
-   stmfd   sp!, {r4 - r12, lr}
+.macro at91_sramc_self_refresh_ena
+   ldr r1, .memtype
+   ldr r2, .sramc_base
 
-   /* Drain write buffer */
-   mov tmp1, #0
-   mcr p15, 0, tmp1, c7, c10, 4
+   cmp r1, #AT91_MEMCTRL_MC
+   bne sr_ena_ddrc_sf
 
-   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
-   ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
-   str tmp1, .mckr_offset
-   ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
-   str tmp1, .pmc_version
-   /* Both ldrne below are here to preload their address in the TLB */
-   ldr tmp1, [r0, #PM_DATA_SHDWC]
-   str tmp1, .shdwc
-   cmp tmp1, #0
-   ldrne   tmp2, [tmp1, #0]
-   ldr tmp1, [r0, #PM_DATA_SFRBU]
-   str tmp1, .sfrbu
-   cmp tmp1, #0
-   ldrne   tmp2, [tmp1, #0x10]
+   /* Active SDRAM self-refresh mode */
+   mov r3, #1
+   str r3, [r2, #AT91_MC_SDRAMC_SRR]
+   b   sr_ena_exit
 
-   /* Active the self-refresh mode */
-   mov r0, #SRAMC_SELF_FRESH_ACTIVE
-   bl  at91_sramc_self_refresh
+sr_ena_ddrc_sf:
+   cmp r1, #AT91_MEMCTRL_DDRSDR
+   bne sr_ena_sdramc_sf
 
-   ldr r0, .pm_mode
-   cmp r0, #AT91_PM_STANDBY
-   beq standby
-   cmp r0, #AT91_PM_BACKUP
-   beq backup_mode
+   /*
+* DDR Memory controller
+*/
 
-   bl  at91_ulp_mode
-   b   exit_suspend
+   /* LPDDR1 --> force DDR2 mode during self-refresh */
+   ldr r3, [r2, #AT91_DDRSDRC_MDR]
+   str r3, .saved_sam9_mdr
+   bic r3, r3, #~AT91_DDRSDRC_MD
+   cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+   ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+   biceq   r3, r3, #AT91_DDRSDRC_MD
+   orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+   streq   r3, [r2, #AT91_DDRSDRC_MDR]
 
-standby:
-   /* Wait for interrupt */
-   ldr pmc, .pmc_base
-   at91_cpu_idle
-   b   exit_suspend
+   /* Active DDRC self-refresh mode */
+   ldr r3, [r2, #AT91_DDRSDRC_LPR]
+   str r3, .saved_sam9_lpr
+   bic r3, r3, #AT91_DDRSDRC_LPCB
+   orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+   str r3, [r2, #AT91_DDRSDRC_LPR]
 
-backup_mode:
-   bl  at91_backup_mode
-   b   exit_suspend
+   /* If using the 2nd ddr controller */
+   ldr r2, .sramc1_base
+   cmp r2, #0
+   beq sr_ena_no_2nd_ddrc
 
-exit_suspend:
-   /* Exit the self-refresh mode */
-   mov r0, #SRAMC_SELF_FRESH_EXIT
-   bl  at91_sramc_self_refresh
+   ldr r3, [r2, #AT91_DDRSDRC_MDR]
+   str r3, .saved_sam9_mdr1
+   bic r3, r3, #~AT91_DDRSDRC_MD
+   cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+   ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+   biceq   r3, r3, #AT91_DDRSDRC_MD
+   orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+   streq   r3, [r2, #AT91_DDRSDRC_MDR]
 
-   /* Restore registers, and return */
-   ldmfd   sp!, {r4 - r12, pc}
-ENDPROC(at91_pm_suspend_in_sram)
+   /* Active DDRC self-refresh mode */
+   ldr r3, [r2, #AT91_DDRSDRC_LPR]
+   str r3, .saved_sam9_lpr1
+   bic r3, r3, #AT91_DDRSDRC_LPCB
+   orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+   str r3, [r2, #AT91_DDRSDRC_LPR]
 
-ENTRY(at91_backup_mode)
-   /* Switch the master cl

[PATCH v3 06/24] ARM: at91: pm: use r7 instead of tmp1

2021-04-15 Thread Claudiu Beznea
Use r7 instead of tmp1 in macros. This prepares the filed for
next commits.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index b683c2caa40b..3d20c9880fee 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -31,30 +31,36 @@ tmp3.reqr6
 
 /*
  * Wait until master oscillator has stabilized.
+ *
+ * Side effects: overwrites r7
  */
.macro wait_moscrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MOSCS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+   tst r7, #AT91_PMC_MOSCS
beq 1b
.endm
 
 /*
  * Wait for main oscillator selection is done
+ *
+ * Side effects: overwrites r7
  */
.macro wait_moscsels
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MOSCSELS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+   tst r7, #AT91_PMC_MOSCSELS
beq 1b
.endm
 
 /*
  * Put the processor to enter the idle state
+ *
+ * Side effects: overwrites r7
  */
.macro at91_cpu_idle
 
 #if defined(CONFIG_CPU_V7)
-   mov tmp1, #AT91_PMC_PCK
-   str tmp1, [pmc, #AT91_PMC_SCDR]
+   mov r7, #AT91_PMC_PCK
+   str r7, [pmc, #AT91_PMC_SCDR]
 
dsb
 
-- 
2.25.1



[PATCH v3 02/24] ARM: at91: pm: move the setup of soc_pm.bu->suspended

2021-04-15 Thread Claudiu Beznea
Move the setup of soc_pm.bu->suspended in platform_suspend::begin
function so that the PMC code in charge with clocks suspend/resume
to differentiate b/w standard PM mode and backup mode.

Signed-off-by: Claudiu Beznea 
Reviewed-by: Alexandre Belloni 
---
 arch/arm/mach-at91/pm.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index e13ceef7ac9a..3742a1fb76db 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -214,6 +214,8 @@ static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, 
u32 mode, u32 polarity)
  */
 static int at91_pm_begin(suspend_state_t state)
 {
+   int ret;
+
switch (state) {
case PM_SUSPEND_MEM:
soc_pm.data.mode = soc_pm.data.suspend_mode;
@@ -227,7 +229,16 @@ static int at91_pm_begin(suspend_state_t state)
soc_pm.data.mode = -1;
}
 
-   return at91_pm_config_ws(soc_pm.data.mode, true);
+   ret = at91_pm_config_ws(soc_pm.data.mode, true);
+   if (ret)
+   return ret;
+
+   if (soc_pm.data.mode == AT91_PM_BACKUP)
+   soc_pm.bu->suspended = 1;
+   else if (soc_pm.bu)
+   soc_pm.bu->suspended = 0;
+
+   return 0;
 }
 
 /*
@@ -296,8 +307,6 @@ static int at91_suspend_finish(unsigned long val)
 static void at91_pm_suspend(suspend_state_t state)
 {
if (soc_pm.data.mode == AT91_PM_BACKUP) {
-   soc_pm.bu->suspended = 1;
-
cpu_suspend(0, at91_suspend_finish);
 
/* The SRAM is lost between suspend cycles */
-- 
2.25.1



[PATCH v3 05/24] ARM: at91: pm: do not initialize pdev

2021-04-15 Thread Claudiu Beznea
There is no need to initialize pdev.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5a6ce1d88971..65e13769cf50 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -659,7 +659,7 @@ static int __init at91_pm_backup_init(void)
 {
struct gen_pool *sram_pool;
struct device_node *np;
-   struct platform_device *pdev = NULL;
+   struct platform_device *pdev;
int ret = -ENODEV;
 
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
-- 
2.25.1



[PATCH v3 04/24] ARM: at91: pm: check for different controllers in at91_pm_modes_init()

2021-04-15 Thread Claudiu Beznea
at91_pm_modes_init() checks for proper nodes in device tree and maps
them accordingly. Up to SAMA7G5 all AT91 SoCs had the same mapping
b/w power saving modes and different controllers needed in the
final/first steps of suspend/resume. SAMA7G5 is not aligned with the
old SoCs thus the code is adapted for this. This patch prepares
the field for next commits.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 143 +---
 1 file changed, 91 insertions(+), 52 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3029351ec78e..5a6ce1d88971 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -57,6 +57,18 @@ struct at91_soc_pm {
struct at91_pm_data data;
 };
 
+/**
+ * enum at91_pm_iomaps:IOs that needs to be mapped for different PM 
modes
+ * @AT91_PM_IOMAP_SHDWC:   SHDWC controller
+ * @AT91_PM_IOMAP_SFRBU:   SFRBU controller
+ */
+enum at91_pm_iomaps {
+   AT91_PM_IOMAP_SHDWC,
+   AT91_PM_IOMAP_SFRBU,
+};
+
+#define AT91_PM_IOMAP(name)BIT(AT91_PM_IOMAP_##name)
+
 static struct at91_soc_pm soc_pm = {
.data = {
.standby_mode = AT91_PM_STANDBY,
@@ -656,24 +668,15 @@ static int __init at91_pm_backup_init(void)
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
return 0;
 
-   np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
-   if (!np) {
-   pr_warn("%s: failed to find sfrbu!\n", __func__);
-   return ret;
-   }
-
-   soc_pm.data.sfrbu = of_iomap(np, 0);
-   of_node_put(np);
-
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
-   goto securam_fail_no_ref_dev;
+   return ret;
 
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev) {
pr_warn("%s: failed to find securam device!\n", __func__);
-   goto securam_fail_no_ref_dev;
+   return ret;
}
 
sram_pool = gen_pool_get(>dev, NULL);
@@ -697,64 +700,92 @@ static int __init at91_pm_backup_init(void)
 
 securam_fail:
put_device(>dev);
-securam_fail_no_ref_dev:
-   iounmap(soc_pm.data.sfrbu);
-   soc_pm.data.sfrbu = NULL;
return ret;
 }
 
-static void __init at91_pm_use_default_mode(int pm_mode)
-{
-   if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
-   return;
-
-   if (soc_pm.data.standby_mode == pm_mode)
-   soc_pm.data.standby_mode = AT91_PM_ULP0;
-   if (soc_pm.data.suspend_mode == pm_mode)
-   soc_pm.data.suspend_mode = AT91_PM_ULP0;
-}
-
 static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
{ /* sentinel. */ }
 };
 
-static void __init at91_pm_modes_init(void)
+static void __init at91_pm_modes_init(const u32 *maps, int len)
 {
struct device_node *np;
-   int ret;
+   int ret, mode;
 
-   if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
-   !at91_is_pm_mode_active(AT91_PM_ULP1))
-   return;
+   ret = at91_pm_backup_init();
+   if (ret) {
+   if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
+   soc_pm.data.standby_mode = AT91_PM_ULP0;
+   if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
+   soc_pm.data.suspend_mode = AT91_PM_ULP0;
+   }
 
-   np = of_find_matching_node(NULL, atmel_shdwc_ids);
-   if (!np) {
-   pr_warn("%s: failed to find shdwc!\n", __func__);
-   goto ulp1_default;
+   if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
+   maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
+   np = of_find_matching_node(NULL, atmel_shdwc_ids);
+   if (!np) {
+   pr_warn("%s: failed to find shdwc!\n", __func__);
+
+   /* Use ULP0 if it doesn't needs SHDWC.*/
+   if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
+   mode = AT91_PM_ULP0;
+   else
+   mode = AT91_PM_STANDBY;
+
+   if (maps[soc_pm.data.standby_mode] & 
AT91_PM_IOMAP(SHDWC))
+   soc_pm.data.standby_mode = mode;
+   if (maps[soc_pm.data.suspend_mode] & 
AT91_PM_IOMAP(SHDWC))
+   soc_pm.data.suspend_mode = mode;
+   } else {
+   soc_pm.data.shdwc = of_iomap(np, 0);
+   of_node_put(np);
+   }
}
 
-   soc_pm.data.shdwc = of_iomap(np, 0);
-   of_node_put(np);
+   if (maps[soc_pm.data.standby_mode] & AT91_PM_IOM

[PATCH v3 03/24] ARM: at91: pm: document at91_soc_pm structure

2021-04-15 Thread Claudiu Beznea
Document at91_soc_pm structure.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3742a1fb76db..3029351ec78e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -41,6 +41,14 @@ struct at91_pm_bu {
phys_addr_t resume;
 };
 
+/**
+ * struct at91_soc_pm - AT91 SoC power management data structure
+ * @config_shdwc_ws: wakeup sources configuration function for SHDWC
+ * @config_pmc_ws: wakeup srouces configuration function for PMC
+ * @ws_ids: wakup sources of_device_id array
+ * @data: PM data to be used on last phase of suspend
+ * @bu: backup unit mapped data (for backup mode)
+ */
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
-- 
2.25.1



[PATCH v3 01/24] ARM: at91: pm: move pm_bu to soc_pm data structure

2021-04-15 Thread Claudiu Beznea
Move pm_bu to soc_pm data structure.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 90dcdfe3b3d0..e13ceef7ac9a 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -27,10 +27,25 @@
 #include "generic.h"
 #include "pm.h"
 
+/**
+ * struct at91_pm_bu - AT91 power management backup unit data structure
+ * @suspended: true if suspended to backup mode
+ * @reserved: reserved
+ * @canary: canary data for memory checking after exit from backup mode
+ * @resume: resume API
+ */
+struct at91_pm_bu {
+   int suspended;
+   unsigned long reserved;
+   phys_addr_t canary;
+   phys_addr_t resume;
+};
+
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
const struct of_device_id *ws_ids;
+   struct at91_pm_bu *bu;
struct at91_pm_data data;
 };
 
@@ -71,13 +86,6 @@ static int at91_pm_valid_state(suspend_state_t state)
 
 static int canary = 0xA5A5A5A5;
 
-static struct at91_pm_bu {
-   int suspended;
-   unsigned long reserved;
-   phys_addr_t canary;
-   phys_addr_t resume;
-} *pm_bu;
-
 struct wakeup_source_info {
unsigned int pmc_fsmr_bit;
unsigned int shdwc_mr_bit;
@@ -288,7 +296,7 @@ static int at91_suspend_finish(unsigned long val)
 static void at91_pm_suspend(suspend_state_t state)
 {
if (soc_pm.data.mode == AT91_PM_BACKUP) {
-   pm_bu->suspended = 1;
+   soc_pm.bu->suspended = 1;
 
cpu_suspend(0, at91_suspend_finish);
 
@@ -657,16 +665,16 @@ static int __init at91_pm_backup_init(void)
goto securam_fail;
}
 
-   pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
-   if (!pm_bu) {
+   soc_pm.bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct 
at91_pm_bu));
+   if (!soc_pm.bu) {
pr_warn("%s: unable to alloc securam!\n", __func__);
ret = -ENOMEM;
goto securam_fail;
}
 
-   pm_bu->suspended = 0;
-   pm_bu->canary = __pa_symbol();
-   pm_bu->resume = __pa_symbol(cpu_resume);
+   soc_pm.bu->suspended = 0;
+   soc_pm.bu->canary = __pa_symbol();
+   soc_pm.bu->resume = __pa_symbol(cpu_resume);
 
return 0;
 
-- 
2.25.1



[PATCH v3 00/24] ARM: at91: pm: add support for sama7g5

2021-04-15 Thread Claudiu Beznea
Hi,

This series adds PM support for SAMA7G5. The standby, ulp0, ulp1, and
backup modes are supported.

Thank you,
Claudiu Beznea

Changes in v3:
- drop: status = "okay" in patch 16/24

Changes in v2:
- keep only the generic sama7_dt in patch 22/24 and adapt patch 23/24
- collected tags

Claudiu Beznea (23):
  ARM: at91: pm: move pm_bu to soc_pm data structure
  ARM: at91: pm: move the setup of soc_pm.bu->suspended
  ARM: at91: pm: document at91_soc_pm structure
  ARM: at91: pm: check for different controllers in at91_pm_modes_init()
  ARM: at91: pm: do not initialize pdev
  ARM: at91: pm: use r7 instead of tmp1
  ARM: at91: pm: avoid push and pop on stack while memory is in
self-refersh
  ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g
  ARM: at91: pm: add support for waiting MCK1..4
  ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5
  ARM: at91: ddr: add registers definitions for sama7g5's ddr
  ARM: at91: pm: add self-refresh support for sama7g5
  ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes
  ARM: at91: pm: add support for 2.5V LDO regulator control
  ARM: at91: pm: wait for ddr power mode off
  dt-bindings: atmel-sysreg: add bindings for sama7g5
  ARM: at91: pm: add sama7g5 ddr controller
  ARM: at91: pm: add sama7g5 ddr phy controller
  ARM: at91: pm: save ddr phy calibration data to securam
  ARM: at91: pm: add backup mode support for SAMA7G5
  ARM: at91: pm: add sama7g5's pmc
  ARM: at91: pm: add pm support for SAMA7G5
  ARM: at91: pm: add sama7g5 shdwc

Eugen Hristev (1):
  ARM: at91: sama7: introduce sama7 SoC family

 .../devicetree/bindings/arm/atmel-sysregs.txt |  14 +-
 arch/arm/mach-at91/Makefile   |   1 +
 arch/arm/mach-at91/generic.h  |   2 +
 arch/arm/mach-at91/pm.c   | 343 ++--
 arch/arm/mach-at91/pm.h   |   3 +
 arch/arm/mach-at91/pm_data-offsets.c  |   2 +
 arch/arm/mach-at91/pm_suspend.S   | 827 +-
 arch/arm/mach-at91/sama7.c|  33 +
 include/soc/at91/sama7-ddr.h  |  80 ++
 include/soc/at91/sama7-sfrbu.h|  34 +
 10 files changed, 1049 insertions(+), 290 deletions(-)
 create mode 100644 arch/arm/mach-at91/sama7.c
 create mode 100644 include/soc/at91/sama7-ddr.h
 create mode 100644 include/soc/at91/sama7-sfrbu.h

-- 
2.25.1



[PATCH] net: macb: fix the restore of cmp registers

2021-04-14 Thread Claudiu Beznea
Commit a14d273ba159 ("net: macb: restore cmp registers on resume path")
introduces the restore of CMP registers on resume path. In case the IP
doesn't support type 2 screeners (zero on DCFG8 register) the
struct macb::rx_fs_list::list is not initialized and thus the
list_for_each_entry(item, >rx_fs_list.list, list) loop introduced in
commit a14d273ba159 ("net: macb: restore cmp registers on resume path")
will access an uninitialized list leading to crash. Thus, initialize
the struct macb::rx_fs_list::list without taking into account if the
IP supports type 2 screeners or not.

Fixes: a14d273ba159 ("net: macb: restore cmp registers on resume path")
Signed-off-by: Claudiu Beznea 
---
 drivers/net/ethernet/cadence/macb_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index c36722541bc4..0db538d089b1 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3926,6 +3926,7 @@ static int macb_init(struct platform_device *pdev)
reg = gem_readl(bp, DCFG8);
bp->max_tuples = min((GEM_BFEXT(SCR2CMP, reg) / 3),
GEM_BFEXT(T2SCR, reg));
+   INIT_LIST_HEAD(>rx_fs_list.list);
if (bp->max_tuples > 0) {
/* also needs one ethtype match to check IPv4 */
if (GEM_BFEXT(SCR2ETH, reg) > 0) {
@@ -3938,7 +3939,6 @@ static int macb_init(struct platform_device *pdev)
/* Filtering is supported in hw but don't enable it in 
kernel now */
dev->hw_features |= NETIF_F_NTUPLE;
/* init Rx flow definitions */
-   INIT_LIST_HEAD(>rx_fs_list.list);
bp->rx_fs_list.count = 0;
spin_lock_init(>rx_fs_lock);
} else
-- 
2.25.1



[PATCH v2 24/24] ARM: at91: pm: add sama7g5 shdwc

2021-04-09 Thread Claudiu Beznea
Add SAMA7G5 SHDWC.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 24d5fd06d487..d6cfe7c4bb00 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -794,6 +794,7 @@ static int __init at91_pm_backup_init(void)
 static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
+   { .compatible = "microchip,sama7g5-shdwc" },
{ /* sentinel. */ }
 };
 
-- 
2.25.1



[PATCH v2 22/24] ARM: at91: sama7: introduce sama7 SoC family

2021-04-09 Thread Claudiu Beznea
From: Eugen Hristev 

Introduce new family of SoCs, sama7, and first SoC, sama7g5.

Signed-off-by: Eugen Hristev 
[claudiu.bez...@microchip.com: keep only the sama7_dt]
Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/Makefile |  1 +
 arch/arm/mach-at91/sama7.c  | 32 
 2 files changed, 33 insertions(+)
 create mode 100644 arch/arm/mach-at91/sama7.c

diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index f565490f1b70..522b680b6446 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_AT91RM9200)+= at91rm9200.o
 obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
 obj-$(CONFIG_SOC_SAM9X60)  += sam9x60.o
 obj-$(CONFIG_SOC_SAMA5)+= sama5.o
+obj-$(CONFIG_SOC_SAMA7)+= sama7.o
 obj-$(CONFIG_SOC_SAMV7)+= samv7.o
 
 # Power Management
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
new file mode 100644
index ..19d7bcbc97f1
--- /dev/null
+++ b/arch/arm/mach-at91/sama7.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Setup code for SAMA7
+ *
+ * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "generic.h"
+
+static void __init sama7_dt_device_init(void)
+{
+   of_platform_default_populate(NULL, NULL, NULL);
+}
+
+static const char *const sama7_dt_board_compat[] __initconst = {
+   "microchip,sama7",
+   NULL
+};
+
+DT_MACHINE_START(sama7_dt, "Microchip SAMA7")
+   /* Maintainer: Microchip */
+   .init_machine   = sama7_dt_device_init,
+   .dt_compat  = sama7_dt_board_compat,
+MACHINE_END
+
-- 
2.25.1



[PATCH v2 23/24] ARM: at91: pm: add pm support for SAMA7G5

2021-04-09 Thread Claudiu Beznea
Add support for SAMA7G5 power management modes: standby, ulp0, ulp1, backup.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/generic.h |  2 ++
 arch/arm/mach-at91/pm.c  | 37 
 arch/arm/mach-at91/sama7.c   |  1 +
 3 files changed, 40 insertions(+)

diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 0a4cdcb4985b..0c3960a8b3eb 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -14,12 +14,14 @@ extern void __init at91sam9_pm_init(void);
 extern void __init sam9x60_pm_init(void);
 extern void __init sama5_pm_init(void);
 extern void __init sama5d2_pm_init(void);
+extern void __init sama7_pm_init(void);
 #else
 static inline void __init at91rm9200_pm_init(void) { }
 static inline void __init at91sam9_pm_init(void) { }
 static inline void __init sam9x60_pm_init(void) { }
 static inline void __init sama5_pm_init(void) { }
 static inline void __init sama5d2_pm_init(void) { }
+static inline void __init sama7_pm_init(void) { }
 #endif
 
 #endif /* _AT91_GENERIC_H */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index f4e66a7c7d18..24d5fd06d487 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -152,6 +152,17 @@ static const struct of_device_id sam9x60_ws_ids[] = {
{ /* sentinel */ }
 };
 
+static const struct of_device_id sama7g5_ws_ids[] = {
+   { .compatible = "atmel,at91sam9x5-rtc", .data = _info[1] },
+   { .compatible = "microchip,sama7g5-ohci",   .data = _info[2] },
+   { .compatible = "usb-ohci", .data = _info[2] },
+   { .compatible = "atmel,at91sam9g45-ehci",   .data = _info[2] },
+   { .compatible = "usb-ehci", .data = _info[2] },
+   { .compatible = "microchip,sama7g5-sdhci",  .data = _info[3] },
+   { .compatible = "atmel,at91sam9260-rtt",.data = _info[4] },
+   { /* sentinel */ }
+};
+
 static int at91_pm_config_ws(unsigned int pm_mode, bool set)
 {
const struct wakeup_source_info *wsi;
@@ -1103,6 +1114,32 @@ void __init sama5d2_pm_init(void)
soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
 }
 
+void __init sama7_pm_init(void)
+{
+   static const int modes[] __initconst = {
+   AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP1, AT91_PM_BACKUP,
+   };
+   static const u32 iomaps[] __initconst = {
+   [AT91_PM_ULP0]  = AT91_PM_IOMAP(SFRBU),
+   [AT91_PM_ULP1]  = AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+   [AT91_PM_BACKUP]= AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+   };
+
+   if (!IS_ENABLED(CONFIG_SOC_SAMA7))
+   return;
+
+   at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
+
+   at91_dt_ramc(true);
+   at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
+   at91_pm_init(NULL);
+
+   soc_pm.ws_ids = sama7g5_ws_ids;
+   soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
+}
+
 static int __init at91_pm_modes_select(char *str)
 {
char *s;
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
index 19d7bcbc97f1..bd43733ede18 100644
--- a/arch/arm/mach-at91/sama7.c
+++ b/arch/arm/mach-at91/sama7.c
@@ -17,6 +17,7 @@
 static void __init sama7_dt_device_init(void)
 {
of_platform_default_populate(NULL, NULL, NULL);
+   sama7_pm_init();
 }
 
 static const char *const sama7_dt_board_compat[] __initconst = {
-- 
2.25.1



[PATCH v2 21/24] ARM: at91: pm: add sama7g5's pmc

2021-04-09 Thread Claudiu Beznea
Add SAMA7G5's PMC to compatible list.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index fcb20272d65d..f4e66a7c7d18 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -897,6 +897,11 @@ static const struct pmc_info pmc_infos[] __initconst = {
.mckr = 0x28,
.version = AT91_PMC_V2,
},
+   {
+   .mckr = 0x28,
+   .version = AT91_PMC_V2,
+   },
+
 };
 
 static const struct of_device_id atmel_pmc_ids[] __initconst = {
@@ -912,6 +917,7 @@ static const struct of_device_id atmel_pmc_ids[] 
__initconst = {
{ .compatible = "atmel,sama5d4-pmc", .data = _infos[1] },
{ .compatible = "atmel,sama5d2-pmc", .data = _infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = _infos[4] },
+   { .compatible = "microchip,sama7g5-pmc", .data = _infos[5] },
{ /* sentinel */ },
 };
 
-- 
2.25.1



[PATCH v2 20/24] ARM: at91: pm: add backup mode support for SAMA7G5

2021-04-09 Thread Claudiu Beznea
Adapt at91_pm_backup_init() to work for SAMA7G5. Also, set the LPM pin
to shutdown controller. This will signal to PMIC that it needs to switch
to the state corresponding to backup mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 3 ++-
 arch/arm/mach-at91/pm_suspend.S | 7 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 91b4014d2e10..fcb20272d65d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -729,7 +729,8 @@ static int __init at91_pm_backup_init(void)
struct platform_device *pdev;
int ret = -ENODEV, located = 0;
 
-   if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
+   if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
+   !IS_ENABLED(CONFIG_SOC_SAMA7G5))
return -EPERM;
 
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 7396e18dd7e5..cbd61a3bcab1 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -106,6 +106,12 @@ lp_done_\ena:
 #endif
.endm
 
+   .macro at91_backup_set_lpm reg
+#ifdef CONFIG_SOC_SAMA7
+   orr \reg, \reg, #0x20
+#endif
+   .endm
+
.text
 
.arm
@@ -989,6 +995,7 @@ ulp_exit:
ldr r0, .shdwc
mov tmp1, #0xA500
add tmp1, tmp1, #0x1
+   at91_backup_set_lpm tmp1
str tmp1, [r0, #0]
 .endm
 
-- 
2.25.1



[PATCH v2 19/24] ARM: at91: pm: save ddr phy calibration data to securam

2021-04-09 Thread Claudiu Beznea
The resuming from backup mode is done with the help of bootloader.
The bootloader reconfigure the DDR controller and DDR PHY controller.
To speed-up the resuming process save the PHY calibration data into
SECURAM before suspending (securam is powered on backup mode).
This data will be later used by bootloader in DDR PHY reconfiguration
process. Also, in the process or recalibration the first 8 words of
the memory may get corrupted. To solve this, these 8 words are saved
in the securam and restored by bootloader in the process of PHY
configuration.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 60 -
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 4dec7216a80e..91b4014d2e10 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,18 +28,23 @@
 #include "generic.h"
 #include "pm.h"
 
+#define BACKUP_DDR_PHY_CALIBRATION (9)
+
 /**
  * struct at91_pm_bu - AT91 power management backup unit data structure
  * @suspended: true if suspended to backup mode
  * @reserved: reserved
  * @canary: canary data for memory checking after exit from backup mode
  * @resume: resume API
+ * @ddr_phy_calibration: DDR PHY calibration data: ZQ0CR0, first 8 words
+ * of the memory
  */
 struct at91_pm_bu {
int suspended;
unsigned long reserved;
phys_addr_t canary;
phys_addr_t resume;
+   unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
 };
 
 /**
@@ -48,6 +54,7 @@ struct at91_pm_bu {
  * @ws_ids: wakup sources of_device_id array
  * @data: PM data to be used on last phase of suspend
  * @bu: backup unit mapped data (for backup mode)
+ * @memcs: memory chip select
  */
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
@@ -55,6 +62,7 @@ struct at91_soc_pm {
const struct of_device_id *ws_ids;
struct at91_pm_bu *bu;
struct at91_pm_data data;
+   void *memcs;
 };
 
 /**
@@ -316,6 +324,19 @@ extern u32 at91_pm_suspend_in_sram_sz;
 
 static int at91_suspend_finish(unsigned long val)
 {
+   int i;
+
+   if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
+   /*
+* The 1st 8 words of memory might get corrupted in the process
+* of DDR PHY recalibration; it is saved here in securam and it
+* will be restored later, after recalibration, by bootloader
+*/
+   for (i = 1; i < BACKUP_DDR_PHY_CALIBRATION; i++)
+   soc_pm.bu->ddr_phy_calibration[i] =
+   *((unsigned int *)soc_pm.memcs + (i - 1));
+   }
+
flush_cache_all();
outer_disable();
 
@@ -673,12 +694,40 @@ static bool __init at91_is_pm_mode_active(int pm_mode)
soc_pm.data.suspend_mode == pm_mode);
 }
 
+static int __init at91_pm_backup_scan_memcs(unsigned long node,
+   const char *uname, int depth,
+   void *data)
+{
+   const char *type;
+   const __be32 *reg;
+   int *located = data;
+   int size;
+
+   /* Memory node already located. */
+   if (*located)
+   return 0;
+
+   type = of_get_flat_dt_prop(node, "device_type", NULL);
+
+   /* We are scanning "memory" nodes only. */
+   if (!type || strcmp(type, "memory"))
+   return 0;
+
+   reg = of_get_flat_dt_prop(node, "reg", );
+   if (reg) {
+   soc_pm.memcs = __va((phys_addr_t)be32_to_cpu(*reg));
+   *located = 1;
+   }
+
+   return 0;
+}
+
 static int __init at91_pm_backup_init(void)
 {
struct gen_pool *sram_pool;
struct device_node *np;
struct platform_device *pdev;
-   int ret = -ENODEV;
+   int ret = -ENODEV, located = 0;
 
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return -EPERM;
@@ -713,6 +762,15 @@ static int __init at91_pm_backup_init(void)
soc_pm.bu->suspended = 0;
soc_pm.bu->canary = __pa_symbol();
soc_pm.bu->resume = __pa_symbol(cpu_resume);
+   if (soc_pm.data.ramc_phy) {
+   of_scan_flat_dt(at91_pm_backup_scan_memcs, );
+   if (!located)
+   goto securam_fail;
+
+   /* DDR3PHY_ZQ0SR0 */
+   soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
+ 0x188);
+   }
 
return 0;
 
-- 
2.25.1



[PATCH v2 18/24] ARM: at91: pm: add sama7g5 ddr phy controller

2021-04-09 Thread Claudiu Beznea
SAMA7G5 self-refresh procedure accesses also the DDR PHY registers.
Adapt the code so that the at91_dt_ramc() to look also for DDR PHYs,
in case it is mandatory.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 27 +--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5dc942a2012d..4dec7216a80e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -552,7 +552,12 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ /*sentinel*/ }
 };
 
-static __init void at91_dt_ramc(void)
+static const struct of_device_id ramc_phy_ids[] __initconst = {
+   { .compatible = "microchip,sama7g5-ddr3phy", },
+   { /* Sentinel. */ },
+};
+
+static __init void at91_dt_ramc(bool phy_mandatory)
 {
struct device_node *np;
const struct of_device_id *of_id;
@@ -578,6 +583,16 @@ static __init void at91_dt_ramc(void)
if (!idx)
panic(pr_fmt("unable to find compatible ram controller node in 
dtb\n"));
 
+   /* Lookup for DDR PHY node, if any. */
+   for_each_matching_node_and_match(np, ramc_phy_ids, _id) {
+   soc_pm.data.ramc_phy = of_iomap(np, 0);
+   if (!soc_pm.data.ramc_phy)
+   panic(pr_fmt("unable to map ramc phy cpu registers\n"));
+   }
+
+   if (phy_mandatory && !soc_pm.data.ramc_phy)
+   panic(pr_fmt("DDR PHY is mandatory!\n"));
+
if (!standby) {
pr_warn("ramc no standby function available\n");
return;
@@ -936,7 +951,7 @@ void __init at91rm9200_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
 
-   at91_dt_ramc();
+   at91_dt_ramc(false);
 
/*
 * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
@@ -960,7 +975,7 @@ void __init sam9x60_pm_init(void)
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 
soc_pm.ws_ids = sam9x60_ws_ids;
@@ -980,7 +995,7 @@ void __init at91sam9_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
 
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(at91sam9_idle);
 }
 
@@ -994,7 +1009,7 @@ void __init sama5_pm_init(void)
return;
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 }
 
@@ -1015,7 +1030,7 @@ void __init sama5d2_pm_init(void)
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 
soc_pm.ws_ids = sama5d2_ws_ids;
-- 
2.25.1



[PATCH v2 17/24] ARM: at91: pm: add sama7g5 ddr controller

2021-04-09 Thread Claudiu Beznea
Add SAMA7G5 DDR controller to the list of DDR controller compatibles.
At the moment there is no standby support. Adapt the code for this.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 65e13769cf50..5dc942a2012d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -548,6 +548,7 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ .compatible = "atmel,at91sam9260-sdramc", .data = _infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = _infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = _infos[3] },
+   { .compatible = "microchip,sama7g5-uddrc", },
{ /*sentinel*/ }
 };
 
@@ -565,9 +566,11 @@ static __init void at91_dt_ramc(void)
panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), 
idx);
 
ramc = of_id->data;
-   if (!standby)
-   standby = ramc->idle;
-   soc_pm.data.memctrl = ramc->memctrl;
+   if (ramc) {
+   if (!standby)
+   standby = ramc->idle;
+   soc_pm.data.memctrl = ramc->memctrl;
+   }
 
idx++;
}
-- 
2.25.1



[PATCH v2 16/24] dt-bindings: atmel-sysreg: add bindings for sama7g5

2021-04-09 Thread Claudiu Beznea
Add RAM controller and RAM PHY controller DT bindings.

Signed-off-by: Claudiu Beznea 
---
 .../devicetree/bindings/arm/atmel-sysregs.txt | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt 
b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
index 807264a78edc..7cd55a760d41 100644
--- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
@@ -45,7 +45,8 @@ RAMC SDRAM/DDR Controller required properties:
"atmel,at91sam9260-sdramc",
"atmel,at91sam9g45-ddramc",
"atmel,sama5d3-ddramc",
-   "microchip,sam9x60-ddramc"
+   "microchip,sam9x60-ddramc",
+   "microchip,sama7g5-uddrc"
 - reg: Should contain registers location and length
 
 Examples:
@@ -55,6 +56,18 @@ Examples:
reg = <0xe800 0x200>;
};
 
+RAMC PHY Controller required properties:
+- compatible: Should be "microchip,sama7g5-ddr3phy", "syscon"
+- reg: Should contain registers location and length
+
+Example:
+
+   ddr3phy: ddr3phy@e3804000 {
+   compatible = "microchip,sama7g5-ddr3phy", "syscon";
+   reg = <0xe3804000 0x1000>;
+   status = "okay";
+};
+
 SHDWC Shutdown Controller
 
 required properties:
-- 
2.25.1



[PATCH v2 15/24] ARM: at91: pm: wait for ddr power mode off

2021-04-09 Thread Claudiu Beznea
Wait for DDR power mode off before shutting down the core.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 9c9e08fd8300..7396e18dd7e5 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -980,6 +980,11 @@ ulp_exit:
mov tmp1, #0x1
str tmp1, [r0, #0x10]
 
+   /* Wait for it. */
+1: ldr tmp1, [r0, #0x10]
+   tst tmp1, #0x1
+   beq 1b
+
/* Shutdown */
ldr r0, .shdwc
mov tmp1, #0xA500
-- 
2.25.1



[PATCH v2 14/24] ARM: at91: pm: add support for 2.5V LDO regulator control

2021-04-09 Thread Claudiu Beznea
Add support to disable/enable 2.5V LDO regulator when entering/exiting
any ULP mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.h |  1 +
 arch/arm/mach-at91/pm_suspend.S | 29 +
 2 files changed, 30 insertions(+)

diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 666474088d55..53bdc9000e44 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AT91_MEMCTRL_MC0
 #define AT91_MEMCTRL_SDRAMC1
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 8b0b8619ee8a..9c9e08fd8300 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -83,6 +83,29 @@ tmp3 .reqr6
 
.endm
 
+/**
+ * Set state for 2.5V low power regulator
+ * @ena: 0 - disable regulator
+ *  1 - enable regulator
+ *
+ * Side effects: overwrites r7, r8, r9, r10
+ */
+   .macro at91_2_5V_reg_set_low_power ena
+#ifdef CONFIG_SOC_SAMA7
+   ldr r7, .sfrbu
+   mov r8, #\ena
+   ldr r9, [r7, #AT91_SFRBU_25LDOCR]
+   orr r9, r9, #AT91_SFRBU_25LDOCR_LP
+   cmp r8, #1
+   beq lp_done_\ena
+   bic r9, r9, #AT91_SFRBU_25LDOCR_LP
+lp_done_\ena:
+   ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY
+   orr r9, r9, r10
+   str r9, [r7, #AT91_SFRBU_25LDOCR]
+#endif
+   .endm
+
.text
 
.arm
@@ -906,6 +929,9 @@ save_mck:
 
at91_plla_disable
 
+   /* Enable low power mode for 2.5V regulator. */
+   at91_2_5V_reg_set_low_power 1
+
ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
@@ -918,6 +944,9 @@ ulp1_mode:
b   ulp_exit
 
 ulp_exit:
+   /* Disable low power mode for 2.5V regulator. */
+   at91_2_5V_reg_set_low_power 0
+
ldr pmc, .pmc_base
 
at91_plla_enable
-- 
2.25.1



[PATCH v2 13/24] ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes

2021-04-09 Thread Claudiu Beznea
Add support for MCK1..4 save restore for ULP modes.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 126 
 1 file changed, 126 insertions(+)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 84418120ba67..8b0b8619ee8a 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -765,7 +765,122 @@ sr_dis_exit:
 2:
 .endm
 
+/**
+ * at91_mckx_ps_enable:save MCK1..4 settings and switch it to main 
clock
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_enable
+#ifdef CONFIG_SOC_SAMA7
+   ldr pmc, .pmc_base
+
+   /* There are 4 MCKs we need to handle: MCK1..4 */
+   mov tmp1, #1
+e_loop:cmp tmp1, #5
+   beq e_done
+
+   /* Write MCK ID to retrieve the settings. */
+   str tmp1, [pmc, #AT91_PMC_MCR_V2]
+   ldr tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+e_save_mck1:
+   cmp tmp1, #1
+   bne e_save_mck2
+   str tmp2, .saved_mck1
+   b   e_ps
+
+e_save_mck2:
+   cmp tmp1, #2
+   bne e_save_mck3
+   str tmp2, .saved_mck2
+   b   e_ps
+
+e_save_mck3:
+   cmp tmp1, #3
+   bne e_save_mck4
+   str tmp2, .saved_mck3
+   b   e_ps
+
+e_save_mck4:
+   str tmp2, .saved_mck4
+
+e_ps:
+   /* Use CSS=MAINCK and DIV=1. */
+   bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS
+   bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV
+   orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK
+   orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1
+   str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+   wait_mckrdy tmp1
+
+   add tmp1, tmp1, #1
+   b   e_loop
+
+e_done:
+#endif
+.endm
+
+/**
+ * at91_mckx_ps_restore: restore MCK1..4 settings
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_restore
+#ifdef CONFIG_SOC_SAMA7
+   ldr pmc, .pmc_base
+
+   /* There are 4 MCKs we need to handle: MCK1..4 */
+   mov tmp1, #1
+r_loop:cmp tmp1, #5
+   beq r_done
+
+r_save_mck1:
+   cmp tmp1, #1
+   bne r_save_mck2
+   ldr tmp2, .saved_mck1
+   b   r_ps
+
+r_save_mck2:
+   cmp tmp1, #2
+   bne r_save_mck3
+   ldr tmp2, .saved_mck2
+   b   r_ps
+
+r_save_mck3:
+   cmp tmp1, #3
+   bne r_save_mck4
+   ldr tmp2, .saved_mck3
+   b   r_ps
+
+r_save_mck4:
+   ldr tmp2, .saved_mck4
+
+r_ps:
+   /* Write MCK ID to retrieve the settings. */
+   str tmp1, [pmc, #AT91_PMC_MCR_V2]
+   ldr tmp3, [pmc, #AT91_PMC_MCR_V2]
+
+   /* We need to restore CSS and DIV. */
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV
+   orr tmp3, tmp3, tmp2
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK
+   orr tmp3, tmp3, tmp1
+   orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
+   str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+   wait_mckrdy tmp1
+
+   add tmp1, tmp1, #1
+   b   r_loop
+r_done:
+#endif
+.endm
+
 .macro at91_ulp_mode
+   at91_mckx_ps_enable
+
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode
@@ -817,6 +932,7 @@ ulp_exit:
mov tmp3, #0
wait_mckrdy tmp3
 
+   at91_mckx_ps_restore
 .endm
 
 .macro at91_backup_mode
@@ -946,6 +1062,16 @@ ENDPROC(at91_pm_suspend_in_sram)
.word 0
 .saved_osc_status:
.word 0
+#ifdef CONFIG_SOC_SAMA7
+.saved_mck1:
+   .word 0
+.saved_mck2:
+   .word 0
+.saved_mck3:
+   .word 0
+.saved_mck4:
+   .word 0
+#endif
 
 ENTRY(at91_pm_suspend_in_sram_sz)
.word .-at91_pm_suspend_in_sram
-- 
2.25.1



[PATCH v2 12/24] ARM: at91: pm: add self-refresh support for sama7g5

2021-04-09 Thread Claudiu Beznea
Add self-refresh support for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.h  |   2 +
 arch/arm/mach-at91/pm_data-offsets.c |   2 +
 arch/arm/mach-at91/pm_suspend.S  | 199 +++
 3 files changed, 203 insertions(+)

diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index bfb260be371e..666474088d55 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AT91_MEMCTRL_MC0
 #define AT91_MEMCTRL_SDRAMC1
@@ -27,6 +28,7 @@
 struct at91_pm_data {
void __iomem *pmc;
void __iomem *ramc[2];
+   void __iomem *ramc_phy;
unsigned long uhp_udp_mask;
unsigned int memctrl;
unsigned int mode;
diff --git a/arch/arm/mach-at91/pm_data-offsets.c 
b/arch/arm/mach-at91/pm_data-offsets.c
index 82089ff258c0..40bd4e8fe40a 100644
--- a/arch/arm/mach-at91/pm_data-offsets.c
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -8,6 +8,8 @@ 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_RAMC_PHY,offsetof(struct at91_pm_data,
+ramc_phy));
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
DEFINE(PM_DATA_MODE,offsetof(struct at91_pm_data, mode));
DEFINE(PM_DATA_SHDWC,   offsetof(struct at91_pm_data, shdwc));
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 7669b32d5257..84418120ba67 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -87,6 +87,200 @@ tmp3.reqr6
 
.arm
 
+#ifdef CONFIG_SOC_SAMA7
+/**
+ * Enable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
+ */
+.macro at91_sramc_self_refresh_ena
+   ldr r2, .sramc_base
+   ldr r3, .sramc_phy_base
+   ldr r7, .pm_mode
+
+   dsb
+
+   /* Disable all AXI ports. */
+   ldr tmp1, [r2, #UDDRC_PCTRL_0]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_0]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_1]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_1]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_2]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_2]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_3]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_3]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_4]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_4]
+
+sr_ena_1:
+   /* Wait for all ports to disable. */
+   ldr tmp1, [r2, #UDDRC_PSTAT]
+   ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
+   tst tmp1, tmp2
+   bne sr_ena_1
+
+   /* Switch to self-refresh. */
+   ldr tmp1, [r2, #UDDRC_PWRCTL]
+   orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
+   str tmp1, [r2, #UDDRC_PWRCTL]
+
+sr_ena_2:
+   /* Wait for self-refresh enter. */
+   ldr tmp1, [r2, #UDDRC_STAT]
+   bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
+   cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
+   bne sr_ena_2
+
+   /* Put DDR PHY's DLL in bypass mode for non-backup modes. */
+   cmp r7, #AT91_PM_BACKUP
+   beq sr_ena_3
+   ldr tmp1, [r3, #DDR3PHY_PIR]
+   orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
+   str tmp1, [r3, #DDR3PHY_PIR]
+
+sr_ena_3:
+   /* Power down DDR PHY data receivers. */
+   ldr tmp1, [r3, #DDR3PHY_DXCCR]
+   orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+   str tmp1, [r3, #DDR3PHY_DXCCR]
+
+   /* Power down ADDR/CMD IO. */
+   ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+   orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+   orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+   orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+   str tmp1, [r3, #DDR3PHY_ACIOCR]
+
+   /* Power down ODT. */
+   ldr tmp1, [r3, #DDR3PHY_DSGCR]
+   orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+   str tmp1, [r3, #DDR3PHY_DSGCR]
+.endm
+
+/**
+ * Disable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
+ */
+.macro at91_sramc_self_refresh_dis
+   ldr r2, .sramc_base
+   ldr r3, .sramc_phy_base
+
+   /* Power up DDR PHY data receivers. */
+   ldr tmp1, [r3, #DDR3PHY_DXCCR]
+   bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+   str tmp1, [r3, #DDR3PHY_DXCCR]
+
+   /* Power up the output of CK and CS pins. */
+   ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+   bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+   bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+   bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+   str

[PATCH v2 11/24] ARM: at91: ddr: add registers definitions for sama7g5's ddr

2021-04-09 Thread Claudiu Beznea
Add registers and bits definitions for SAMA7G5's UDDRC and DDR3PHY.

Signed-off-by: Claudiu Beznea 
---
 include/soc/at91/sama7-ddr.h | 80 
 1 file changed, 80 insertions(+)
 create mode 100644 include/soc/at91/sama7-ddr.h

diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h
new file mode 100644
index ..f6542584ca13
--- /dev/null
+++ b/include/soc/at91/sama7-ddr.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets
+ * and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea 
+ */
+
+#ifndef __SAMA7_DDR_H__
+#define __SAMA7_DDR_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+/* DDR3PHY */
+#define DDR3PHY_PIR(0x04)  /* DDR3PHY PHY 
Initialization Register  */
+#defineDDR3PHY_PIR_DLLBYP  (1 << 17)   /* DLL Bypass */
+#defineDDR3PHY_PIR_ITMSRST (1 << 4)/* 
Interface Timing Module Soft Reset */
+#defineDDR3PHY_PIR_DLLLOCK (1 << 2)/* DLL Lock */
+#defineDDR3PHY_PIR_DLLSRST (1 << 1)/* DLL 
Soft Rest */
+#defineDDR3PHY_PIR_INIT(1 << 0)/* 
Initialization Trigger */
+
+#define DDR3PHY_PGCR   (0x08)  /* DDR3PHY PHY 
General Configuration Register */
+#defineDDR3PHY_PGCR_CKDV1  (1 << 13)   /* CK# 
Disable Value */
+#defineDDR3PHY_PGCR_CKDV0  (1 << 12)   /* CK 
Disable Value */
+
+#defineDDR3PHY_PGSR(0x0C)  /* 
DDR3PHY PHY General Status Register */
+#defineDDR3PHY_PGSR_IDONE  (1 << 0)/* 
Initialization Done */
+
+#define DDR3PHY_ACIOCR (0x24)  /*  DDR3PHY AC 
I/O Configuration Register */
+#defineDDR3PHY_ACIOCR_CSPDD_CS0(1 << 18)   /* 
CS#[0] Power Down Driver */
+#defineDDR3PHY_ACIOCR_CKPDD_CK0(1 << 8)/* 
CK[0] Power Down Driver */
+#defineDDR3PHY_ACIORC_ACPDD(1 << 3)/* AC 
Power Down Driver */
+
+#define DDR3PHY_DXCCR  (0x28)  /* DDR3PHY 
DATX8 Common Configuration Register */
+#defineDDR3PHY_DXCCR_DXPDR (1 << 3)/* Data 
Power Down Receiver */
+
+#define DDR3PHY_DSGCR  (0x2C)  /* DDR3PHY DDR 
System General Configuration Register */
+#defineDDR3PHY_DSGCR_ODTPDD_ODT0   (1 << 20)   /* 
ODT[0] Power Down Driver */
+
+#define DDR3PHY_ZQ0SR0 (0x188) /* ZQ status 
register 0 */
+
+/* UDDRC */
+#define UDDRC_STAT (0x04)  /* UDDRC 
Operating Mode Status Register */
+#defineUDDRC_STAT_SELFREF_TYPE_DIS (0x0 << 4)  /* 
SDRAM is not in Self-refresh */
+#defineUDDRC_STAT_SELFREF_TYPE_PHY (0x1 << 4)  /* 
SDRAM is in Self-refresh, which was caused by PHY Master Request */
+#defineUDDRC_STAT_SELFREF_TYPE_SW  (0x2 << 4)  /* 
SDRAM is in Self-refresh, which was not caused solely under Automatic 
Self-refresh control */
+#defineUDDRC_STAT_SELFREF_TYPE_AUTO(0x3 << 4)  /* 
SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
+#defineUDDRC_STAT_SELFREF_TYPE_MSK (0x3 << 4)  /* 
Self-refresh type mask */
+#defineUDDRC_STAT_OPMODE_INIT  (0x0 << 0)  /* Init 
*/
+#defineUDDRC_STAT_OPMODE_NORMAL(0x1 << 0)  /* 
Normal */
+#defineUDDRC_STAT_OPMODE_PWRDOWN   (0x2 << 0)  /* 
Power-down */
+#defineUDDRC_STAT_OPMODE_SELF_REFRESH  (0x3 << 0)  /* 
Self-refresh */
+#defineUDDRC_STAT_OPMODE_MSK   (0x7 << 0)  /* 
Operating mode mask */
+
+#define UDDRC_PWRCTL   (0x30)  /* UDDRC Low 
Power Control Register */
+#defineUDDRC_PWRCTRL_SELFREF_SW(1 << 5)/* 
Software self-refresh */
+
+#define UDDRC_DFIMISC  (0x1B0) /* UDDRC DFI 
Miscellaneous Control Register */
+#defineUDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY 
initialization complete enable signal */
+
+#define UDDRC_SWCTRL   (0x320) /* UDDRC 
Software Register Programming Control Enable */
+#defineUDDRC_SWCTRL_SW_DONE(1 << 0)/* 
Enable quasi-dynamic register programming outside reset */
+
+#define UDDRC

[PATCH v2 08/24] ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g

2021-04-09 Thread Claudiu Beznea
Replace CONFIG_SOC_SAM9X60 with CONFIG_HAVE_AT91_SAM9X60_PLL as the
SAM9X60's PLL is also present on SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 960ad29cce51..1f63bbfad728 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -422,7 +422,7 @@ sr_dis_exit:
cmp tmp1, #AT91_PMC_V1
beq 1f
 
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* Save PLLA settings. */
ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
@@ -489,7 +489,7 @@ sr_dis_exit:
cmp tmp3, #AT91_PMC_V1
beq 4f
 
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* step 1. */
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
-- 
2.25.1



[PATCH v2 09/24] ARM: at91: pm: add support for waiting MCK1..4

2021-04-09 Thread Claudiu Beznea
SAMA7G5 has 5 master clocks 0..4. MCK0 is controlled differently than
MCK 1..4. MCK 1..4 should also be saved/restored in the last phase of
suspend/resume. Thus, adapt wait_mckrdy to support also MCK1..4.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 48 -
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 1f63bbfad728..7669b32d5257 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -22,11 +22,23 @@ tmp3.reqr6
 
 /*
  * Wait until master clock is ready (after switching master clock source)
+ *
+ * @r_mckid:   register holding master clock identifier
+ *
+ * Side effects: overwrites r7, r8
  */
-   .macro wait_mckrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MCKRDY
-   beq 1b
+   .macro wait_mckrdy r_mckid
+#ifdef CONFIG_SOC_SAMA7
+   cmp \r_mckid, #0
+   beq 1f
+   mov r7, #AT91_PMC_MCKXRDY
+   b   2f
+#endif
+1: mov r7, #AT91_PMC_MCKRDY
+2: ldr r8, [pmc, #AT91_PMC_SR]
+   and r8, r7
+   cmp r8, r7
+   bne 2b
.endm
 
 /*
@@ -231,7 +243,9 @@ sr_dis_exit:
bic tmp1, tmp1, #AT91_PMC_PRES
orr tmp1, tmp1, #AT91_PMC_PRES_64
str tmp1, [pmc, tmp3]
-   wait_mckrdy
+
+   mov tmp3, #0
+   wait_mckrdy tmp3
b   1f
 
 0:
@@ -267,10 +281,13 @@ sr_dis_exit:
bne 5f
 
/* Set lowest prescaler for fast resume. */
+   ldr tmp3, .mckr_offset
ldr tmp1, [pmc, tmp3]
bic tmp1, tmp1, #AT91_PMC_PRES
str tmp1, [pmc, tmp3]
-   wait_mckrdy
+
+   mov tmp3, #0
+   wait_mckrdy tmp3
b   6f
 
 5: /* Restore RC oscillator state */
@@ -307,6 +324,7 @@ sr_dis_exit:
 .macro at91_pm_ulp1_mode
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
+   mov tmp3, #0
 
/* Save RC oscillator state and check if it is enabled. */
ldr tmp1, [pmc, #AT91_PMC_SR]
@@ -348,7 +366,7 @@ sr_dis_exit:
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -361,7 +379,7 @@ sr_dis_exit:
nop
nop
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Enable the crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -377,7 +395,7 @@ sr_dis_exit:
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Switch main clock source to crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -394,7 +412,7 @@ sr_dis_exit:
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Restore RC oscillator state */
ldr tmp1, .saved_osc_status
@@ -573,10 +591,12 @@ sr_dis_exit:
 save_mck:
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
at91_plla_disable
 
+   ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
 
@@ -599,7 +619,8 @@ ulp_exit:
ldr tmp2, .saved_mckr
str tmp2, [pmc, tmp1]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
 .endm
 
@@ -611,7 +632,8 @@ ulp_exit:
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
/*BUMEN*/
ldr r0, .sfrbu
-- 
2.25.1



[PATCH v2 10/24] ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5

2021-04-09 Thread Claudiu Beznea
Add SFRBU registers definitions for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 include/soc/at91/sama7-sfrbu.h | 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 include/soc/at91/sama7-sfrbu.h

diff --git a/include/soc/at91/sama7-sfrbu.h b/include/soc/at91/sama7-sfrbu.h
new file mode 100644
index ..76b740810d34
--- /dev/null
+++ b/include/soc/at91/sama7-sfrbu.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 SFRBU registers offsets and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea 
+ */
+
+#ifndef __SAMA7_SFRBU_H__
+#define __SAMA7_SFRBU_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+#define AT91_SFRBU_PSWBU   (0x00)  /* SFRBU Power 
Switch BU Control Register */
+#defineAT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* 
Specific value mandatory to allow writing of other register bits */
+#defineAT91_SFRBU_PSWBU_STATE  (1 << 2)/* 
Power switch BU state */
+#defineAT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1)/* 
Power switch BU source selection */
+#defineAT91_SFRBU_PSWBU_CTRL   (1 << 0)/* 
Power switch BU control */
+
+#define AT91_SFRBU_25LDOCR (0x0C)  /* SFRBU 2.5V 
LDO Control Register */
+#defineAT91_SFRBU_25LDOCR_LDOANAKEY(0x3B6E18 << 8) /* 
Specific value mandatory to allow writing of other register bits. */
+#defineAT91_SFRBU_25LDOCR_STATE(1 << 3)/* 
LDOANA Switch On/Off Control */
+#defineAT91_SFRBU_25LDOCR_LP   (1 << 2)/* 
LDOANA Low-Power Mode Control */
+#defineAT91_SFRBU_PD_VALUE_MSK (0x3)
+#defineAT91_SFRBU_25LDOCR_PD_VALUE(v)  ((v) & 
AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */
+
+#define AT91_FRBU_DDRPWR   (0x10)  /* SFRBU DDR 
Power Control Register */
+#defineAT91_FRBU_DDRPWR_STATE  (1 << 0)/* DDR 
Power Mode State */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_SFRBU_H__ */
+
-- 
2.25.1



[PATCH v2 07/24] ARM: at91: pm: avoid push and pop on stack while memory is in self-refersh

2021-04-09 Thread Claudiu Beznea
For the previous AT91 RAM controller and self-refresh procedure this
had no side effects. However, for SAMA7G5 the self-refresh procedure
doesn't allow this anymore as the RAM controller ports are closed
before switching it to self-refresh. This commits prepares the code
for the following ones adding self-refresh and PM support for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 397 +---
 1 file changed, 205 insertions(+), 192 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 3d20c9880fee..960ad29cce51 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -75,98 +75,147 @@ tmp3   .reqr6
 
.arm
 
-/*
- * void at91_suspend_sram_fn(struct at91_pm_data*)
- * @input param:
- * @r0: base address of struct at91_pm_data
+/**
+ * Enable self-refresh
+ *
+ * register usage:
+ * @r1: memory type
+ * @r2: base address of the sram controller
+ * @r3: temporary
  */
-/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of 
fncpy() */
-   .align 3
-ENTRY(at91_pm_suspend_in_sram)
-   /* Save registers on stack */
-   stmfd   sp!, {r4 - r12, lr}
+.macro at91_sramc_self_refresh_ena
+   ldr r1, .memtype
+   ldr r2, .sramc_base
 
-   /* Drain write buffer */
-   mov tmp1, #0
-   mcr p15, 0, tmp1, c7, c10, 4
+   cmp r1, #AT91_MEMCTRL_MC
+   bne sr_ena_ddrc_sf
 
-   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
-   ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
-   str tmp1, .mckr_offset
-   ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
-   str tmp1, .pmc_version
-   /* Both ldrne below are here to preload their address in the TLB */
-   ldr tmp1, [r0, #PM_DATA_SHDWC]
-   str tmp1, .shdwc
-   cmp tmp1, #0
-   ldrne   tmp2, [tmp1, #0]
-   ldr tmp1, [r0, #PM_DATA_SFRBU]
-   str tmp1, .sfrbu
-   cmp tmp1, #0
-   ldrne   tmp2, [tmp1, #0x10]
+   /* Active SDRAM self-refresh mode */
+   mov r3, #1
+   str r3, [r2, #AT91_MC_SDRAMC_SRR]
+   b   sr_ena_exit
 
-   /* Active the self-refresh mode */
-   mov r0, #SRAMC_SELF_FRESH_ACTIVE
-   bl  at91_sramc_self_refresh
+sr_ena_ddrc_sf:
+   cmp r1, #AT91_MEMCTRL_DDRSDR
+   bne sr_ena_sdramc_sf
 
-   ldr r0, .pm_mode
-   cmp r0, #AT91_PM_STANDBY
-   beq standby
-   cmp r0, #AT91_PM_BACKUP
-   beq backup_mode
+   /*
+* DDR Memory controller
+*/
 
-   bl  at91_ulp_mode
-   b   exit_suspend
+   /* LPDDR1 --> force DDR2 mode during self-refresh */
+   ldr r3, [r2, #AT91_DDRSDRC_MDR]
+   str r3, .saved_sam9_mdr
+   bic r3, r3, #~AT91_DDRSDRC_MD
+   cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+   ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+   biceq   r3, r3, #AT91_DDRSDRC_MD
+   orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+   streq   r3, [r2, #AT91_DDRSDRC_MDR]
 
-standby:
-   /* Wait for interrupt */
-   ldr pmc, .pmc_base
-   at91_cpu_idle
-   b   exit_suspend
+   /* Active DDRC self-refresh mode */
+   ldr r3, [r2, #AT91_DDRSDRC_LPR]
+   str r3, .saved_sam9_lpr
+   bic r3, r3, #AT91_DDRSDRC_LPCB
+   orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+   str r3, [r2, #AT91_DDRSDRC_LPR]
 
-backup_mode:
-   bl  at91_backup_mode
-   b   exit_suspend
+   /* If using the 2nd ddr controller */
+   ldr r2, .sramc1_base
+   cmp r2, #0
+   beq sr_ena_no_2nd_ddrc
 
-exit_suspend:
-   /* Exit the self-refresh mode */
-   mov r0, #SRAMC_SELF_FRESH_EXIT
-   bl  at91_sramc_self_refresh
+   ldr r3, [r2, #AT91_DDRSDRC_MDR]
+   str r3, .saved_sam9_mdr1
+   bic r3, r3, #~AT91_DDRSDRC_MD
+   cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+   ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+   biceq   r3, r3, #AT91_DDRSDRC_MD
+   orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+   streq   r3, [r2, #AT91_DDRSDRC_MDR]
 
-   /* Restore registers, and return */
-   ldmfd   sp!, {r4 - r12, pc}
-ENDPROC(at91_pm_suspend_in_sram)
+   /* Active DDRC self-refresh mode */
+   ldr r3, [r2, #AT91_DDRSDRC_LPR]
+   str r3, .saved_sam9_lpr1
+   bic r3, r3, #AT91_DDRSDRC_LPCB
+   orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+   str r3, [r2, #AT91_DDRSDRC_LPR]
 
-ENTRY(at91_backup_mode)
-   /* Switch the master cl

[PATCH v2 06/24] ARM: at91: pm: use r7 instead of tmp1

2021-04-09 Thread Claudiu Beznea
Use r7 instead of tmp1 in macros. This prepares the filed for
next commits.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index b683c2caa40b..3d20c9880fee 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -31,30 +31,36 @@ tmp3.reqr6
 
 /*
  * Wait until master oscillator has stabilized.
+ *
+ * Side effects: overwrites r7
  */
.macro wait_moscrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MOSCS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+   tst r7, #AT91_PMC_MOSCS
beq 1b
.endm
 
 /*
  * Wait for main oscillator selection is done
+ *
+ * Side effects: overwrites r7
  */
.macro wait_moscsels
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MOSCSELS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+   tst r7, #AT91_PMC_MOSCSELS
beq 1b
.endm
 
 /*
  * Put the processor to enter the idle state
+ *
+ * Side effects: overwrites r7
  */
.macro at91_cpu_idle
 
 #if defined(CONFIG_CPU_V7)
-   mov tmp1, #AT91_PMC_PCK
-   str tmp1, [pmc, #AT91_PMC_SCDR]
+   mov r7, #AT91_PMC_PCK
+   str r7, [pmc, #AT91_PMC_SCDR]
 
dsb
 
-- 
2.25.1



[PATCH v2 05/24] ARM: at91: pm: do not initialize pdev

2021-04-09 Thread Claudiu Beznea
There is no need to initialize pdev.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5a6ce1d88971..65e13769cf50 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -659,7 +659,7 @@ static int __init at91_pm_backup_init(void)
 {
struct gen_pool *sram_pool;
struct device_node *np;
-   struct platform_device *pdev = NULL;
+   struct platform_device *pdev;
int ret = -ENODEV;
 
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
-- 
2.25.1



[PATCH v2 04/24] ARM: at91: pm: check for different controllers in at91_pm_modes_init()

2021-04-09 Thread Claudiu Beznea
at91_pm_modes_init() checks for proper nodes in device tree and maps
them accordingly. Up to SAMA7G5 all AT91 SoCs had the same mapping
b/w power saving modes and different controllers needed in the
final/first steps of suspend/resume. SAMA7G5 is not aligned with the
old SoCs thus the code is adapted for this. This patch prepares
the field for next commits.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 143 +---
 1 file changed, 91 insertions(+), 52 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3029351ec78e..5a6ce1d88971 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -57,6 +57,18 @@ struct at91_soc_pm {
struct at91_pm_data data;
 };
 
+/**
+ * enum at91_pm_iomaps:IOs that needs to be mapped for different PM 
modes
+ * @AT91_PM_IOMAP_SHDWC:   SHDWC controller
+ * @AT91_PM_IOMAP_SFRBU:   SFRBU controller
+ */
+enum at91_pm_iomaps {
+   AT91_PM_IOMAP_SHDWC,
+   AT91_PM_IOMAP_SFRBU,
+};
+
+#define AT91_PM_IOMAP(name)BIT(AT91_PM_IOMAP_##name)
+
 static struct at91_soc_pm soc_pm = {
.data = {
.standby_mode = AT91_PM_STANDBY,
@@ -656,24 +668,15 @@ static int __init at91_pm_backup_init(void)
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
return 0;
 
-   np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
-   if (!np) {
-   pr_warn("%s: failed to find sfrbu!\n", __func__);
-   return ret;
-   }
-
-   soc_pm.data.sfrbu = of_iomap(np, 0);
-   of_node_put(np);
-
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
-   goto securam_fail_no_ref_dev;
+   return ret;
 
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev) {
pr_warn("%s: failed to find securam device!\n", __func__);
-   goto securam_fail_no_ref_dev;
+   return ret;
}
 
sram_pool = gen_pool_get(>dev, NULL);
@@ -697,64 +700,92 @@ static int __init at91_pm_backup_init(void)
 
 securam_fail:
put_device(>dev);
-securam_fail_no_ref_dev:
-   iounmap(soc_pm.data.sfrbu);
-   soc_pm.data.sfrbu = NULL;
return ret;
 }
 
-static void __init at91_pm_use_default_mode(int pm_mode)
-{
-   if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
-   return;
-
-   if (soc_pm.data.standby_mode == pm_mode)
-   soc_pm.data.standby_mode = AT91_PM_ULP0;
-   if (soc_pm.data.suspend_mode == pm_mode)
-   soc_pm.data.suspend_mode = AT91_PM_ULP0;
-}
-
 static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
{ /* sentinel. */ }
 };
 
-static void __init at91_pm_modes_init(void)
+static void __init at91_pm_modes_init(const u32 *maps, int len)
 {
struct device_node *np;
-   int ret;
+   int ret, mode;
 
-   if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
-   !at91_is_pm_mode_active(AT91_PM_ULP1))
-   return;
+   ret = at91_pm_backup_init();
+   if (ret) {
+   if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
+   soc_pm.data.standby_mode = AT91_PM_ULP0;
+   if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
+   soc_pm.data.suspend_mode = AT91_PM_ULP0;
+   }
 
-   np = of_find_matching_node(NULL, atmel_shdwc_ids);
-   if (!np) {
-   pr_warn("%s: failed to find shdwc!\n", __func__);
-   goto ulp1_default;
+   if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
+   maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
+   np = of_find_matching_node(NULL, atmel_shdwc_ids);
+   if (!np) {
+   pr_warn("%s: failed to find shdwc!\n", __func__);
+
+   /* Use ULP0 if it doesn't needs SHDWC.*/
+   if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
+   mode = AT91_PM_ULP0;
+   else
+   mode = AT91_PM_STANDBY;
+
+   if (maps[soc_pm.data.standby_mode] & 
AT91_PM_IOMAP(SHDWC))
+   soc_pm.data.standby_mode = mode;
+   if (maps[soc_pm.data.suspend_mode] & 
AT91_PM_IOMAP(SHDWC))
+   soc_pm.data.suspend_mode = mode;
+   } else {
+   soc_pm.data.shdwc = of_iomap(np, 0);
+   of_node_put(np);
+   }
}
 
-   soc_pm.data.shdwc = of_iomap(np, 0);
-   of_node_put(np);
+   if (maps[soc_pm.data.standby_mode] & AT91_PM_IOM

[PATCH v2 03/24] ARM: at91: pm: document at91_soc_pm structure

2021-04-09 Thread Claudiu Beznea
Document at91_soc_pm structure.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3742a1fb76db..3029351ec78e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -41,6 +41,14 @@ struct at91_pm_bu {
phys_addr_t resume;
 };
 
+/**
+ * struct at91_soc_pm - AT91 SoC power management data structure
+ * @config_shdwc_ws: wakeup sources configuration function for SHDWC
+ * @config_pmc_ws: wakeup srouces configuration function for PMC
+ * @ws_ids: wakup sources of_device_id array
+ * @data: PM data to be used on last phase of suspend
+ * @bu: backup unit mapped data (for backup mode)
+ */
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
-- 
2.25.1



[PATCH v2 02/24] ARM: at91: pm: move the setup of soc_pm.bu->suspended

2021-04-09 Thread Claudiu Beznea
Move the setup of soc_pm.bu->suspended in platform_suspend::begin
function so that the PMC code in charge with clocks suspend/resume
to differentiate b/w standard PM mode and backup mode.

Signed-off-by: Claudiu Beznea 
Reviewed-by: Alexandre Belloni 
---
 arch/arm/mach-at91/pm.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index e13ceef7ac9a..3742a1fb76db 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -214,6 +214,8 @@ static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, 
u32 mode, u32 polarity)
  */
 static int at91_pm_begin(suspend_state_t state)
 {
+   int ret;
+
switch (state) {
case PM_SUSPEND_MEM:
soc_pm.data.mode = soc_pm.data.suspend_mode;
@@ -227,7 +229,16 @@ static int at91_pm_begin(suspend_state_t state)
soc_pm.data.mode = -1;
}
 
-   return at91_pm_config_ws(soc_pm.data.mode, true);
+   ret = at91_pm_config_ws(soc_pm.data.mode, true);
+   if (ret)
+   return ret;
+
+   if (soc_pm.data.mode == AT91_PM_BACKUP)
+   soc_pm.bu->suspended = 1;
+   else if (soc_pm.bu)
+   soc_pm.bu->suspended = 0;
+
+   return 0;
 }
 
 /*
@@ -296,8 +307,6 @@ static int at91_suspend_finish(unsigned long val)
 static void at91_pm_suspend(suspend_state_t state)
 {
if (soc_pm.data.mode == AT91_PM_BACKUP) {
-   soc_pm.bu->suspended = 1;
-
cpu_suspend(0, at91_suspend_finish);
 
/* The SRAM is lost between suspend cycles */
-- 
2.25.1



[PATCH v2 01/24] ARM: at91: pm: move pm_bu to soc_pm data structure

2021-04-09 Thread Claudiu Beznea
Move pm_bu to soc_pm data structure.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 90dcdfe3b3d0..e13ceef7ac9a 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -27,10 +27,25 @@
 #include "generic.h"
 #include "pm.h"
 
+/**
+ * struct at91_pm_bu - AT91 power management backup unit data structure
+ * @suspended: true if suspended to backup mode
+ * @reserved: reserved
+ * @canary: canary data for memory checking after exit from backup mode
+ * @resume: resume API
+ */
+struct at91_pm_bu {
+   int suspended;
+   unsigned long reserved;
+   phys_addr_t canary;
+   phys_addr_t resume;
+};
+
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
const struct of_device_id *ws_ids;
+   struct at91_pm_bu *bu;
struct at91_pm_data data;
 };
 
@@ -71,13 +86,6 @@ static int at91_pm_valid_state(suspend_state_t state)
 
 static int canary = 0xA5A5A5A5;
 
-static struct at91_pm_bu {
-   int suspended;
-   unsigned long reserved;
-   phys_addr_t canary;
-   phys_addr_t resume;
-} *pm_bu;
-
 struct wakeup_source_info {
unsigned int pmc_fsmr_bit;
unsigned int shdwc_mr_bit;
@@ -288,7 +296,7 @@ static int at91_suspend_finish(unsigned long val)
 static void at91_pm_suspend(suspend_state_t state)
 {
if (soc_pm.data.mode == AT91_PM_BACKUP) {
-   pm_bu->suspended = 1;
+   soc_pm.bu->suspended = 1;
 
cpu_suspend(0, at91_suspend_finish);
 
@@ -657,16 +665,16 @@ static int __init at91_pm_backup_init(void)
goto securam_fail;
}
 
-   pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
-   if (!pm_bu) {
+   soc_pm.bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct 
at91_pm_bu));
+   if (!soc_pm.bu) {
pr_warn("%s: unable to alloc securam!\n", __func__);
ret = -ENOMEM;
goto securam_fail;
}
 
-   pm_bu->suspended = 0;
-   pm_bu->canary = __pa_symbol();
-   pm_bu->resume = __pa_symbol(cpu_resume);
+   soc_pm.bu->suspended = 0;
+   soc_pm.bu->canary = __pa_symbol();
+   soc_pm.bu->resume = __pa_symbol(cpu_resume);
 
return 0;
 
-- 
2.25.1



[PATCH v2 00/24] ARM: at91: pm: add support for sama7g5

2021-04-09 Thread Claudiu Beznea
Hi,

This series adds PM support for SAMA7G5. The standby, ulp0, ulp1, and
backup modes are supported.

Thank you,
Claudiu Beznea

Changes in v2:
- keep only the generic sama7_dt in patch 22/24 and adapt patch 23/24
- collected tags

Claudiu Beznea (23):
  ARM: at91: pm: move pm_bu to soc_pm data structure
  ARM: at91: pm: move the setup of soc_pm.bu->suspended
  ARM: at91: pm: document at91_soc_pm structure
  ARM: at91: pm: check for different controllers in at91_pm_modes_init()
  ARM: at91: pm: do not initialize pdev
  ARM: at91: pm: use r7 instead of tmp1
  ARM: at91: pm: avoid push and pop on stack while memory is in
self-refersh
  ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g
  ARM: at91: pm: add support for waiting MCK1..4
  ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5
  ARM: at91: ddr: add registers definitions for sama7g5's ddr
  ARM: at91: pm: add self-refresh support for sama7g5
  ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes
  ARM: at91: pm: add support for 2.5V LDO regulator control
  ARM: at91: pm: wait for ddr power mode off
  dt-bindings: atmel-sysreg: add bindings for sama7g5
  ARM: at91: pm: add sama7g5 ddr controller
  ARM: at91: pm: add sama7g5 ddr phy controller
  ARM: at91: pm: save ddr phy calibration data to securam
  ARM: at91: pm: add backup mode support for SAMA7G5
  ARM: at91: pm: add sama7g5's pmc
  ARM: at91: pm: add pm support for SAMA7G5
  ARM: at91: pm: add sama7g5 shdwc

Eugen Hristev (1):
  ARM: at91: sama7: introduce sama7 SoC family

 .../devicetree/bindings/arm/atmel-sysregs.txt |  15 +-
 arch/arm/mach-at91/Makefile   |   1 +
 arch/arm/mach-at91/generic.h  |   2 +
 arch/arm/mach-at91/pm.c   | 343 ++--
 arch/arm/mach-at91/pm.h   |   3 +
 arch/arm/mach-at91/pm_data-offsets.c  |   2 +
 arch/arm/mach-at91/pm_suspend.S   | 827 +-
 arch/arm/mach-at91/sama7.c|  33 +
 include/soc/at91/sama7-ddr.h  |  80 ++
 include/soc/at91/sama7-sfrbu.h|  34 +
 10 files changed, 1050 insertions(+), 290 deletions(-)
 create mode 100644 arch/arm/mach-at91/sama7.c
 create mode 100644 include/soc/at91/sama7-ddr.h
 create mode 100644 include/soc/at91/sama7-sfrbu.h

-- 
2.25.1



[PATCH] ARM: configs: at91_dt_defconfig: configs for sam9x60

2021-04-06 Thread Claudiu Beznea
Enable CONFIG_NO_HZ_IDLE and CONFIG_HIGH_RES_TIMERS=y to be used
in conjunction with PIT64B present on SAM9X60.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/configs/at91_dt_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/at91_dt_defconfig 
b/arch/arm/configs/at91_dt_defconfig
index 6403b064e8dc..bd749977b566 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -1,6 +1,8 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-- 
2.25.1



[PATCH] eeprom: at24: avoid adjusting offset for 24AA025E{48, 64}

2021-04-02 Thread Claudiu Beznea
Some EEPROMs could be used only for MAC storage. In this case the
EEPROM areas where MACs resides could be modeled as NVMEM cells
(directly via DT bindings) such that the already available networking
infrastructure to read properly the MAC addresses (via
of_get_mac_address()). Add "atmel,24mac02e4", "atmel,24mac02e4"
compatible for the usage w/ 24AA025E{48, 64} type of EEPROMs and adapt
the driver to not do offset adjustments.

Signed-off-by: Claudiu Beznea 
---

Hi Bartosz,

For the previously available compatibles the offset adjustment is done
(probably for compatibility w/ old DT bindings?). In my scenario 24AA025E48
is used in setup with macb driver which is calling of_get_mac_address()
to get the proper NVMEM cell in EEPROM where the MAC resides and read
directly from there. We modeled the EEPROM and NVMEM cell in DT as
follows:

 {
// ...
eeprom0: eeprom0@52 {
compatible = "atmel,24mac02e4";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x52>;
pagesize = <16>;
size = <256>;
status = "okay";

eeprom0_eui48: eui48@fa {
reg = <0xfa 0x6>;
};
};
};

 {
// ...

nvmem-cells = <_eui48>;
nvmem-cell-names = "mac-address";

// ...
};


Let me know if some other approach needs to be taken into account in
at24 driver for this to work.

Thank you,
Claudiu Beznea

 drivers/misc/eeprom/at24.c | 69 ++
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 926408b41270..ae2fbcb5e83d 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -123,17 +123,19 @@ MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try 
writes (default 25)");
 struct at24_chip_data {
u32 byte_len;
u8 flags;
+   u8 adjoff;
void (*read_post)(unsigned int off, char *buf, size_t count);
 };
 
-#define AT24_CHIP_DATA(_name, _len, _flags)\
+#define AT24_CHIP_DATA(_name, _len, _flags, _adjoff)   \
static const struct at24_chip_data _name = {\
-   .byte_len = _len, .flags = _flags,  \
+   .byte_len = _len, .flags = _flags, .adjoff = _adjoff, \
}
 
-#define AT24_CHIP_DATA_CB(_name, _len, _flags, _read_post) \
+#define AT24_CHIP_DATA_CB(_name, _len, _flags, _adjoff, _read_post)\
static const struct at24_chip_data _name = {\
.byte_len = _len, .flags = _flags,  \
+   .adjoff = _adjoff,  \
.read_post = _read_post,\
}
 
@@ -158,48 +160,52 @@ static void at24_read_post_vaio(unsigned int off, char 
*buf, size_t count)
 }
 
 /* needs 8 addresses as A0-A2 are ignored */
-AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR);
+AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR, 0);
 /* old variants can't be handled with this generic entry! */
-AT24_CHIP_DATA(at24_data_24c01, 1024 / 8, 0);
+AT24_CHIP_DATA(at24_data_24c01, 1024 / 8, 0, 0);
 AT24_CHIP_DATA(at24_data_24cs01, 16,
-   AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
-AT24_CHIP_DATA(at24_data_24c02, 2048 / 8, 0);
+   AT24_FLAG_SERIAL | AT24_FLAG_READONLY, 0);
+AT24_CHIP_DATA(at24_data_24c02, 2048 / 8, 0, 0);
 AT24_CHIP_DATA(at24_data_24cs02, 16,
-   AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+   AT24_FLAG_SERIAL | AT24_FLAG_READONLY, 0);
 AT24_CHIP_DATA(at24_data_24mac402, 48 / 8,
-   AT24_FLAG_MAC | AT24_FLAG_READONLY);
+   AT24_FLAG_MAC | AT24_FLAG_READONLY, 1);
 AT24_CHIP_DATA(at24_data_24mac602, 64 / 8,
-   AT24_FLAG_MAC | AT24_FLAG_READONLY);
+   AT24_FLAG_MAC | AT24_FLAG_READONLY, 1);
+AT24_CHIP_DATA(at24_data_24mac02e4, 48 / 8,
+   AT24_FLAG_MAC | AT24_FLAG_READONLY, 0);
+AT24_CHIP_DATA(at24_data_24mac02e6, 64 / 8,
+   AT24_FLAG_MAC | AT24_FLAG_READONLY, 0);
 /* spd is a 24c02 in memory DIMMs */
 AT24_CHIP_DATA(at24_data_spd, 2048 / 8,
-   AT24_FLAG_READONLY | AT24_FLAG_IRUGO);
+   AT24_FLAG_READONLY | AT24_FLAG_IRUGO, 0);
 /* 24c02_vaio is a 24c02 on some Sony laptops */
 AT24_CHIP_DATA_CB(at24_data_24c02_vaio, 2048 / 8,
-   AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
+   AT24_FLAG_READONLY | AT24_FLAG_IRUGO, 0,
at24_read_post_vaio);
-AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0);
+AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0, 0);
 AT24_CHIP_DATA(at24_data_24cs04, 16,
-   AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+   AT24_FLAG_SERIAL | AT24_FLAG_READONLY, 0);
 /* 24rf08 quirk is handled at i2c-core */
-AT24_CHIP_DATA(at24_data_24c08

[PATCH 1/1] net: macb: restore cmp registers on resume path

2021-04-02 Thread Claudiu Beznea
Restore CMP screener registers on resume path.

Fixes: c1e85c6ce57ef ("net: macb: save/restore the remaining registers and 
features")
Signed-off-by: Claudiu Beznea 
---
 drivers/net/ethernet/cadence/macb_main.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index f56f3dbbc015..ffd56a23f8b0 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3269,6 +3269,9 @@ static void gem_prog_cmp_regs(struct macb *bp, struct 
ethtool_rx_flow_spec *fs)
bool cmp_b = false;
bool cmp_c = false;
 
+   if (!macb_is_gem(bp))
+   return;
+
tp4sp_v = &(fs->h_u.tcp_ip4_spec);
tp4sp_m = &(fs->m_u.tcp_ip4_spec);
 
@@ -3637,6 +3640,7 @@ static void macb_restore_features(struct macb *bp)
 {
struct net_device *netdev = bp->dev;
netdev_features_t features = netdev->features;
+   struct ethtool_rx_fs_item *item;
 
/* TX checksum offload */
macb_set_txcsum_feature(bp, features);
@@ -3645,6 +3649,9 @@ static void macb_restore_features(struct macb *bp)
macb_set_rxcsum_feature(bp, features);
 
/* RX Flow Filters */
+   list_for_each_entry(item, >rx_fs_list.list, list)
+   gem_prog_cmp_regs(bp, >fs);
+
macb_set_rxflow_feature(bp, features);
 }
 
-- 
2.25.1



[PATCH v2 1/1] power: reset: at91-reset: use devm_of_iomap

2021-04-02 Thread Claudiu Beznea
Use devm_of_iomap() to map resources. This will avoid the necessity to
track the mapped resources and free them on failure path or on remove.

Reported-by: kernel test robot 
Reported-by: Dan Carpenter 
Suggested-by: Nicolas Ferre 
Signed-off-by: Claudiu Beznea 
---

Changes in v2:
- use devm_of_iomap()
- change commit description and title to match to the new approach
- add Suggested-by tag

 drivers/power/reset/at91-reset.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
index 3ff9d93a5226..026649409135 100644
--- a/drivers/power/reset/at91-reset.c
+++ b/drivers/power/reset/at91-reset.c
@@ -192,7 +192,7 @@ static int __init at91_reset_probe(struct platform_device 
*pdev)
if (!reset)
return -ENOMEM;
 
-   reset->rstc_base = of_iomap(pdev->dev.of_node, 0);
+   reset->rstc_base = devm_of_iomap(>dev, pdev->dev.of_node, 0, 
NULL);
if (!reset->rstc_base) {
dev_err(>dev, "Could not map reset controller address\n");
return -ENODEV;
@@ -202,7 +202,7 @@ static int __init at91_reset_probe(struct platform_device 
*pdev)
/* we need to shutdown the ddr controller, so get ramc base */
for_each_matching_node_and_match(np, at91_ramc_of_match, 
) {
reset->ramc_lpr = (u32)match->data;
-   reset->ramc_base[idx] = of_iomap(np, 0);
+   reset->ramc_base[idx] = devm_of_iomap(>dev, np, 
0, NULL);
if (!reset->ramc_base[idx]) {
dev_err(>dev, "Could not map ram 
controller address\n");
of_node_put(np);
-- 
2.25.1



[PATCH v2 6/6] clk: at91: clk-master: improve readability by using local variables

2021-04-01 Thread Claudiu Beznea
Improve readability in clk_sama7g5_master_set() by using local
variables.

Suggested-by: Nicolas Ferre 
Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/clk-master.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index 1b2962289629..76b2467b32dc 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -720,6 +720,8 @@ static void clk_sama7g5_master_set(struct clk_master 
*master,
unsigned long flags;
unsigned int val, cparent;
unsigned int enable = status ? AT91_PMC_MCR_V2_EN : 0;
+   unsigned int parent = master->parent << PMC_MCR_CSS_SHIFT;
+   unsigned int div = master->div << MASTER_DIV_SHIFT;
 
spin_lock_irqsave(master->lock, flags);
 
@@ -729,9 +731,7 @@ static void clk_sama7g5_master_set(struct clk_master 
*master,
regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
   enable | AT91_PMC_MCR_V2_CSS | AT91_PMC_MCR_V2_DIV |
   AT91_PMC_MCR_V2_CMD | AT91_PMC_MCR_V2_ID_MSK,
-  enable | (master->parent << PMC_MCR_CSS_SHIFT) |
-  (master->div << MASTER_DIV_SHIFT) |
-  AT91_PMC_MCR_V2_CMD |
+  enable | parent | div | AT91_PMC_MCR_V2_CMD |
   AT91_PMC_MCR_V2_ID(master->id));
 
cparent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
-- 
2.25.1



[PATCH v2 3/6] clk: at91: sama7g5: add securam's peripheral clock

2021-04-01 Thread Claudiu Beznea
Add SECURAM's peripheral clock.

Signed-off-by: Claudiu Beznea 
Acked-by: Nicolas Ferre 
---
 drivers/clk/at91/sama7g5.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
index 9e1ec48c4474..9c87b50abbae 100644
--- a/drivers/clk/at91/sama7g5.c
+++ b/drivers/clk/at91/sama7g5.c
@@ -377,6 +377,7 @@ static const struct {
u8 id;
 } sama7g5_periphck[] = {
{ .n = "pioA_clk",  .p = "mck0", .id = 11, },
+   { .n = "securam_clk",   .p = "mck0", .id = 18, },
{ .n = "sfr_clk",   .p = "mck1", .id = 19, },
{ .n = "hsmc_clk",  .p = "mck1", .id = 21, },
{ .n = "xdmac0_clk",.p = "mck1", .id = 22, },
-- 
2.25.1



[PATCH v2 2/6] clk: at91: pmc: execute suspend/resume only for backup mode

2021-04-01 Thread Claudiu Beznea
Before going to backup mode architecture specific PM code sets the first
word in securam (and it will be cleared in a subsequent commit for the rest
of power saving modes). Thus take this into account when
suspending/resuming clocks. This will avoid executing unnecessary
instructions when suspending to non backup modes. Since the clear of the
1st word in securam will be done in a subsequent commit the current commit
will not broke the current behavior since up to this moment the
suspend/resume were executed for all AT91 PM modes. The difference now
is that the suspend/resume for clocks will be executed for the rest of
AT91 PM modes just after the 1st enter/exit to/from backup mode.
Also this commit changed the postcore_initcall() with subsys_initcall()
to be able to execute of_find_compatible_node() since this was not
available at the moment of postcore_initcall(). This should not alter
the tcb_clksrc since the changes are related to clocks suspend/resume
procedure that will be executed at the user space request, thus long
ago after postcore_initcall().

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/pmc.c | 48 ++
 1 file changed, 39 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 77b57c9f5dcb..c226d33cd899 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -8,6 +8,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -110,13 +112,35 @@ struct pmc_data *pmc_data_allocate(unsigned int ncore, 
unsigned int nsystem,
 }
 
 #ifdef CONFIG_PM
+
+/* Address in SECURAM that say if we suspend to backup mode. */
+static void __iomem *at91_pmc_backup_suspend;
+
 static int at91_pmc_suspend(void)
 {
+   unsigned int backup;
+
+   if (!at91_pmc_backup_suspend)
+   return 0;
+
+   backup = *(unsigned int *)at91_pmc_backup_suspend;
+   if (!backup)
+   return 0;
+
return clk_save_context();
 }
 
 static void at91_pmc_resume(void)
 {
+   unsigned int backup;
+
+   if (!at91_pmc_backup_suspend)
+   return;
+
+   backup = *(unsigned int *)at91_pmc_backup_suspend;
+   if (!backup)
+   return;
+
clk_restore_context();
 }
 
@@ -125,24 +149,30 @@ static struct syscore_ops pmc_syscore_ops = {
.resume = at91_pmc_resume,
 };
 
-static const struct of_device_id sama5d2_pmc_dt_ids[] = {
-   { .compatible = "atmel,sama5d2-pmc" },
-   { /* sentinel */ }
-};
-
 static int __init pmc_register_ops(void)
 {
+   struct platform_device *pdev;
struct device_node *np;
 
-   np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
+   np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
-   return 0;
+   return -ENODEV;
+
+   pdev = of_find_device_by_node(np);
of_node_put(np);
+   if (!pdev)
+   return -ENODEV;
+
+   at91_pmc_backup_suspend = of_iomap(np, 0);
+   if (!at91_pmc_backup_suspend) {
+   pr_warn("%s(): unable to map securam\n", __func__);
+   return -ENOMEM;
+   }
 
register_syscore_ops(_syscore_ops);
 
return 0;
 }
-/* This has to happen before arch_initcall because of the tcb_clksrc driver */
-postcore_initcall(pmc_register_ops);
+
+subsys_initcall(pmc_register_ops);
 #endif
-- 
2.25.1



[PATCH v2 4/6] clk: at91: clk-master: add register definition for sama7g5's master clock

2021-04-01 Thread Claudiu Beznea
Add register definitions for SAMA7G5's master clock. These would be
also used by architecture specific power saving code. With this, update
also clk-master.c.

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/clk-master.c | 50 ---
 include/linux/clk/at91_pmc.h  | 26 ++
 2 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index 21e82111890d..736406528824 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -17,15 +17,7 @@
 #define MASTER_DIV_SHIFT   8
 #define MASTER_DIV_MASK0x7
 
-#define PMC_MCR0x30
-#define PMC_MCR_ID_MSK GENMASK(3, 0)
-#define PMC_MCR_CMDBIT(7)
-#define PMC_MCR_DIVGENMASK(10, 8)
-#define PMC_MCR_CSSGENMASK(20, 16)
 #define PMC_MCR_CSS_SHIFT  (16)
-#define PMC_MCR_EN BIT(28)
-
-#define PMC_MCR_ID(x)  ((x) & PMC_MCR_ID_MSK)
 
 #define MASTER_MAX_ID  4
 
@@ -682,20 +674,22 @@ static void clk_sama7g5_master_set(struct clk_master 
*master,
 {
unsigned long flags;
unsigned int val, cparent;
-   unsigned int enable = status ? PMC_MCR_EN : 0;
+   unsigned int enable = status ? AT91_PMC_MCR_V2_EN : 0;
 
spin_lock_irqsave(master->lock, flags);
 
-   regmap_write(master->regmap, PMC_MCR, PMC_MCR_ID(master->id));
-   regmap_read(master->regmap, PMC_MCR, );
-   regmap_update_bits(master->regmap, PMC_MCR,
-  enable | PMC_MCR_CSS | PMC_MCR_DIV |
-  PMC_MCR_CMD | PMC_MCR_ID_MSK,
+   regmap_write(master->regmap, AT91_PMC_MCR_V2,
+AT91_PMC_MCR_V2_ID(master->id));
+   regmap_read(master->regmap, AT91_PMC_MCR_V2, );
+   regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
+  enable | AT91_PMC_MCR_V2_CSS | AT91_PMC_MCR_V2_DIV |
+  AT91_PMC_MCR_V2_CMD | AT91_PMC_MCR_V2_ID_MSK,
   enable | (master->parent << PMC_MCR_CSS_SHIFT) |
   (master->div << MASTER_DIV_SHIFT) |
-  PMC_MCR_CMD | PMC_MCR_ID(master->id));
+  AT91_PMC_MCR_V2_CMD |
+  AT91_PMC_MCR_V2_ID(master->id));
 
-   cparent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
+   cparent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
 
/* Wait here only if parent is being changed. */
while ((cparent != master->parent) && !clk_master_ready(master))
@@ -720,10 +714,12 @@ static void clk_sama7g5_master_disable(struct clk_hw *hw)
 
spin_lock_irqsave(master->lock, flags);
 
-   regmap_write(master->regmap, PMC_MCR, master->id);
-   regmap_update_bits(master->regmap, PMC_MCR,
-  PMC_MCR_EN | PMC_MCR_CMD | PMC_MCR_ID_MSK,
-  PMC_MCR_CMD | PMC_MCR_ID(master->id));
+   regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+   regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
+  AT91_PMC_MCR_V2_EN | AT91_PMC_MCR_V2_CMD |
+  AT91_PMC_MCR_V2_ID_MSK,
+  AT91_PMC_MCR_V2_CMD |
+  AT91_PMC_MCR_V2_ID(master->id));
 
spin_unlock_irqrestore(master->lock, flags);
 }
@@ -736,12 +732,12 @@ static int clk_sama7g5_master_is_enabled(struct clk_hw 
*hw)
 
spin_lock_irqsave(master->lock, flags);
 
-   regmap_write(master->regmap, PMC_MCR, master->id);
-   regmap_read(master->regmap, PMC_MCR, );
+   regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+   regmap_read(master->regmap, AT91_PMC_MCR_V2, );
 
spin_unlock_irqrestore(master->lock, flags);
 
-   return !!(val & PMC_MCR_EN);
+   return !!(val & AT91_PMC_MCR_V2_EN);
 }
 
 static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -837,10 +833,10 @@ at91_clk_sama7g5_register_master(struct regmap *regmap,
master->mux_table = mux_table;
 
spin_lock_irqsave(master->lock, flags);
-   regmap_write(master->regmap, PMC_MCR, master->id);
-   regmap_read(master->regmap, PMC_MCR, );
-   master->parent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
-   master->div = (val & PMC_MCR_DIV) >> MASTER_DIV_SHIFT;
+   regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+   regmap_read(master->regmap, AT91_PMC_MCR_V2, );
+   master->parent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
+   master->div = (val & AT91_PMC_MCR_V2_DIV) >> MASTER_DIV_SHIFT;
spin_unlock_irqrestore(master->lock, flags);
 
   

[PATCH v2 0/6] clk: at91: updates for power management and dvfs

2021-04-01 Thread Claudiu Beznea
Hi,

This series addresses the power management for SAMA7G5 and also updates
the master clock prescaller and master clock divider drivers to accommodate
the requests at [1].

The power management part is implemented by adding
save_context()/restore_context() on each clock driver (patch 1/6). Since
the PM part is necessary only for backup mode (supported on SAMA5D2 and
SAMA7G5) the pmc.c has been adapted to call the
save_context()/restore_context() only on switches to/from backup mode
(patch 2/6).

Patch 3/6 adds the securam clock on SAMA7G5. This is necessary for
backup mode of SAMA7G5.

Patch 4/6 adds registers definitions for the new master clocks (MCK1..4) of
SAMA7G5 and adapt the clk-master.c. The defines exported in
include/linux/clk/at91_pmc.h will be also used by platform specific PM
code.

Patch 5/6 adpat the master clock divider and master clock prescaller
to address the requests at [1].

Patch 6/6 clean up a bit the code in clk-master as suggested by Nicolas.

Thank you,
Claudiu Beznea

[1] https://lore.kernel.org/lkml/20210105104426.4tmgc2l3vyicwedd@vireshk-i7/

Changes in v2:
- addressed code review comments
- collected tags

Claudiu Beznea (6):
  clk: at91: re-factor clocks suspend/resume
  clk: at91: pmc: execute suspend/resume only for backup mode
  clk: at91: sama7g5: add securam's peripheral clock
  clk: at91: clk-master: add register definition for sama7g5's master
clock
  clk: at91: clk-master: update for dvfs
  clk: at91: clk-master: improve readability by using local variables

 drivers/clk/at91/at91rm9200.c   |   2 +-
 drivers/clk/at91/at91sam9260.c  |   2 +-
 drivers/clk/at91/at91sam9g45.c  |   2 +-
 drivers/clk/at91/at91sam9n12.c  |   2 +-
 drivers/clk/at91/at91sam9rl.c   |   2 +-
 drivers/clk/at91/at91sam9x5.c   |   2 +-
 drivers/clk/at91/clk-generated.c|  46 +++-
 drivers/clk/at91/clk-main.c |  66 +
 drivers/clk/at91/clk-master.c   | 396 +---
 drivers/clk/at91/clk-peripheral.c   |  40 ++-
 drivers/clk/at91/clk-pll.c  |  37 +++
 drivers/clk/at91/clk-programmable.c |  29 +-
 drivers/clk/at91/clk-sam9x60-pll.c  |  68 -
 drivers/clk/at91/clk-system.c   |  20 ++
 drivers/clk/at91/clk-usb.c  |  27 ++
 drivers/clk/at91/clk-utmi.c |  47 +++-
 drivers/clk/at91/dt-compat.c|   2 +-
 drivers/clk/at91/pmc.c  | 175 +++-
 drivers/clk/at91/pmc.h  |  27 +-
 drivers/clk/at91/sam9x60.c  |   2 +-
 drivers/clk/at91/sama5d2.c  |   2 +-
 drivers/clk/at91/sama5d3.c  |   2 +-
 drivers/clk/at91/sama5d4.c  |   2 +-
 drivers/clk/at91/sama7g5.c  |   3 +-
 include/linux/clk/at91_pmc.h|  26 ++
 25 files changed, 752 insertions(+), 277 deletions(-)

-- 
2.25.1



[PATCH v2 5/6] clk: at91: clk-master: update for dvfs

2021-04-01 Thread Claudiu Beznea
SAMA7G5 supports CPU DVFS. The hardware block diagram for the clock
system generating CPU clock is as follows:

   ++
   +-->|divider1|--> CPU clock
   |   ++
++   +--+  |   ++
|CPU PLL |-->|prescaller|--+-->|divider0|--> MCK0 clock
++   +--+  ++

The divider1 is not implemented in software since the supported CPU
frequencies could be directly retrieved from CPU PLL + prescaller.
Every time the CPU clock needs to be changed the MCK0 should also be
changed to avoid its over/under clocking and also to preserve its
initial value (200MHz). MCK0 feeds IPs that are glitch free aware.

The initial approach for implementing DVFS was to implement MCK0 and
CPU clocks as 2 different Linux clocks, to pass these two clocks to CPUFreq
driver and in CPUFreq driver to run clk_set_rate() on CPU and MCK clocks
accordingly. E.g. if 1GHz speed was requested by CPUFreq subsystem the
following were executed in CPUFreq driver:

/* ... */
clk_set_rate(mck0, intermediary_freq_to_avoid_over_under_clocking);
clk_set_rate(cpu, 10);
clk_set_rate(mck0, initial_freq);
/ ... */

However, it has been proposed in [1] to use the generic cpufreq-dt driver
and to overload the necessary clocks operations in the proper clock
driver.

To address this proposal the master clock prescaller registers a clock
notifier that will update properly the master clock divider on
PRE_RATE_CHANGE and POST_RATE_CHANGE events to avoid master clock
divider over/under clocking and also to preserve its initial value
(200MHz).

[1] 
https://lore.kernel.org/lkml/1609842147-8161-1-git-send-email-claudiu.bez...@microchip.com/

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/at91rm9200.c  |   2 +-
 drivers/clk/at91/at91sam9260.c |   2 +-
 drivers/clk/at91/at91sam9g45.c |   2 +-
 drivers/clk/at91/at91sam9n12.c |   2 +-
 drivers/clk/at91/at91sam9rl.c  |   2 +-
 drivers/clk/at91/at91sam9x5.c  |   2 +-
 drivers/clk/at91/clk-master.c  | 187 -
 drivers/clk/at91/dt-compat.c   |   2 +-
 drivers/clk/at91/pmc.h |   3 +-
 drivers/clk/at91/sam9x60.c |   2 +-
 drivers/clk/at91/sama5d2.c |   2 +-
 drivers/clk/at91/sama5d3.c |   2 +-
 drivers/clk/at91/sama5d4.c |   2 +-
 drivers/clk/at91/sama7g5.c |   2 +-
 14 files changed, 130 insertions(+), 84 deletions(-)

diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c
index 428a6f4b9ebc..f8df6064d55d 100644
--- a/drivers/clk/at91/at91rm9200.c
+++ b/drivers/clk/at91/at91rm9200.c
@@ -144,7 +144,7 @@ static void __init at91rm9200_pmc_setup(struct device_node 
*np)
   _master_layout,
   _mck_characteristics,
   _mck_lock, CLK_SET_RATE_GATE,
-  INT_MIN);
+  INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
 
diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c
index b29843bea278..8db7bf141b45 100644
--- a/drivers/clk/at91/at91sam9260.c
+++ b/drivers/clk/at91/at91sam9260.c
@@ -420,7 +420,7 @@ static void __init at91sam926x_pmc_setup(struct device_node 
*np,
   _master_layout,
   data->mck_characteristics,
   _mck_lock,
-  CLK_SET_RATE_GATE, INT_MIN);
+  CLK_SET_RATE_GATE, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
 
diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c
index 15da0dfe3ef2..c139169b2d40 100644
--- a/drivers/clk/at91/at91sam9g45.c
+++ b/drivers/clk/at91/at91sam9g45.c
@@ -155,7 +155,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node 
*np)
   _master_layout,
   _characteristics,
   _mck_lock,
-  CLK_SET_RATE_GATE, INT_MIN);
+  CLK_SET_RATE_GATE, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
 
diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c
index 7fe435f4b46b..a4e46c4026d0 100644
--- a/drivers/clk/at91/at91sam9n12.c
+++ b/drivers/clk/at91/at91sam9n12.c
@@ -182,7 +182,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node 
*np)
   _master_layout,
   _characteristics,
   _mck_lock,
-  CLK_SET_RATE_GATE, INT_MIN);
+  CLK_SET_RAT

[PATCH v2 1/6] clk: at91: re-factor clocks suspend/resume

2021-04-01 Thread Claudiu Beznea
SAMA5D2 and SAMA7G5 have a special power saving mode (backup mode) where
most of the SoC's components are powered off (including PMC). Resuming
from this mode is done with the help of bootloader. Peripherals are not
aware of the power saving mode thus most of them are disabling clocks in
proper suspend API and re-enable them in resume API without taking into
account the previously setup rate. Moreover some of the peripherals are
acting as wakeup sources and are not disabling the clocks in this
scenario, when suspending. Since backup mode cuts the power for
peripherals, in resume part these clocks needs to be re-configured.

The initial PMC suspend/resume code was designed with SAMA5D2's PMC
in mind. SAMA7G's PMC is different (few new functionalities, different
registers offsets, different offsets in registers for each
functionalities). To address both SAMA5D2 and SAMA7G5 PMC add
.save_context()/.resume_context() support to each clocks driver and call
this from PMC driver.

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/clk-generated.c|  46 +--
 drivers/clk/at91/clk-main.c |  66 ++
 drivers/clk/at91/clk-master.c   | 183 ++--
 drivers/clk/at91/clk-peripheral.c   |  40 +-
 drivers/clk/at91/clk-pll.c  |  37 ++
 drivers/clk/at91/clk-programmable.c |  29 -
 drivers/clk/at91/clk-sam9x60-pll.c  |  68 ++-
 drivers/clk/at91/clk-system.c   |  20 +++
 drivers/clk/at91/clk-usb.c  |  27 
 drivers/clk/at91/clk-utmi.c |  47 ++-
 drivers/clk/at91/pmc.c  | 149 ++
 drivers/clk/at91/pmc.h  |  24 ++--
 12 files changed, 556 insertions(+), 180 deletions(-)

diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index b4fc8d71daf2..a3ff46e251c5 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -27,6 +27,7 @@ struct clk_generated {
u32 id;
u32 gckdiv;
const struct clk_pcr_layout *layout;
+   struct at91_clk_pms pms;
u8 parent_id;
int chg_pid;
 };
@@ -34,25 +35,35 @@ struct clk_generated {
 #define to_clk_generated(hw) \
container_of(hw, struct clk_generated, hw)
 
-static int clk_generated_enable(struct clk_hw *hw)
+static int clk_generated_set(struct clk_generated *gck, int status)
 {
-   struct clk_generated *gck = to_clk_generated(hw);
unsigned long flags;
-
-   pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
-__func__, gck->gckdiv, gck->parent_id);
+   unsigned int enable = status ? AT91_PMC_PCR_GCKEN : 0;
 
spin_lock_irqsave(gck->lock, flags);
regmap_write(gck->regmap, gck->layout->offset,
 (gck->id & gck->layout->pid_mask));
regmap_update_bits(gck->regmap, gck->layout->offset,
   AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
-  gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+  gck->layout->cmd | enable,
   field_prep(gck->layout->gckcss_mask, gck->parent_id) 
|
   gck->layout->cmd |
   FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
-  AT91_PMC_PCR_GCKEN);
+  enable);
spin_unlock_irqrestore(gck->lock, flags);
+
+   return 0;
+}
+
+static int clk_generated_enable(struct clk_hw *hw)
+{
+   struct clk_generated *gck = to_clk_generated(hw);
+
+   pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
+__func__, gck->gckdiv, gck->parent_id);
+
+   clk_generated_set(gck, 1);
+
return 0;
 }
 
@@ -239,6 +250,23 @@ static int clk_generated_set_rate(struct clk_hw *hw,
return 0;
 }
 
+static int clk_generated_save_context(struct clk_hw *hw)
+{
+   struct clk_generated *gck = to_clk_generated(hw);
+
+   gck->pms.status = clk_generated_is_enabled(>hw);
+
+   return 0;
+}
+
+static void clk_generated_restore_context(struct clk_hw *hw)
+{
+   struct clk_generated *gck = to_clk_generated(hw);
+
+   if (gck->pms.status)
+   clk_generated_set(gck, gck->pms.status);
+}
+
 static const struct clk_ops generated_ops = {
.enable = clk_generated_enable,
.disable = clk_generated_disable,
@@ -248,6 +276,8 @@ static const struct clk_ops generated_ops = {
.get_parent = clk_generated_get_parent,
.set_parent = clk_generated_set_parent,
.set_rate = clk_generated_set_rate,
+   .save_context = clk_generated_save_context,
+   .restore_context = clk_generated_restore_context,
 };
 
 /**
@@ -314,8 +344,6 @@ at91_clk_register_generated(struct regmap *regmap, 
spinlock_t *lock,
if (ret) {
kfree(gck);
hw = ERR_PTR(ret);
-   } 

[PATCH 21/24] ARM: at91: pm: add sama7g5's pmc

2021-03-31 Thread Claudiu Beznea
Add SAMA7G5's PMC to compatible list.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index fcb20272d65d..f4e66a7c7d18 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -897,6 +897,11 @@ static const struct pmc_info pmc_infos[] __initconst = {
.mckr = 0x28,
.version = AT91_PMC_V2,
},
+   {
+   .mckr = 0x28,
+   .version = AT91_PMC_V2,
+   },
+
 };
 
 static const struct of_device_id atmel_pmc_ids[] __initconst = {
@@ -912,6 +917,7 @@ static const struct of_device_id atmel_pmc_ids[] 
__initconst = {
{ .compatible = "atmel,sama5d4-pmc", .data = _infos[1] },
{ .compatible = "atmel,sama5d2-pmc", .data = _infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = _infos[4] },
+   { .compatible = "microchip,sama7g5-pmc", .data = _infos[5] },
{ /* sentinel */ },
 };
 
-- 
2.25.1



[PATCH 19/24] ARM: at91: pm: save ddr phy calibration data to securam

2021-03-31 Thread Claudiu Beznea
The resuming from backup mode is done with the help of bootloader.
The bootloader reconfigure the DDR controller and DDR PHY controller.
To speed-up the resuming process save the PHY calibration data into
SECURAM before suspending (securam is powered on backup mode).
This data will be later used by bootloader in DDR PHY reconfiguration
process. Also, in the process or recalibration the first 8 words of
the memory may get corrupted. To solve this, these 8 words are saved
in the securam and restored by bootloader in the process of PHY
configuration.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 60 -
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 4dec7216a80e..91b4014d2e10 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,18 +28,23 @@
 #include "generic.h"
 #include "pm.h"
 
+#define BACKUP_DDR_PHY_CALIBRATION (9)
+
 /**
  * struct at91_pm_bu - AT91 power management backup unit data structure
  * @suspended: true if suspended to backup mode
  * @reserved: reserved
  * @canary: canary data for memory checking after exit from backup mode
  * @resume: resume API
+ * @ddr_phy_calibration: DDR PHY calibration data: ZQ0CR0, first 8 words
+ * of the memory
  */
 struct at91_pm_bu {
int suspended;
unsigned long reserved;
phys_addr_t canary;
phys_addr_t resume;
+   unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
 };
 
 /**
@@ -48,6 +54,7 @@ struct at91_pm_bu {
  * @ws_ids: wakup sources of_device_id array
  * @data: PM data to be used on last phase of suspend
  * @bu: backup unit mapped data (for backup mode)
+ * @memcs: memory chip select
  */
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
@@ -55,6 +62,7 @@ struct at91_soc_pm {
const struct of_device_id *ws_ids;
struct at91_pm_bu *bu;
struct at91_pm_data data;
+   void *memcs;
 };
 
 /**
@@ -316,6 +324,19 @@ extern u32 at91_pm_suspend_in_sram_sz;
 
 static int at91_suspend_finish(unsigned long val)
 {
+   int i;
+
+   if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
+   /*
+* The 1st 8 words of memory might get corrupted in the process
+* of DDR PHY recalibration; it is saved here in securam and it
+* will be restored later, after recalibration, by bootloader
+*/
+   for (i = 1; i < BACKUP_DDR_PHY_CALIBRATION; i++)
+   soc_pm.bu->ddr_phy_calibration[i] =
+   *((unsigned int *)soc_pm.memcs + (i - 1));
+   }
+
flush_cache_all();
outer_disable();
 
@@ -673,12 +694,40 @@ static bool __init at91_is_pm_mode_active(int pm_mode)
soc_pm.data.suspend_mode == pm_mode);
 }
 
+static int __init at91_pm_backup_scan_memcs(unsigned long node,
+   const char *uname, int depth,
+   void *data)
+{
+   const char *type;
+   const __be32 *reg;
+   int *located = data;
+   int size;
+
+   /* Memory node already located. */
+   if (*located)
+   return 0;
+
+   type = of_get_flat_dt_prop(node, "device_type", NULL);
+
+   /* We are scanning "memory" nodes only. */
+   if (!type || strcmp(type, "memory"))
+   return 0;
+
+   reg = of_get_flat_dt_prop(node, "reg", );
+   if (reg) {
+   soc_pm.memcs = __va((phys_addr_t)be32_to_cpu(*reg));
+   *located = 1;
+   }
+
+   return 0;
+}
+
 static int __init at91_pm_backup_init(void)
 {
struct gen_pool *sram_pool;
struct device_node *np;
struct platform_device *pdev;
-   int ret = -ENODEV;
+   int ret = -ENODEV, located = 0;
 
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return -EPERM;
@@ -713,6 +762,15 @@ static int __init at91_pm_backup_init(void)
soc_pm.bu->suspended = 0;
soc_pm.bu->canary = __pa_symbol();
soc_pm.bu->resume = __pa_symbol(cpu_resume);
+   if (soc_pm.data.ramc_phy) {
+   of_scan_flat_dt(at91_pm_backup_scan_memcs, );
+   if (!located)
+   goto securam_fail;
+
+   /* DDR3PHY_ZQ0SR0 */
+   soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
+ 0x188);
+   }
 
return 0;
 
-- 
2.25.1



[PATCH 24/24] ARM: at91: pm: add sama7g5 shdwc

2021-03-31 Thread Claudiu Beznea
Add SAMA7G5 SHDWC.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 24d5fd06d487..d6cfe7c4bb00 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -794,6 +794,7 @@ static int __init at91_pm_backup_init(void)
 static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
+   { .compatible = "microchip,sama7g5-shdwc" },
{ /* sentinel. */ }
 };
 
-- 
2.25.1



[PATCH 23/24] ARM: at91: pm: add pm support for SAMA7G5

2021-03-31 Thread Claudiu Beznea
Add support for SAMA7G5 power management modes: standby, ulp0, ulp1, backup.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/generic.h |  2 ++
 arch/arm/mach-at91/pm.c  | 37 
 arch/arm/mach-at91/sama7.c   |  1 +
 3 files changed, 40 insertions(+)

diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 0a4cdcb4985b..0c3960a8b3eb 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -14,12 +14,14 @@ extern void __init at91sam9_pm_init(void);
 extern void __init sam9x60_pm_init(void);
 extern void __init sama5_pm_init(void);
 extern void __init sama5d2_pm_init(void);
+extern void __init sama7_pm_init(void);
 #else
 static inline void __init at91rm9200_pm_init(void) { }
 static inline void __init at91sam9_pm_init(void) { }
 static inline void __init sam9x60_pm_init(void) { }
 static inline void __init sama5_pm_init(void) { }
 static inline void __init sama5d2_pm_init(void) { }
+static inline void __init sama7_pm_init(void) { }
 #endif
 
 #endif /* _AT91_GENERIC_H */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index f4e66a7c7d18..24d5fd06d487 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -152,6 +152,17 @@ static const struct of_device_id sam9x60_ws_ids[] = {
{ /* sentinel */ }
 };
 
+static const struct of_device_id sama7g5_ws_ids[] = {
+   { .compatible = "atmel,at91sam9x5-rtc", .data = _info[1] },
+   { .compatible = "microchip,sama7g5-ohci",   .data = _info[2] },
+   { .compatible = "usb-ohci", .data = _info[2] },
+   { .compatible = "atmel,at91sam9g45-ehci",   .data = _info[2] },
+   { .compatible = "usb-ehci", .data = _info[2] },
+   { .compatible = "microchip,sama7g5-sdhci",  .data = _info[3] },
+   { .compatible = "atmel,at91sam9260-rtt",.data = _info[4] },
+   { /* sentinel */ }
+};
+
 static int at91_pm_config_ws(unsigned int pm_mode, bool set)
 {
const struct wakeup_source_info *wsi;
@@ -1103,6 +1114,32 @@ void __init sama5d2_pm_init(void)
soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
 }
 
+void __init sama7_pm_init(void)
+{
+   static const int modes[] __initconst = {
+   AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP1, AT91_PM_BACKUP,
+   };
+   static const u32 iomaps[] __initconst = {
+   [AT91_PM_ULP0]  = AT91_PM_IOMAP(SFRBU),
+   [AT91_PM_ULP1]  = AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+   [AT91_PM_BACKUP]= AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+   };
+
+   if (!IS_ENABLED(CONFIG_SOC_SAMA7))
+   return;
+
+   at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
+
+   at91_dt_ramc(true);
+   at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
+   at91_pm_init(NULL);
+
+   soc_pm.ws_ids = sama7g5_ws_ids;
+   soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
+}
+
 static int __init at91_pm_modes_select(char *str)
 {
char *s;
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
index e04cadb569ad..bcabe4d82080 100644
--- a/arch/arm/mach-at91/sama7.c
+++ b/arch/arm/mach-at91/sama7.c
@@ -17,6 +17,7 @@
 static void __init sama7_common_init(void)
 {
of_platform_default_populate(NULL, NULL, NULL);
+   sama7_pm_init();
 }
 
 static void __init sama7_dt_device_init(void)
-- 
2.25.1



[PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

2021-03-31 Thread Claudiu Beznea
From: Eugen Hristev 

Introduce new family of SoCs, sama7, and first SoC, sama7g5.

Signed-off-by: Eugen Hristev 
Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/Makefile |  1 +
 arch/arm/mach-at91/sama7.c  | 48 +
 2 files changed, 49 insertions(+)
 create mode 100644 arch/arm/mach-at91/sama7.c

diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index f565490f1b70..6cc6624cddac 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_SOC_AT91SAM9)  += at91sam9.o
 obj-$(CONFIG_SOC_SAM9X60)  += sam9x60.o
 obj-$(CONFIG_SOC_SAMA5)+= sama5.o
 obj-$(CONFIG_SOC_SAMV7)+= samv7.o
+obj-$(CONFIG_SOC_SAMA7)+= sama7.o
 
 # Power Management
 obj-$(CONFIG_ATMEL_PM) += pm.o pm_suspend.o
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
new file mode 100644
index ..e04cadb569ad
--- /dev/null
+++ b/arch/arm/mach-at91/sama7.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Setup code for SAMA7
+ *
+ * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "generic.h"
+
+static void __init sama7_common_init(void)
+{
+   of_platform_default_populate(NULL, NULL, NULL);
+}
+
+static void __init sama7_dt_device_init(void)
+{
+   sama7_common_init();
+}
+
+static const char *const sama7_dt_board_compat[] __initconst = {
+   "microchip,sama7",
+   NULL
+};
+
+DT_MACHINE_START(sama7_dt, "Microchip SAMA7")
+   /* Maintainer: Microchip */
+   .init_machine   = sama7_dt_device_init,
+   .dt_compat  = sama7_dt_board_compat,
+MACHINE_END
+
+static const char *const sama7g5_dt_board_compat[] __initconst = {
+   "microchip,sama7g5",
+   NULL
+};
+
+DT_MACHINE_START(sama7g5_dt, "Microchip SAMA7G5")
+   /* Maintainer: Microchip */
+   .init_machine   = sama7_dt_device_init,
+   .dt_compat  = sama7g5_dt_board_compat,
+MACHINE_END
+
-- 
2.25.1



[PATCH 20/24] ARM: at91: pm: add backup mode support for SAMA7G5

2021-03-31 Thread Claudiu Beznea
Adapt at91_pm_backup_init() to work for SAMA7G5. Also, set the LPM pin
to shutdown controller. This will signal to PMIC that it needs to switch
to the state corresponding to backup mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 3 ++-
 arch/arm/mach-at91/pm_suspend.S | 7 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 91b4014d2e10..fcb20272d65d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -729,7 +729,8 @@ static int __init at91_pm_backup_init(void)
struct platform_device *pdev;
int ret = -ENODEV, located = 0;
 
-   if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
+   if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
+   !IS_ENABLED(CONFIG_SOC_SAMA7G5))
return -EPERM;
 
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 7396e18dd7e5..cbd61a3bcab1 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -106,6 +106,12 @@ lp_done_\ena:
 #endif
.endm
 
+   .macro at91_backup_set_lpm reg
+#ifdef CONFIG_SOC_SAMA7
+   orr \reg, \reg, #0x20
+#endif
+   .endm
+
.text
 
.arm
@@ -989,6 +995,7 @@ ulp_exit:
ldr r0, .shdwc
mov tmp1, #0xA500
add tmp1, tmp1, #0x1
+   at91_backup_set_lpm tmp1
str tmp1, [r0, #0]
 .endm
 
-- 
2.25.1



[PATCH 18/24] ARM: at91: pm: add sama7g5 ddr phy controller

2021-03-31 Thread Claudiu Beznea
SAMA7G5 self-refresh procedure accesses also the DDR PHY registers.
Adapt the code so that the at91_dt_ramc() to look also for DDR PHYs,
in case it is mandatory.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 27 +--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5dc942a2012d..4dec7216a80e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -552,7 +552,12 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ /*sentinel*/ }
 };
 
-static __init void at91_dt_ramc(void)
+static const struct of_device_id ramc_phy_ids[] __initconst = {
+   { .compatible = "microchip,sama7g5-ddr3phy", },
+   { /* Sentinel. */ },
+};
+
+static __init void at91_dt_ramc(bool phy_mandatory)
 {
struct device_node *np;
const struct of_device_id *of_id;
@@ -578,6 +583,16 @@ static __init void at91_dt_ramc(void)
if (!idx)
panic(pr_fmt("unable to find compatible ram controller node in 
dtb\n"));
 
+   /* Lookup for DDR PHY node, if any. */
+   for_each_matching_node_and_match(np, ramc_phy_ids, _id) {
+   soc_pm.data.ramc_phy = of_iomap(np, 0);
+   if (!soc_pm.data.ramc_phy)
+   panic(pr_fmt("unable to map ramc phy cpu registers\n"));
+   }
+
+   if (phy_mandatory && !soc_pm.data.ramc_phy)
+   panic(pr_fmt("DDR PHY is mandatory!\n"));
+
if (!standby) {
pr_warn("ramc no standby function available\n");
return;
@@ -936,7 +951,7 @@ void __init at91rm9200_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
 
-   at91_dt_ramc();
+   at91_dt_ramc(false);
 
/*
 * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
@@ -960,7 +975,7 @@ void __init sam9x60_pm_init(void)
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 
soc_pm.ws_ids = sam9x60_ws_ids;
@@ -980,7 +995,7 @@ void __init at91sam9_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
 
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(at91sam9_idle);
 }
 
@@ -994,7 +1009,7 @@ void __init sama5_pm_init(void)
return;
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 }
 
@@ -1015,7 +1030,7 @@ void __init sama5d2_pm_init(void)
 
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
-   at91_dt_ramc();
+   at91_dt_ramc(false);
at91_pm_init(NULL);
 
soc_pm.ws_ids = sama5d2_ws_ids;
-- 
2.25.1



[PATCH 17/24] ARM: at91: pm: add sama7g5 ddr controller

2021-03-31 Thread Claudiu Beznea
Add SAMA7G5 DDR controller to the list of DDR controller compatibles.
At the moment there is no standby support. Adapt the code for this.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 65e13769cf50..5dc942a2012d 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -548,6 +548,7 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ .compatible = "atmel,at91sam9260-sdramc", .data = _infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = _infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = _infos[3] },
+   { .compatible = "microchip,sama7g5-uddrc", },
{ /*sentinel*/ }
 };
 
@@ -565,9 +566,11 @@ static __init void at91_dt_ramc(void)
panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), 
idx);
 
ramc = of_id->data;
-   if (!standby)
-   standby = ramc->idle;
-   soc_pm.data.memctrl = ramc->memctrl;
+   if (ramc) {
+   if (!standby)
+   standby = ramc->idle;
+   soc_pm.data.memctrl = ramc->memctrl;
+   }
 
idx++;
}
-- 
2.25.1



[PATCH 14/24] ARM: at91: pm: add support for 2.5V LDO regulator control

2021-03-31 Thread Claudiu Beznea
Add support to disable/enable 2.5V LDO regulator when entering/exiting
any ULP mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.h |  1 +
 arch/arm/mach-at91/pm_suspend.S | 29 +
 2 files changed, 30 insertions(+)

diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 666474088d55..53bdc9000e44 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AT91_MEMCTRL_MC0
 #define AT91_MEMCTRL_SDRAMC1
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 8b0b8619ee8a..9c9e08fd8300 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -83,6 +83,29 @@ tmp3 .reqr6
 
.endm
 
+/**
+ * Set state for 2.5V low power regulator
+ * @ena: 0 - disable regulator
+ *  1 - enable regulator
+ *
+ * Side effects: overwrites r7, r8, r9, r10
+ */
+   .macro at91_2_5V_reg_set_low_power ena
+#ifdef CONFIG_SOC_SAMA7
+   ldr r7, .sfrbu
+   mov r8, #\ena
+   ldr r9, [r7, #AT91_SFRBU_25LDOCR]
+   orr r9, r9, #AT91_SFRBU_25LDOCR_LP
+   cmp r8, #1
+   beq lp_done_\ena
+   bic r9, r9, #AT91_SFRBU_25LDOCR_LP
+lp_done_\ena:
+   ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY
+   orr r9, r9, r10
+   str r9, [r7, #AT91_SFRBU_25LDOCR]
+#endif
+   .endm
+
.text
 
.arm
@@ -906,6 +929,9 @@ save_mck:
 
at91_plla_disable
 
+   /* Enable low power mode for 2.5V regulator. */
+   at91_2_5V_reg_set_low_power 1
+
ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
@@ -918,6 +944,9 @@ ulp1_mode:
b   ulp_exit
 
 ulp_exit:
+   /* Disable low power mode for 2.5V regulator. */
+   at91_2_5V_reg_set_low_power 0
+
ldr pmc, .pmc_base
 
at91_plla_enable
-- 
2.25.1



[PATCH 16/24] dt-bindings: atmel-sysreg: add bindings for sama7g5

2021-03-31 Thread Claudiu Beznea
Add RAM controller and RAM PHY controller DT bindings.

Signed-off-by: Claudiu Beznea 
---
 .../devicetree/bindings/arm/atmel-sysregs.txt | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt 
b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
index 807264a78edc..7cd55a760d41 100644
--- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
@@ -45,7 +45,8 @@ RAMC SDRAM/DDR Controller required properties:
"atmel,at91sam9260-sdramc",
"atmel,at91sam9g45-ddramc",
"atmel,sama5d3-ddramc",
-   "microchip,sam9x60-ddramc"
+   "microchip,sam9x60-ddramc",
+   "microchip,sama7g5-uddrc"
 - reg: Should contain registers location and length
 
 Examples:
@@ -55,6 +56,18 @@ Examples:
reg = <0xe800 0x200>;
};
 
+RAMC PHY Controller required properties:
+- compatible: Should be "microchip,sama7g5-ddr3phy", "syscon"
+- reg: Should contain registers location and length
+
+Example:
+
+   ddr3phy: ddr3phy@e3804000 {
+   compatible = "microchip,sama7g5-ddr3phy", "syscon";
+   reg = <0xe3804000 0x1000>;
+   status = "okay";
+};
+
 SHDWC Shutdown Controller
 
 required properties:
-- 
2.25.1



[PATCH 15/24] ARM: at91: pm: wait for ddr power mode off

2021-03-31 Thread Claudiu Beznea
Wait for DDR power mode off before shutting down the core.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 9c9e08fd8300..7396e18dd7e5 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -980,6 +980,11 @@ ulp_exit:
mov tmp1, #0x1
str tmp1, [r0, #0x10]
 
+   /* Wait for it. */
+1: ldr tmp1, [r0, #0x10]
+   tst tmp1, #0x1
+   beq 1b
+
/* Shutdown */
ldr r0, .shdwc
mov tmp1, #0xA500
-- 
2.25.1



[PATCH 02/24] ARM: at91: pm: move the setup of soc_pm.bu->suspended

2021-03-31 Thread Claudiu Beznea
Move the setup of soc_pm.bu->suspended in platform_suspend::begin
function so that the PMC code in charge with clocks suspend/resume
to differentiate b/w standard PM mode and backup mode.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index e13ceef7ac9a..3742a1fb76db 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -214,6 +214,8 @@ static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, 
u32 mode, u32 polarity)
  */
 static int at91_pm_begin(suspend_state_t state)
 {
+   int ret;
+
switch (state) {
case PM_SUSPEND_MEM:
soc_pm.data.mode = soc_pm.data.suspend_mode;
@@ -227,7 +229,16 @@ static int at91_pm_begin(suspend_state_t state)
soc_pm.data.mode = -1;
}
 
-   return at91_pm_config_ws(soc_pm.data.mode, true);
+   ret = at91_pm_config_ws(soc_pm.data.mode, true);
+   if (ret)
+   return ret;
+
+   if (soc_pm.data.mode == AT91_PM_BACKUP)
+   soc_pm.bu->suspended = 1;
+   else if (soc_pm.bu)
+   soc_pm.bu->suspended = 0;
+
+   return 0;
 }
 
 /*
@@ -296,8 +307,6 @@ static int at91_suspend_finish(unsigned long val)
 static void at91_pm_suspend(suspend_state_t state)
 {
if (soc_pm.data.mode == AT91_PM_BACKUP) {
-   soc_pm.bu->suspended = 1;
-
cpu_suspend(0, at91_suspend_finish);
 
/* The SRAM is lost between suspend cycles */
-- 
2.25.1



[PATCH 05/24] ARM: at91: pm: do not initialize pdev

2021-03-31 Thread Claudiu Beznea
There is no need to initialize pdev.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5a6ce1d88971..65e13769cf50 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -659,7 +659,7 @@ static int __init at91_pm_backup_init(void)
 {
struct gen_pool *sram_pool;
struct device_node *np;
-   struct platform_device *pdev = NULL;
+   struct platform_device *pdev;
int ret = -ENODEV;
 
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
-- 
2.25.1



[PATCH 04/24] ARM: at91: pm: check for different controllers in at91_pm_modes_init()

2021-03-31 Thread Claudiu Beznea
at91_pm_modes_init() checks for proper nodes in device tree and maps
them accordingly. Up to SAMA7G5 all AT91 SoCs had the same mapping
b/w power saving modes and different controllers needed in the
final/first steps of suspend/resume. SAMA7G5 is not aligned with the
old SoCs thus the code is adapted for this. This patch prepares
the field for next commits.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 143 +---
 1 file changed, 91 insertions(+), 52 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3029351ec78e..5a6ce1d88971 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -57,6 +57,18 @@ struct at91_soc_pm {
struct at91_pm_data data;
 };
 
+/**
+ * enum at91_pm_iomaps:IOs that needs to be mapped for different PM 
modes
+ * @AT91_PM_IOMAP_SHDWC:   SHDWC controller
+ * @AT91_PM_IOMAP_SFRBU:   SFRBU controller
+ */
+enum at91_pm_iomaps {
+   AT91_PM_IOMAP_SHDWC,
+   AT91_PM_IOMAP_SFRBU,
+};
+
+#define AT91_PM_IOMAP(name)BIT(AT91_PM_IOMAP_##name)
+
 static struct at91_soc_pm soc_pm = {
.data = {
.standby_mode = AT91_PM_STANDBY,
@@ -656,24 +668,15 @@ static int __init at91_pm_backup_init(void)
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
return 0;
 
-   np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
-   if (!np) {
-   pr_warn("%s: failed to find sfrbu!\n", __func__);
-   return ret;
-   }
-
-   soc_pm.data.sfrbu = of_iomap(np, 0);
-   of_node_put(np);
-
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
-   goto securam_fail_no_ref_dev;
+   return ret;
 
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev) {
pr_warn("%s: failed to find securam device!\n", __func__);
-   goto securam_fail_no_ref_dev;
+   return ret;
}
 
sram_pool = gen_pool_get(>dev, NULL);
@@ -697,64 +700,92 @@ static int __init at91_pm_backup_init(void)
 
 securam_fail:
put_device(>dev);
-securam_fail_no_ref_dev:
-   iounmap(soc_pm.data.sfrbu);
-   soc_pm.data.sfrbu = NULL;
return ret;
 }
 
-static void __init at91_pm_use_default_mode(int pm_mode)
-{
-   if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
-   return;
-
-   if (soc_pm.data.standby_mode == pm_mode)
-   soc_pm.data.standby_mode = AT91_PM_ULP0;
-   if (soc_pm.data.suspend_mode == pm_mode)
-   soc_pm.data.suspend_mode = AT91_PM_ULP0;
-}
-
 static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
{ /* sentinel. */ }
 };
 
-static void __init at91_pm_modes_init(void)
+static void __init at91_pm_modes_init(const u32 *maps, int len)
 {
struct device_node *np;
-   int ret;
+   int ret, mode;
 
-   if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
-   !at91_is_pm_mode_active(AT91_PM_ULP1))
-   return;
+   ret = at91_pm_backup_init();
+   if (ret) {
+   if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
+   soc_pm.data.standby_mode = AT91_PM_ULP0;
+   if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
+   soc_pm.data.suspend_mode = AT91_PM_ULP0;
+   }
 
-   np = of_find_matching_node(NULL, atmel_shdwc_ids);
-   if (!np) {
-   pr_warn("%s: failed to find shdwc!\n", __func__);
-   goto ulp1_default;
+   if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
+   maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
+   np = of_find_matching_node(NULL, atmel_shdwc_ids);
+   if (!np) {
+   pr_warn("%s: failed to find shdwc!\n", __func__);
+
+   /* Use ULP0 if it doesn't needs SHDWC.*/
+   if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
+   mode = AT91_PM_ULP0;
+   else
+   mode = AT91_PM_STANDBY;
+
+   if (maps[soc_pm.data.standby_mode] & 
AT91_PM_IOMAP(SHDWC))
+   soc_pm.data.standby_mode = mode;
+   if (maps[soc_pm.data.suspend_mode] & 
AT91_PM_IOMAP(SHDWC))
+   soc_pm.data.suspend_mode = mode;
+   } else {
+   soc_pm.data.shdwc = of_iomap(np, 0);
+   of_node_put(np);
+   }
}
 
-   soc_pm.data.shdwc = of_iomap(np, 0);
-   of_node_put(np);
+   if (maps[soc_pm.data.standby_mode] & AT91_PM_IOM

[PATCH 01/24] ARM: at91: pm: move pm_bu to soc_pm data structure

2021-03-31 Thread Claudiu Beznea
Move pm_bu to soc_pm data structure.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 90dcdfe3b3d0..e13ceef7ac9a 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -27,10 +27,25 @@
 #include "generic.h"
 #include "pm.h"
 
+/**
+ * struct at91_pm_bu - AT91 power management backup unit data structure
+ * @suspended: true if suspended to backup mode
+ * @reserved: reserved
+ * @canary: canary data for memory checking after exit from backup mode
+ * @resume: resume API
+ */
+struct at91_pm_bu {
+   int suspended;
+   unsigned long reserved;
+   phys_addr_t canary;
+   phys_addr_t resume;
+};
+
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
const struct of_device_id *ws_ids;
+   struct at91_pm_bu *bu;
struct at91_pm_data data;
 };
 
@@ -71,13 +86,6 @@ static int at91_pm_valid_state(suspend_state_t state)
 
 static int canary = 0xA5A5A5A5;
 
-static struct at91_pm_bu {
-   int suspended;
-   unsigned long reserved;
-   phys_addr_t canary;
-   phys_addr_t resume;
-} *pm_bu;
-
 struct wakeup_source_info {
unsigned int pmc_fsmr_bit;
unsigned int shdwc_mr_bit;
@@ -288,7 +296,7 @@ static int at91_suspend_finish(unsigned long val)
 static void at91_pm_suspend(suspend_state_t state)
 {
if (soc_pm.data.mode == AT91_PM_BACKUP) {
-   pm_bu->suspended = 1;
+   soc_pm.bu->suspended = 1;
 
cpu_suspend(0, at91_suspend_finish);
 
@@ -657,16 +665,16 @@ static int __init at91_pm_backup_init(void)
goto securam_fail;
}
 
-   pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
-   if (!pm_bu) {
+   soc_pm.bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct 
at91_pm_bu));
+   if (!soc_pm.bu) {
pr_warn("%s: unable to alloc securam!\n", __func__);
ret = -ENOMEM;
goto securam_fail;
}
 
-   pm_bu->suspended = 0;
-   pm_bu->canary = __pa_symbol();
-   pm_bu->resume = __pa_symbol(cpu_resume);
+   soc_pm.bu->suspended = 0;
+   soc_pm.bu->canary = __pa_symbol();
+   soc_pm.bu->resume = __pa_symbol(cpu_resume);
 
return 0;
 
-- 
2.25.1



[PATCH 03/24] ARM: at91: pm: document at91_soc_pm structure

2021-03-31 Thread Claudiu Beznea
Document at91_soc_pm structure.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3742a1fb76db..3029351ec78e 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -41,6 +41,14 @@ struct at91_pm_bu {
phys_addr_t resume;
 };
 
+/**
+ * struct at91_soc_pm - AT91 SoC power management data structure
+ * @config_shdwc_ws: wakeup sources configuration function for SHDWC
+ * @config_pmc_ws: wakeup srouces configuration function for PMC
+ * @ws_ids: wakup sources of_device_id array
+ * @data: PM data to be used on last phase of suspend
+ * @bu: backup unit mapped data (for backup mode)
+ */
 struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
-- 
2.25.1



[PATCH 13/24] ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes

2021-03-31 Thread Claudiu Beznea
Add support for MCK1..4 save restore for ULP modes.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 126 
 1 file changed, 126 insertions(+)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 84418120ba67..8b0b8619ee8a 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -765,7 +765,122 @@ sr_dis_exit:
 2:
 .endm
 
+/**
+ * at91_mckx_ps_enable:save MCK1..4 settings and switch it to main 
clock
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_enable
+#ifdef CONFIG_SOC_SAMA7
+   ldr pmc, .pmc_base
+
+   /* There are 4 MCKs we need to handle: MCK1..4 */
+   mov tmp1, #1
+e_loop:cmp tmp1, #5
+   beq e_done
+
+   /* Write MCK ID to retrieve the settings. */
+   str tmp1, [pmc, #AT91_PMC_MCR_V2]
+   ldr tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+e_save_mck1:
+   cmp tmp1, #1
+   bne e_save_mck2
+   str tmp2, .saved_mck1
+   b   e_ps
+
+e_save_mck2:
+   cmp tmp1, #2
+   bne e_save_mck3
+   str tmp2, .saved_mck2
+   b   e_ps
+
+e_save_mck3:
+   cmp tmp1, #3
+   bne e_save_mck4
+   str tmp2, .saved_mck3
+   b   e_ps
+
+e_save_mck4:
+   str tmp2, .saved_mck4
+
+e_ps:
+   /* Use CSS=MAINCK and DIV=1. */
+   bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS
+   bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV
+   orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK
+   orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1
+   str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+   wait_mckrdy tmp1
+
+   add tmp1, tmp1, #1
+   b   e_loop
+
+e_done:
+#endif
+.endm
+
+/**
+ * at91_mckx_ps_restore: restore MCK1..4 settings
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_restore
+#ifdef CONFIG_SOC_SAMA7
+   ldr pmc, .pmc_base
+
+   /* There are 4 MCKs we need to handle: MCK1..4 */
+   mov tmp1, #1
+r_loop:cmp tmp1, #5
+   beq r_done
+
+r_save_mck1:
+   cmp tmp1, #1
+   bne r_save_mck2
+   ldr tmp2, .saved_mck1
+   b   r_ps
+
+r_save_mck2:
+   cmp tmp1, #2
+   bne r_save_mck3
+   ldr tmp2, .saved_mck2
+   b   r_ps
+
+r_save_mck3:
+   cmp tmp1, #3
+   bne r_save_mck4
+   ldr tmp2, .saved_mck3
+   b   r_ps
+
+r_save_mck4:
+   ldr tmp2, .saved_mck4
+
+r_ps:
+   /* Write MCK ID to retrieve the settings. */
+   str tmp1, [pmc, #AT91_PMC_MCR_V2]
+   ldr tmp3, [pmc, #AT91_PMC_MCR_V2]
+
+   /* We need to restore CSS and DIV. */
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV
+   orr tmp3, tmp3, tmp2
+   bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK
+   orr tmp3, tmp3, tmp1
+   orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
+   str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+   wait_mckrdy tmp1
+
+   add tmp1, tmp1, #1
+   b   r_loop
+r_done:
+#endif
+.endm
+
 .macro at91_ulp_mode
+   at91_mckx_ps_enable
+
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode
@@ -817,6 +932,7 @@ ulp_exit:
mov tmp3, #0
wait_mckrdy tmp3
 
+   at91_mckx_ps_restore
 .endm
 
 .macro at91_backup_mode
@@ -946,6 +1062,16 @@ ENDPROC(at91_pm_suspend_in_sram)
.word 0
 .saved_osc_status:
.word 0
+#ifdef CONFIG_SOC_SAMA7
+.saved_mck1:
+   .word 0
+.saved_mck2:
+   .word 0
+.saved_mck3:
+   .word 0
+.saved_mck4:
+   .word 0
+#endif
 
 ENTRY(at91_pm_suspend_in_sram_sz)
.word .-at91_pm_suspend_in_sram
-- 
2.25.1



[PATCH 10/24] ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5

2021-03-31 Thread Claudiu Beznea
Add SFRBU registers definitions for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 include/soc/at91/sama7-sfrbu.h | 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 include/soc/at91/sama7-sfrbu.h

diff --git a/include/soc/at91/sama7-sfrbu.h b/include/soc/at91/sama7-sfrbu.h
new file mode 100644
index ..76b740810d34
--- /dev/null
+++ b/include/soc/at91/sama7-sfrbu.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 SFRBU registers offsets and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea 
+ */
+
+#ifndef __SAMA7_SFRBU_H__
+#define __SAMA7_SFRBU_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+#define AT91_SFRBU_PSWBU   (0x00)  /* SFRBU Power 
Switch BU Control Register */
+#defineAT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* 
Specific value mandatory to allow writing of other register bits */
+#defineAT91_SFRBU_PSWBU_STATE  (1 << 2)/* 
Power switch BU state */
+#defineAT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1)/* 
Power switch BU source selection */
+#defineAT91_SFRBU_PSWBU_CTRL   (1 << 0)/* 
Power switch BU control */
+
+#define AT91_SFRBU_25LDOCR (0x0C)  /* SFRBU 2.5V 
LDO Control Register */
+#defineAT91_SFRBU_25LDOCR_LDOANAKEY(0x3B6E18 << 8) /* 
Specific value mandatory to allow writing of other register bits. */
+#defineAT91_SFRBU_25LDOCR_STATE(1 << 3)/* 
LDOANA Switch On/Off Control */
+#defineAT91_SFRBU_25LDOCR_LP   (1 << 2)/* 
LDOANA Low-Power Mode Control */
+#defineAT91_SFRBU_PD_VALUE_MSK (0x3)
+#defineAT91_SFRBU_25LDOCR_PD_VALUE(v)  ((v) & 
AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */
+
+#define AT91_FRBU_DDRPWR   (0x10)  /* SFRBU DDR 
Power Control Register */
+#defineAT91_FRBU_DDRPWR_STATE  (1 << 0)/* DDR 
Power Mode State */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_SFRBU_H__ */
+
-- 
2.25.1



[PATCH 00/24] ARM: at91: pm: add support for sama7g5

2021-03-31 Thread Claudiu Beznea
Hi,

This series adds PM support for SAMA7G5. The standby, ulp0, ulp1, and
backup modes are supported.

Thank you,
Claudiu Beznea

Claudiu Beznea (23):
  ARM: at91: pm: move pm_bu to soc_pm data structure
  ARM: at91: pm: move the setup of soc_pm.bu->suspended
  ARM: at91: pm: document at91_soc_pm structure
  ARM: at91: pm: check for different controllers in at91_pm_modes_init()
  ARM: at91: pm: do not initialize pdev
  ARM: at91: pm: use r7 instead of tmp1
  ARM: at91: pm: avoid push and pop on stack while memory is in
self-refersh
  ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g
  ARM: at91: pm: add support for waiting MCK1..4
  ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5
  ARM: at91: ddr: add registers definitions for sama7g5's ddr
  ARM: at91: pm: add self-refresh support for sama7g5
  ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes
  ARM: at91: pm: add support for 2.5V LDO regulator control
  ARM: at91: pm: wait for ddr power mode off
  dt-bindings: atmel-sysreg: add bindings for sama7g5
  ARM: at91: pm: add sama7g5 ddr controller
  ARM: at91: pm: add sama7g5 ddr phy controller
  ARM: at91: pm: save ddr phy calibration data to securam
  ARM: at91: pm: add backup mode support for SAMA7G5
  ARM: at91: pm: add sama7g5's pmc
  ARM: at91: pm: add pm support for SAMA7G5
  ARM: at91: pm: add sama7g5 shdwc

Eugen Hristev (1):
  ARM: at91: sama7: introduce sama7 SoC family

 .../devicetree/bindings/arm/atmel-sysregs.txt |  15 +-
 arch/arm/mach-at91/Makefile   |   1 +
 arch/arm/mach-at91/generic.h  |   2 +
 arch/arm/mach-at91/pm.c   | 343 ++--
 arch/arm/mach-at91/pm.h   |   3 +
 arch/arm/mach-at91/pm_data-offsets.c  |   2 +
 arch/arm/mach-at91/pm_suspend.S   | 827 +-
 arch/arm/mach-at91/sama7.c|  49 ++
 include/soc/at91/sama7-ddr.h  |  80 ++
 include/soc/at91/sama7-sfrbu.h|  34 +
 10 files changed, 1066 insertions(+), 290 deletions(-)
 create mode 100644 arch/arm/mach-at91/sama7.c
 create mode 100644 include/soc/at91/sama7-ddr.h
 create mode 100644 include/soc/at91/sama7-sfrbu.h

-- 
2.25.1



[PATCH 12/24] ARM: at91: pm: add self-refresh support for sama7g5

2021-03-31 Thread Claudiu Beznea
Add self-refresh support for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm.h  |   2 +
 arch/arm/mach-at91/pm_data-offsets.c |   2 +
 arch/arm/mach-at91/pm_suspend.S  | 199 +++
 3 files changed, 203 insertions(+)

diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index bfb260be371e..666474088d55 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AT91_MEMCTRL_MC0
 #define AT91_MEMCTRL_SDRAMC1
@@ -27,6 +28,7 @@
 struct at91_pm_data {
void __iomem *pmc;
void __iomem *ramc[2];
+   void __iomem *ramc_phy;
unsigned long uhp_udp_mask;
unsigned int memctrl;
unsigned int mode;
diff --git a/arch/arm/mach-at91/pm_data-offsets.c 
b/arch/arm/mach-at91/pm_data-offsets.c
index 82089ff258c0..40bd4e8fe40a 100644
--- a/arch/arm/mach-at91/pm_data-offsets.c
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -8,6 +8,8 @@ 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_RAMC_PHY,offsetof(struct at91_pm_data,
+ramc_phy));
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
DEFINE(PM_DATA_MODE,offsetof(struct at91_pm_data, mode));
DEFINE(PM_DATA_SHDWC,   offsetof(struct at91_pm_data, shdwc));
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 7669b32d5257..84418120ba67 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -87,6 +87,200 @@ tmp3.reqr6
 
.arm
 
+#ifdef CONFIG_SOC_SAMA7
+/**
+ * Enable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
+ */
+.macro at91_sramc_self_refresh_ena
+   ldr r2, .sramc_base
+   ldr r3, .sramc_phy_base
+   ldr r7, .pm_mode
+
+   dsb
+
+   /* Disable all AXI ports. */
+   ldr tmp1, [r2, #UDDRC_PCTRL_0]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_0]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_1]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_1]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_2]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_2]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_3]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_3]
+
+   ldr tmp1, [r2, #UDDRC_PCTRL_4]
+   bic tmp1, tmp1, #0x1
+   str tmp1, [r2, #UDDRC_PCTRL_4]
+
+sr_ena_1:
+   /* Wait for all ports to disable. */
+   ldr tmp1, [r2, #UDDRC_PSTAT]
+   ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
+   tst tmp1, tmp2
+   bne sr_ena_1
+
+   /* Switch to self-refresh. */
+   ldr tmp1, [r2, #UDDRC_PWRCTL]
+   orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
+   str tmp1, [r2, #UDDRC_PWRCTL]
+
+sr_ena_2:
+   /* Wait for self-refresh enter. */
+   ldr tmp1, [r2, #UDDRC_STAT]
+   bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
+   cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
+   bne sr_ena_2
+
+   /* Put DDR PHY's DLL in bypass mode for non-backup modes. */
+   cmp r7, #AT91_PM_BACKUP
+   beq sr_ena_3
+   ldr tmp1, [r3, #DDR3PHY_PIR]
+   orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
+   str tmp1, [r3, #DDR3PHY_PIR]
+
+sr_ena_3:
+   /* Power down DDR PHY data receivers. */
+   ldr tmp1, [r3, #DDR3PHY_DXCCR]
+   orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+   str tmp1, [r3, #DDR3PHY_DXCCR]
+
+   /* Power down ADDR/CMD IO. */
+   ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+   orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+   orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+   orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+   str tmp1, [r3, #DDR3PHY_ACIOCR]
+
+   /* Power down ODT. */
+   ldr tmp1, [r3, #DDR3PHY_DSGCR]
+   orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+   str tmp1, [r3, #DDR3PHY_DSGCR]
+.endm
+
+/**
+ * Disable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
+ */
+.macro at91_sramc_self_refresh_dis
+   ldr r2, .sramc_base
+   ldr r3, .sramc_phy_base
+
+   /* Power up DDR PHY data receivers. */
+   ldr tmp1, [r3, #DDR3PHY_DXCCR]
+   bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+   str tmp1, [r3, #DDR3PHY_DXCCR]
+
+   /* Power up the output of CK and CS pins. */
+   ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+   bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+   bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+   bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+   str

[PATCH 06/24] ARM: at91: pm: use r7 instead of tmp1

2021-03-31 Thread Claudiu Beznea
Use r7 instead of tmp1 in macros. This prepares the filed for
next commits.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index b683c2caa40b..3d20c9880fee 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -31,30 +31,36 @@ tmp3.reqr6
 
 /*
  * Wait until master oscillator has stabilized.
+ *
+ * Side effects: overwrites r7
  */
.macro wait_moscrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MOSCS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+   tst r7, #AT91_PMC_MOSCS
beq 1b
.endm
 
 /*
  * Wait for main oscillator selection is done
+ *
+ * Side effects: overwrites r7
  */
.macro wait_moscsels
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MOSCSELS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+   tst r7, #AT91_PMC_MOSCSELS
beq 1b
.endm
 
 /*
  * Put the processor to enter the idle state
+ *
+ * Side effects: overwrites r7
  */
.macro at91_cpu_idle
 
 #if defined(CONFIG_CPU_V7)
-   mov tmp1, #AT91_PMC_PCK
-   str tmp1, [pmc, #AT91_PMC_SCDR]
+   mov r7, #AT91_PMC_PCK
+   str r7, [pmc, #AT91_PMC_SCDR]
 
dsb
 
-- 
2.25.1



[PATCH 09/24] ARM: at91: pm: add support for waiting MCK1..4

2021-03-31 Thread Claudiu Beznea
SAMA7G5 has 5 master clocks 0..4. MCK0 is controlled differently than
MCK 1..4. MCK 1..4 should also be saved/restored in the last phase of
suspend/resume. Thus, adapt wait_mckrdy to support also MCK1..4.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 48 -
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 1f63bbfad728..7669b32d5257 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -22,11 +22,23 @@ tmp3.reqr6
 
 /*
  * Wait until master clock is ready (after switching master clock source)
+ *
+ * @r_mckid:   register holding master clock identifier
+ *
+ * Side effects: overwrites r7, r8
  */
-   .macro wait_mckrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
-   tst tmp1, #AT91_PMC_MCKRDY
-   beq 1b
+   .macro wait_mckrdy r_mckid
+#ifdef CONFIG_SOC_SAMA7
+   cmp \r_mckid, #0
+   beq 1f
+   mov r7, #AT91_PMC_MCKXRDY
+   b   2f
+#endif
+1: mov r7, #AT91_PMC_MCKRDY
+2: ldr r8, [pmc, #AT91_PMC_SR]
+   and r8, r7
+   cmp r8, r7
+   bne 2b
.endm
 
 /*
@@ -231,7 +243,9 @@ sr_dis_exit:
bic tmp1, tmp1, #AT91_PMC_PRES
orr tmp1, tmp1, #AT91_PMC_PRES_64
str tmp1, [pmc, tmp3]
-   wait_mckrdy
+
+   mov tmp3, #0
+   wait_mckrdy tmp3
b   1f
 
 0:
@@ -267,10 +281,13 @@ sr_dis_exit:
bne 5f
 
/* Set lowest prescaler for fast resume. */
+   ldr tmp3, .mckr_offset
ldr tmp1, [pmc, tmp3]
bic tmp1, tmp1, #AT91_PMC_PRES
str tmp1, [pmc, tmp3]
-   wait_mckrdy
+
+   mov tmp3, #0
+   wait_mckrdy tmp3
b   6f
 
 5: /* Restore RC oscillator state */
@@ -307,6 +324,7 @@ sr_dis_exit:
 .macro at91_pm_ulp1_mode
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
+   mov tmp3, #0
 
/* Save RC oscillator state and check if it is enabled. */
ldr tmp1, [pmc, #AT91_PMC_SR]
@@ -348,7 +366,7 @@ sr_dis_exit:
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -361,7 +379,7 @@ sr_dis_exit:
nop
nop
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Enable the crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -377,7 +395,7 @@ sr_dis_exit:
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Switch main clock source to crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -394,7 +412,7 @@ sr_dis_exit:
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   wait_mckrdy tmp3
 
/* Restore RC oscillator state */
ldr tmp1, .saved_osc_status
@@ -573,10 +591,12 @@ sr_dis_exit:
 save_mck:
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
at91_plla_disable
 
+   ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
 
@@ -599,7 +619,8 @@ ulp_exit:
ldr tmp2, .saved_mckr
str tmp2, [pmc, tmp1]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
 .endm
 
@@ -611,7 +632,8 @@ ulp_exit:
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
 
-   wait_mckrdy
+   mov tmp3, #0
+   wait_mckrdy tmp3
 
/*BUMEN*/
ldr r0, .sfrbu
-- 
2.25.1



[PATCH 07/24] ARM: at91: pm: avoid push and pop on stack while memory is in self-refersh

2021-03-31 Thread Claudiu Beznea
For the previous AT91 RAM controller and self-refresh procedure this
had no side effects. However, for SAMA7G5 the self-refresh procedure
doesn't allow this anymore as the RAM controller ports are closed
before switching it to self-refresh. This commits prepares the code
for the following ones adding self-refresh and PM support for SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 397 +---
 1 file changed, 205 insertions(+), 192 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 3d20c9880fee..960ad29cce51 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -75,98 +75,147 @@ tmp3   .reqr6
 
.arm
 
-/*
- * void at91_suspend_sram_fn(struct at91_pm_data*)
- * @input param:
- * @r0: base address of struct at91_pm_data
+/**
+ * Enable self-refresh
+ *
+ * register usage:
+ * @r1: memory type
+ * @r2: base address of the sram controller
+ * @r3: temporary
  */
-/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of 
fncpy() */
-   .align 3
-ENTRY(at91_pm_suspend_in_sram)
-   /* Save registers on stack */
-   stmfd   sp!, {r4 - r12, lr}
+.macro at91_sramc_self_refresh_ena
+   ldr r1, .memtype
+   ldr r2, .sramc_base
 
-   /* Drain write buffer */
-   mov tmp1, #0
-   mcr p15, 0, tmp1, c7, c10, 4
+   cmp r1, #AT91_MEMCTRL_MC
+   bne sr_ena_ddrc_sf
 
-   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
-   ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
-   str tmp1, .mckr_offset
-   ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
-   str tmp1, .pmc_version
-   /* Both ldrne below are here to preload their address in the TLB */
-   ldr tmp1, [r0, #PM_DATA_SHDWC]
-   str tmp1, .shdwc
-   cmp tmp1, #0
-   ldrne   tmp2, [tmp1, #0]
-   ldr tmp1, [r0, #PM_DATA_SFRBU]
-   str tmp1, .sfrbu
-   cmp tmp1, #0
-   ldrne   tmp2, [tmp1, #0x10]
+   /* Active SDRAM self-refresh mode */
+   mov r3, #1
+   str r3, [r2, #AT91_MC_SDRAMC_SRR]
+   b   sr_ena_exit
 
-   /* Active the self-refresh mode */
-   mov r0, #SRAMC_SELF_FRESH_ACTIVE
-   bl  at91_sramc_self_refresh
+sr_ena_ddrc_sf:
+   cmp r1, #AT91_MEMCTRL_DDRSDR
+   bne sr_ena_sdramc_sf
 
-   ldr r0, .pm_mode
-   cmp r0, #AT91_PM_STANDBY
-   beq standby
-   cmp r0, #AT91_PM_BACKUP
-   beq backup_mode
+   /*
+* DDR Memory controller
+*/
 
-   bl  at91_ulp_mode
-   b   exit_suspend
+   /* LPDDR1 --> force DDR2 mode during self-refresh */
+   ldr r3, [r2, #AT91_DDRSDRC_MDR]
+   str r3, .saved_sam9_mdr
+   bic r3, r3, #~AT91_DDRSDRC_MD
+   cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+   ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+   biceq   r3, r3, #AT91_DDRSDRC_MD
+   orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+   streq   r3, [r2, #AT91_DDRSDRC_MDR]
 
-standby:
-   /* Wait for interrupt */
-   ldr pmc, .pmc_base
-   at91_cpu_idle
-   b   exit_suspend
+   /* Active DDRC self-refresh mode */
+   ldr r3, [r2, #AT91_DDRSDRC_LPR]
+   str r3, .saved_sam9_lpr
+   bic r3, r3, #AT91_DDRSDRC_LPCB
+   orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+   str r3, [r2, #AT91_DDRSDRC_LPR]
 
-backup_mode:
-   bl  at91_backup_mode
-   b   exit_suspend
+   /* If using the 2nd ddr controller */
+   ldr r2, .sramc1_base
+   cmp r2, #0
+   beq sr_ena_no_2nd_ddrc
 
-exit_suspend:
-   /* Exit the self-refresh mode */
-   mov r0, #SRAMC_SELF_FRESH_EXIT
-   bl  at91_sramc_self_refresh
+   ldr r3, [r2, #AT91_DDRSDRC_MDR]
+   str r3, .saved_sam9_mdr1
+   bic r3, r3, #~AT91_DDRSDRC_MD
+   cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+   ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+   biceq   r3, r3, #AT91_DDRSDRC_MD
+   orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+   streq   r3, [r2, #AT91_DDRSDRC_MDR]
 
-   /* Restore registers, and return */
-   ldmfd   sp!, {r4 - r12, pc}
-ENDPROC(at91_pm_suspend_in_sram)
+   /* Active DDRC self-refresh mode */
+   ldr r3, [r2, #AT91_DDRSDRC_LPR]
+   str r3, .saved_sam9_lpr1
+   bic r3, r3, #AT91_DDRSDRC_LPCB
+   orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+   str r3, [r2, #AT91_DDRSDRC_LPR]
 
-ENTRY(at91_backup_mode)
-   /* Switch the master cl

[PATCH 11/24] ARM: at91: ddr: add registers definitions for sama7g5's ddr

2021-03-31 Thread Claudiu Beznea
Add registers and bits definitions for SAMA7G5's UDDRC and DDR3PHY.

Signed-off-by: Claudiu Beznea 
---
 include/soc/at91/sama7-ddr.h | 80 
 1 file changed, 80 insertions(+)
 create mode 100644 include/soc/at91/sama7-ddr.h

diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h
new file mode 100644
index ..f6542584ca13
--- /dev/null
+++ b/include/soc/at91/sama7-ddr.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets
+ * and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea 
+ */
+
+#ifndef __SAMA7_DDR_H__
+#define __SAMA7_DDR_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+/* DDR3PHY */
+#define DDR3PHY_PIR(0x04)  /* DDR3PHY PHY 
Initialization Register  */
+#defineDDR3PHY_PIR_DLLBYP  (1 << 17)   /* DLL Bypass */
+#defineDDR3PHY_PIR_ITMSRST (1 << 4)/* 
Interface Timing Module Soft Reset */
+#defineDDR3PHY_PIR_DLLLOCK (1 << 2)/* DLL Lock */
+#defineDDR3PHY_PIR_DLLSRST (1 << 1)/* DLL 
Soft Rest */
+#defineDDR3PHY_PIR_INIT(1 << 0)/* 
Initialization Trigger */
+
+#define DDR3PHY_PGCR   (0x08)  /* DDR3PHY PHY 
General Configuration Register */
+#defineDDR3PHY_PGCR_CKDV1  (1 << 13)   /* CK# 
Disable Value */
+#defineDDR3PHY_PGCR_CKDV0  (1 << 12)   /* CK 
Disable Value */
+
+#defineDDR3PHY_PGSR(0x0C)  /* 
DDR3PHY PHY General Status Register */
+#defineDDR3PHY_PGSR_IDONE  (1 << 0)/* 
Initialization Done */
+
+#define DDR3PHY_ACIOCR (0x24)  /*  DDR3PHY AC 
I/O Configuration Register */
+#defineDDR3PHY_ACIOCR_CSPDD_CS0(1 << 18)   /* 
CS#[0] Power Down Driver */
+#defineDDR3PHY_ACIOCR_CKPDD_CK0(1 << 8)/* 
CK[0] Power Down Driver */
+#defineDDR3PHY_ACIORC_ACPDD(1 << 3)/* AC 
Power Down Driver */
+
+#define DDR3PHY_DXCCR  (0x28)  /* DDR3PHY 
DATX8 Common Configuration Register */
+#defineDDR3PHY_DXCCR_DXPDR (1 << 3)/* Data 
Power Down Receiver */
+
+#define DDR3PHY_DSGCR  (0x2C)  /* DDR3PHY DDR 
System General Configuration Register */
+#defineDDR3PHY_DSGCR_ODTPDD_ODT0   (1 << 20)   /* 
ODT[0] Power Down Driver */
+
+#define DDR3PHY_ZQ0SR0 (0x188) /* ZQ status 
register 0 */
+
+/* UDDRC */
+#define UDDRC_STAT (0x04)  /* UDDRC 
Operating Mode Status Register */
+#defineUDDRC_STAT_SELFREF_TYPE_DIS (0x0 << 4)  /* 
SDRAM is not in Self-refresh */
+#defineUDDRC_STAT_SELFREF_TYPE_PHY (0x1 << 4)  /* 
SDRAM is in Self-refresh, which was caused by PHY Master Request */
+#defineUDDRC_STAT_SELFREF_TYPE_SW  (0x2 << 4)  /* 
SDRAM is in Self-refresh, which was not caused solely under Automatic 
Self-refresh control */
+#defineUDDRC_STAT_SELFREF_TYPE_AUTO(0x3 << 4)  /* 
SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
+#defineUDDRC_STAT_SELFREF_TYPE_MSK (0x3 << 4)  /* 
Self-refresh type mask */
+#defineUDDRC_STAT_OPMODE_INIT  (0x0 << 0)  /* Init 
*/
+#defineUDDRC_STAT_OPMODE_NORMAL(0x1 << 0)  /* 
Normal */
+#defineUDDRC_STAT_OPMODE_PWRDOWN   (0x2 << 0)  /* 
Power-down */
+#defineUDDRC_STAT_OPMODE_SELF_REFRESH  (0x3 << 0)  /* 
Self-refresh */
+#defineUDDRC_STAT_OPMODE_MSK   (0x7 << 0)  /* 
Operating mode mask */
+
+#define UDDRC_PWRCTL   (0x30)  /* UDDRC Low 
Power Control Register */
+#defineUDDRC_PWRCTRL_SELFREF_SW(1 << 5)/* 
Software self-refresh */
+
+#define UDDRC_DFIMISC  (0x1B0) /* UDDRC DFI 
Miscellaneous Control Register */
+#defineUDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY 
initialization complete enable signal */
+
+#define UDDRC_SWCTRL   (0x320) /* UDDRC 
Software Register Programming Control Enable */
+#defineUDDRC_SWCTRL_SW_DONE(1 << 0)/* 
Enable quasi-dynamic register programming outside reset */
+
+#define UDDRC

[PATCH 08/24] ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g

2021-03-31 Thread Claudiu Beznea
Replace CONFIG_SOC_SAM9X60 with CONFIG_HAVE_AT91_SAM9X60_PLL as the
SAM9X60's PLL is also present on SAMA7G5.

Signed-off-by: Claudiu Beznea 
---
 arch/arm/mach-at91/pm_suspend.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 960ad29cce51..1f63bbfad728 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -422,7 +422,7 @@ sr_dis_exit:
cmp tmp1, #AT91_PMC_V1
beq 1f
 
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* Save PLLA settings. */
ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
@@ -489,7 +489,7 @@ sr_dis_exit:
cmp tmp3, #AT91_PMC_V1
beq 4f
 
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* step 1. */
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
-- 
2.25.1



[RESEND PATCH 5/5] clk: at91: clk-master: update for dvfs

2021-03-24 Thread Claudiu Beznea
SAMA7G5 supports CPU DVFS. The hardware block diagram for the clock
system generating CPU clock is as follows:

   ++
   +-->|divider1|--> CPU clock
   |   ++
++   +--+  |   ++
|CPU PLL |-->|prescaller|--+-->|divider0|--> MCK0 clock
++   +--+  ++

The divider1 is not implemented in software since the supported CPU
frequencies could be directly retrieved from CPU PLL + prescaller.
Every time the CPU clock needs to be changed the MCK0 should also be
changed to avoid its over/under clocking and also to preserve its
initial value (200MHz). MCK0 feeds IPs that are glitch free aware.

The initial approach for implementing DVFS was to implement MCK0 and
CPU clocks as 2 different Linux clocks, to pass these two clocks to CPUFreq
driver and in CPUFreq driver to run clk_set_rate() on CPU and MCK clocks
accordingly. E.g. if 1GHz speed was requested by CPUFreq subsystem the
following were executed in CPUFreq driver:

/* ... */
clk_set_rate(mck0, intermediary_freq_to_avoid_over_under_clocking);
clk_set_rate(cpu, 10);
clk_set_rate(mck0, initial_freq);
/ ... */

However, it has been proposed in [1] to use the generic cpufreq-dt driver
and to overload the necessary clocks operations in the proper clock
driver.

To address this proposal the master clock prescaller registers a clock
notifier that will update properly the master clock divider on
PRE_RATE_CHANGE and POST_RATE_CHANGE events to avoid master clock
divider over/under clocking and also to preserve its initial value
(200MHz).

[1] 
https://lore.kernel.org/lkml/1609842147-8161-1-git-send-email-claudiu.bez...@microchip.com/

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/at91rm9200.c  |   2 +-
 drivers/clk/at91/at91sam9260.c |   2 +-
 drivers/clk/at91/at91sam9g45.c |   2 +-
 drivers/clk/at91/at91sam9n12.c |   2 +-
 drivers/clk/at91/at91sam9rl.c  |   2 +-
 drivers/clk/at91/at91sam9x5.c  |   2 +-
 drivers/clk/at91/clk-master.c  | 187 -
 drivers/clk/at91/dt-compat.c   |   2 +-
 drivers/clk/at91/pmc.h |   3 +-
 drivers/clk/at91/sam9x60.c |   2 +-
 drivers/clk/at91/sama5d2.c |   2 +-
 drivers/clk/at91/sama5d3.c |   2 +-
 drivers/clk/at91/sama5d4.c |   2 +-
 drivers/clk/at91/sama7g5.c |   2 +-
 14 files changed, 130 insertions(+), 84 deletions(-)

diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c
index 0fad1009f315..749c0b1e9c3d 100644
--- a/drivers/clk/at91/at91rm9200.c
+++ b/drivers/clk/at91/at91rm9200.c
@@ -144,7 +144,7 @@ static void __init at91rm9200_pmc_setup(struct device_node 
*np)
   _master_layout,
   _mck_characteristics,
   _mck_lock, CLK_SET_RATE_GATE,
-  INT_MIN);
+  INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
 
diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c
index ceb5495f723a..c01d9455f6d4 100644
--- a/drivers/clk/at91/at91sam9260.c
+++ b/drivers/clk/at91/at91sam9260.c
@@ -420,7 +420,7 @@ static void __init at91sam926x_pmc_setup(struct device_node 
*np,
   _master_layout,
   data->mck_characteristics,
   _mck_lock,
-  CLK_SET_RATE_GATE, INT_MIN);
+  CLK_SET_RATE_GATE, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
 
diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c
index 0214333dedd3..8364e7a06cfc 100644
--- a/drivers/clk/at91/at91sam9g45.c
+++ b/drivers/clk/at91/at91sam9g45.c
@@ -155,7 +155,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node 
*np)
   _master_layout,
   _characteristics,
   _mck_lock,
-  CLK_SET_RATE_GATE, INT_MIN);
+  CLK_SET_RATE_GATE, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
 
diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c
index f9db5316a7f1..ddcae243a4ea 100644
--- a/drivers/clk/at91/at91sam9n12.c
+++ b/drivers/clk/at91/at91sam9n12.c
@@ -182,7 +182,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node 
*np)
   _master_layout,
   _characteristics,
   _mck_lock,
-  CLK_SET_RATE_GATE, INT_MIN);
+  CLK_SET_RAT

[RESEND PATCH 3/5] clk: at91: sama7g5: add securam's peripheral clock

2021-03-24 Thread Claudiu Beznea
Add SECURAM's peripheral clock.

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/sama7g5.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
index a6e20b35960e..28e26fb90417 100644
--- a/drivers/clk/at91/sama7g5.c
+++ b/drivers/clk/at91/sama7g5.c
@@ -377,6 +377,7 @@ static const struct {
u8 id;
 } sama7g5_periphck[] = {
{ .n = "pioA_clk",  .p = "mck0", .id = 11, },
+   { .n = "securam_clk",   .p = "mck0", .id = 18, },
{ .n = "sfr_clk",   .p = "mck1", .id = 19, },
{ .n = "hsmc_clk",  .p = "mck1", .id = 21, },
{ .n = "xdmac0_clk",.p = "mck1", .id = 22, },
-- 
2.25.1



[RESEND PATCH 4/5] clk: at91: clk-master: add register definition for sama7g5's master clock

2021-03-24 Thread Claudiu Beznea
Add register definitions for SAMA7G5's master clock. These would be
also used by architecture specific power saving code. With this, update
also clk-master.c.

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/clk-master.c | 51 +--
 include/linux/clk/at91_pmc.h  | 26 ++
 2 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index 6f1fb2eb2a8d..a6a393bb1def 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -17,15 +17,7 @@
 #define MASTER_DIV_SHIFT   8
 #define MASTER_DIV_MASK0x7
 
-#define PMC_MCR0x30
-#define PMC_MCR_ID_MSK GENMASK(3, 0)
-#define PMC_MCR_CMDBIT(7)
-#define PMC_MCR_DIVGENMASK(10, 8)
-#define PMC_MCR_CSSGENMASK(20, 16)
 #define PMC_MCR_CSS_SHIFT  (16)
-#define PMC_MCR_EN BIT(28)
-
-#define PMC_MCR_ID(x)  ((x) & PMC_MCR_ID_MSK)
 
 #define MASTER_MAX_ID  4
 
@@ -685,17 +677,20 @@ static void clk_sama7g5_master_set(struct clk_master 
*master,
 
spin_lock_irqsave(master->lock, flags);
 
-   regmap_write(master->regmap, PMC_MCR, PMC_MCR_ID(master->id));
-   regmap_read(master->regmap, PMC_MCR, );
-   regmap_update_bits(master->regmap, PMC_MCR,
-  (status ? PMC_MCR_EN : 0) | PMC_MCR_CSS | 
PMC_MCR_DIV |
-  PMC_MCR_CMD | PMC_MCR_ID_MSK,
-  (status ? PMC_MCR_EN : 0) |
+   regmap_write(master->regmap, AT91_PMC_MCR_V2,
+AT91_PMC_MCR_V2_ID(master->id));
+   regmap_read(master->regmap, AT91_PMC_MCR_V2, );
+   regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
+  (status ? AT91_PMC_MCR_V2_EN : 0) |
+  AT91_PMC_MCR_V2_CSS | AT91_PMC_MCR_V2_DIV |
+  AT91_PMC_MCR_V2_CMD | AT91_PMC_MCR_V2_ID_MSK,
+  (status ? AT91_PMC_MCR_V2_EN : 0) |
   (master->parent << PMC_MCR_CSS_SHIFT) |
   (master->div << MASTER_DIV_SHIFT) |
-  PMC_MCR_CMD | PMC_MCR_ID(master->id));
+  AT91_PMC_MCR_V2_CMD |
+  AT91_PMC_MCR_V2_ID(master->id));
 
-   cparent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
+   cparent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
 
/* Wait here only if parent is being changed. */
while ((cparent != master->parent) && !clk_master_ready(master))
@@ -720,10 +715,12 @@ static void clk_sama7g5_master_disable(struct clk_hw *hw)
 
spin_lock_irqsave(master->lock, flags);
 
-   regmap_write(master->regmap, PMC_MCR, master->id);
-   regmap_update_bits(master->regmap, PMC_MCR,
-  PMC_MCR_EN | PMC_MCR_CMD | PMC_MCR_ID_MSK,
-  PMC_MCR_CMD | PMC_MCR_ID(master->id));
+   regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+   regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
+  AT91_PMC_MCR_V2_EN | AT91_PMC_MCR_V2_CMD |
+  AT91_PMC_MCR_V2_ID_MSK,
+  AT91_PMC_MCR_V2_CMD |
+  AT91_PMC_MCR_V2_ID(master->id));
 
spin_unlock_irqrestore(master->lock, flags);
 }
@@ -736,12 +733,12 @@ static int clk_sama7g5_master_is_enabled(struct clk_hw 
*hw)
 
spin_lock_irqsave(master->lock, flags);
 
-   regmap_write(master->regmap, PMC_MCR, master->id);
-   regmap_read(master->regmap, PMC_MCR, );
+   regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+   regmap_read(master->regmap, AT91_PMC_MCR_V2, );
 
spin_unlock_irqrestore(master->lock, flags);
 
-   return !!(val & PMC_MCR_EN);
+   return !!(val & AT91_PMC_MCR_V2_EN);
 }
 
 static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -837,10 +834,10 @@ at91_clk_sama7g5_register_master(struct regmap *regmap,
master->mux_table = mux_table;
 
spin_lock_irqsave(master->lock, flags);
-   regmap_write(master->regmap, PMC_MCR, master->id);
-   regmap_read(master->regmap, PMC_MCR, );
-   master->parent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
-   master->div = (val & PMC_MCR_DIV) >> MASTER_DIV_SHIFT;
+   regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+   regmap_read(master->regmap, AT91_PMC_MCR_V2, );
+   master->parent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
+   master->div = (val & AT91_PMC_MCR_V2_DIV) >> MASTER_DIV_SHIFT;
spin_unlock_irqrestore(master->lock, flags);
 
   

[RESEND PATCH 2/5] clk: at91: pmc: execute suspend/resume only for backup mode

2021-03-24 Thread Claudiu Beznea
Before going to backup mode architecture specific PM code sets the first
word in securam (and it will be cleared in a subsequent commit for the rest
of power saving modes). Thus take this into account when
suspending/resuming clocks. This will avoid executing unnecessary
instructions when suspending to non backup modes. Since the clear of the
1st word in securam will be done in a subsequent commit the current commit
will not broke the current behavior since up to this moment the
suspend/resume were executed for all AT91 PM modes. The difference now
is that the suspend/resume for clocks will be executed for the rest of
AT91 PM modes just after the 1st enter/exit to/from backup mode.
Also this commit changed the postcore_initcall() with subsys_initcall()
to be able to execute of_find_compatible_node() since this was not
available at the moment of postcore_initcall(). This should not alter
the tcb_clksrc since the changes are related to clocks suspend/resume
procedure that will be executed at the user space request, thus long
ago after postcore_initcall().

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/pmc.c | 48 ++
 1 file changed, 39 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 77b57c9f5dcb..c226d33cd899 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -8,6 +8,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -110,13 +112,35 @@ struct pmc_data *pmc_data_allocate(unsigned int ncore, 
unsigned int nsystem,
 }
 
 #ifdef CONFIG_PM
+
+/* Address in SECURAM that say if we suspend to backup mode. */
+static void __iomem *at91_pmc_backup_suspend;
+
 static int at91_pmc_suspend(void)
 {
+   unsigned int backup;
+
+   if (!at91_pmc_backup_suspend)
+   return 0;
+
+   backup = *(unsigned int *)at91_pmc_backup_suspend;
+   if (!backup)
+   return 0;
+
return clk_save_context();
 }
 
 static void at91_pmc_resume(void)
 {
+   unsigned int backup;
+
+   if (!at91_pmc_backup_suspend)
+   return;
+
+   backup = *(unsigned int *)at91_pmc_backup_suspend;
+   if (!backup)
+   return;
+
clk_restore_context();
 }
 
@@ -125,24 +149,30 @@ static struct syscore_ops pmc_syscore_ops = {
.resume = at91_pmc_resume,
 };
 
-static const struct of_device_id sama5d2_pmc_dt_ids[] = {
-   { .compatible = "atmel,sama5d2-pmc" },
-   { /* sentinel */ }
-};
-
 static int __init pmc_register_ops(void)
 {
+   struct platform_device *pdev;
struct device_node *np;
 
-   np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
+   np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
-   return 0;
+   return -ENODEV;
+
+   pdev = of_find_device_by_node(np);
of_node_put(np);
+   if (!pdev)
+   return -ENODEV;
+
+   at91_pmc_backup_suspend = of_iomap(np, 0);
+   if (!at91_pmc_backup_suspend) {
+   pr_warn("%s(): unable to map securam\n", __func__);
+   return -ENOMEM;
+   }
 
register_syscore_ops(_syscore_ops);
 
return 0;
 }
-/* This has to happen before arch_initcall because of the tcb_clksrc driver */
-postcore_initcall(pmc_register_ops);
+
+subsys_initcall(pmc_register_ops);
 #endif
-- 
2.25.1



[RESEND PATCH 1/5] clk: at91: re-factor clocks suspend/resume

2021-03-24 Thread Claudiu Beznea
SAMA5D2 and SAMA7G5 have a special power saving mode (backup mode) where
most of the SoC's components are powered off (including PMC). Resuming
from this mode is done with the help of bootloader. Peripherals are not
aware of the power saving mode thus most of them are disabling clocks in
proper suspend API and re-enable them in resume API without taking into
account the previously setup rate. Moreover some of the peripherals are
acting as wakeup sources and are not disabling the clocks in this
scenario, when suspending. Since backup mode cuts the power for
peripherals, in resume part these clocks needs to be re-configured.

The initial PMC suspend/resume code was designed with SAMA5D2's PMC
in mind. SAMA7G's PMC is different (few new functionalities, different
registers offsets, different offsets in registers for each
functionalities). To address both SAMA5D2 and SAMA7G5 PMC add
.save_context()/.resume_context() support to each clocks driver and call
this from PMC driver.

Signed-off-by: Claudiu Beznea 
---
 drivers/clk/at91/clk-generated.c|  45 +--
 drivers/clk/at91/clk-main.c |  66 ++
 drivers/clk/at91/clk-master.c   | 183 ++--
 drivers/clk/at91/clk-peripheral.c   |  38 +-
 drivers/clk/at91/clk-pll.c  |  37 ++
 drivers/clk/at91/clk-programmable.c |  29 -
 drivers/clk/at91/clk-sam9x60-pll.c  |  68 ++-
 drivers/clk/at91/clk-system.c   |  20 +++
 drivers/clk/at91/clk-usb.c  |  27 
 drivers/clk/at91/clk-utmi.c |  47 ++-
 drivers/clk/at91/pmc.c  | 149 ++
 drivers/clk/at91/pmc.h  |  24 ++--
 12 files changed, 554 insertions(+), 179 deletions(-)

diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index b4fc8d71daf2..0e436f9e7508 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -27,6 +27,7 @@ struct clk_generated {
u32 id;
u32 gckdiv;
const struct clk_pcr_layout *layout;
+   struct at91_clk_pms pms;
u8 parent_id;
int chg_pid;
 };
@@ -34,25 +35,34 @@ struct clk_generated {
 #define to_clk_generated(hw) \
container_of(hw, struct clk_generated, hw)
 
-static int clk_generated_enable(struct clk_hw *hw)
+static int clk_generated_set(struct clk_generated *gck, int status)
 {
-   struct clk_generated *gck = to_clk_generated(hw);
unsigned long flags;
 
-   pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
-__func__, gck->gckdiv, gck->parent_id);
-
spin_lock_irqsave(gck->lock, flags);
regmap_write(gck->regmap, gck->layout->offset,
 (gck->id & gck->layout->pid_mask));
regmap_update_bits(gck->regmap, gck->layout->offset,
   AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
-  gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+  gck->layout->cmd | (status ? AT91_PMC_PCR_GCKEN : 0),
   field_prep(gck->layout->gckcss_mask, gck->parent_id) 
|
   gck->layout->cmd |
   FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
-  AT91_PMC_PCR_GCKEN);
+  (status ? AT91_PMC_PCR_GCKEN : 0));
spin_unlock_irqrestore(gck->lock, flags);
+
+   return 0;
+}
+
+static int clk_generated_enable(struct clk_hw *hw)
+{
+   struct clk_generated *gck = to_clk_generated(hw);
+
+   pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
+__func__, gck->gckdiv, gck->parent_id);
+
+   clk_generated_set(gck, 1);
+
return 0;
 }
 
@@ -239,6 +249,23 @@ static int clk_generated_set_rate(struct clk_hw *hw,
return 0;
 }
 
+static int clk_generated_save_context(struct clk_hw *hw)
+{
+   struct clk_generated *gck = to_clk_generated(hw);
+
+   gck->pms.status = clk_generated_is_enabled(>hw);
+
+   return 0;
+}
+
+static void clk_generated_restore_context(struct clk_hw *hw)
+{
+   struct clk_generated *gck = to_clk_generated(hw);
+
+   if (gck->pms.status)
+   clk_generated_set(gck, gck->pms.status);
+}
+
 static const struct clk_ops generated_ops = {
.enable = clk_generated_enable,
.disable = clk_generated_disable,
@@ -248,6 +275,8 @@ static const struct clk_ops generated_ops = {
.get_parent = clk_generated_get_parent,
.set_parent = clk_generated_set_parent,
.set_rate = clk_generated_set_rate,
+   .save_context = clk_generated_save_context,
+   .restore_context = clk_generated_restore_context,
 };
 
 /**
@@ -314,8 +343,6 @@ at91_clk_register_generated(struct regmap *regmap, 
spinlock_t *lock,
if (ret) {
kfree(gck);
hw = ERR_PTR(ret);
-   } else {
-

[RESEND PATCH 0/5] clk: at91: updates for power management and dvfs

2021-03-24 Thread Claudiu Beznea
Hi,

This series addresses the power management for SAMA7G5 and also updates
the master clock prescaller and master clock divider drivers to accommodate
the requests at [1].

The power management part is implemented by adding
save_context()/restore_context() on each clock driver (patch 1/5). Since
the PM part is necessary only for backup mode (supported on SAMA5D2 and
SAMA7G5) the pmc.c has been adapted to call the
save_context()/restore_context() only on switches to/from backup mode
(patch 2/5).

Patch 3/5 adds the securam clock on SAMA7G5. This is necessary for
backup mode of SAMA7G5.

Patch 4/5 adds registers definitions for the new master clocks (MCK1..4) of
SAMA7G5 and adapt the clk-master.c. The defines exported in
include/linux/clk/at91_pmc.h will be also used by platform specific PM
code.

Patch 5/5 adpat the master clock divider and master clock prescaller
to address the requests at [1].

Thank you,
Claudiu Beznea

[1] https://lore.kernel.org/lkml/20210105104426.4tmgc2l3vyicwedd@vireshk-i7/

Claudiu Beznea (5):
  clk: at91: re-factor clocks suspend/resume
  clk: at91: pmc: execute suspend/resume only for backup mode
  clk: at91: sama7g5: add securam's peripheral clock
  clk: at91: clk-master: add register definition for sama7g5's master
clock
  clk: at91: clk-master: update for dvfs

 drivers/clk/at91/at91rm9200.c   |   2 +-
 drivers/clk/at91/at91sam9260.c  |   2 +-
 drivers/clk/at91/at91sam9g45.c  |   2 +-
 drivers/clk/at91/at91sam9n12.c  |   2 +-
 drivers/clk/at91/at91sam9rl.c   |   2 +-
 drivers/clk/at91/at91sam9x5.c   |   2 +-
 drivers/clk/at91/clk-generated.c|  45 +++-
 drivers/clk/at91/clk-main.c |  66 +
 drivers/clk/at91/clk-master.c   | 395 +---
 drivers/clk/at91/clk-peripheral.c   |  38 ++-
 drivers/clk/at91/clk-pll.c  |  37 +++
 drivers/clk/at91/clk-programmable.c |  29 +-
 drivers/clk/at91/clk-sam9x60-pll.c  |  68 -
 drivers/clk/at91/clk-system.c   |  20 ++
 drivers/clk/at91/clk-usb.c  |  27 ++
 drivers/clk/at91/clk-utmi.c |  47 +++-
 drivers/clk/at91/dt-compat.c|   2 +-
 drivers/clk/at91/pmc.c  | 175 +++-
 drivers/clk/at91/pmc.h  |  27 +-
 drivers/clk/at91/sam9x60.c  |   2 +-
 drivers/clk/at91/sama5d2.c  |   2 +-
 drivers/clk/at91/sama5d3.c  |   2 +-
 drivers/clk/at91/sama5d4.c  |   2 +-
 drivers/clk/at91/sama7g5.c  |   3 +-
 include/linux/clk/at91_pmc.h|  26 ++
 25 files changed, 750 insertions(+), 275 deletions(-)

-- 
2.25.1



[PATCH 0/2] irqchip/mchp-eic: add driver for Microchip EIC

2021-03-02 Thread Claudiu Beznea
Hi,

This patch adds support for Microchip External Interrupt Controller
present on SAMA7G5. The controller supports for 2 external interrupt
lines, glitch filter capabilities and is connected to GIC as follows:

pinX   +--+ EXT_IRQ0 +--+ int 153 (for pinX) +--+
-->|  |->|  |--->|  |
pinY   | PIO  | EXT_IRQ1 | EIC  | int 154 (for pinY) | GIC  |
-->|  |->|  |--->|  |
   +--+  +--++--+

where PIO is the pin controller.

Thank you,
Claudiu Beznea

Claudiu Beznea (2):
  dt-bindings: mchp-eic: add bindings
  irqchip/mchp-eic: add support

 .../interrupt-controller/mchp,eic.yaml|  74 
 MAINTAINERS   |   6 +
 drivers/irqchip/Kconfig   |   7 +
 drivers/irqchip/Makefile  |   1 +
 drivers/irqchip/irq-mchp-eic.c| 350 ++
 5 files changed, 438 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/interrupt-controller/mchp,eic.yaml
 create mode 100644 drivers/irqchip/irq-mchp-eic.c

-- 
2.25.1



[PATCH 2/2] irqchip/mchp-eic: add support

2021-03-02 Thread Claudiu Beznea
Add support for Microchip External Interrupt Controller.

Signed-off-by: Claudiu Beznea 
---
 MAINTAINERS|   6 +
 drivers/irqchip/Kconfig|   7 +
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/irq-mchp-eic.c | 350 +
 4 files changed, 364 insertions(+)
 create mode 100644 drivers/irqchip/irq-mchp-eic.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a008b70f3c16..ea99e5a7f519 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11585,6 +11585,12 @@ L: linux-arm-ker...@lists.infradead.org (moderated 
for non-subscribers)
 S: Supported
 F: drivers/usb/gadget/udc/atmel_usba_udc.*
 
+MICROCHIP EIC DRIVER
+M: Claudiu Beznea 
+L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers)
+S: Supported
+F: drivers/irqchip/irq-mchp-eic.c
+
 MICROCHIP WILC1000 WIFI DRIVER
 M: Ajay Singh 
 M: Claudiu Beznea 
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 2aa79c32ee22..7c7ca33c3f7d 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -596,4 +596,11 @@ config MST_IRQ
help
  Support MStar Interrupt Controller.
 
+config MCHP_EIC
+   bool "Microchip External Interrupt Controller"
+   depends on ARCH_AT91 || COMPILE_TEST
+   select IRQ_DOMAIN
+   help
+ Support for Microchip External Interrupt Controller.
+
 endmenu
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 94c2885882ee..f3df6eb7c4c3 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -114,3 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC)  += 
irq-loongson-pch-pic.o
 obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o
 obj-$(CONFIG_MST_IRQ)  += irq-mst-intc.o
 obj-$(CONFIG_SL28CPLD_INTC)+= irq-sl28cpld.o
+obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o
diff --git a/drivers/irqchip/irq-mchp-eic.c b/drivers/irqchip/irq-mchp-eic.c
new file mode 100644
index ..ec01877fc75f
--- /dev/null
+++ b/drivers/irqchip/irq-mchp-eic.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Microchip External Interrupt Controller driver
+ *
+ * Copyright (C) 2021 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudiu Beznea 
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MCHP_EIC_GFCS  (0x0)
+#define MCHP_EIC_SCFG(x)   (0x4 + (x) * 0x4)
+#define MCHP_EIC_SCFG_FRZ  BIT(31)
+#define MCHP_EIC_SCFG_EN   BIT(16)
+#define MCHP_EIC_SCFG_LVL  BIT(9)
+#define MCHP_EIC_SCFG_POL  BIT(8)
+#define MCHP_EIC_SCFG_GFEN BIT(4)
+#define MCHP_EIC_SCFG_GFSELGENMASK(1, 0)
+
+#define MCHP_EIC_NIRQ  (2)
+#define MCHP_EIC_DEFAULT_WAIT_US   (100)
+
+/**
+ * struct mchp_eic - EIC private data structure
+ * @base: base address
+ * @dev: eic device
+ * @clk: peripheral clock
+ * @chip: irq chip
+ * @domain: irq domain
+ * @irqs: irqs b/w eic and gic
+ * @scfg: backup for scfg registers (necessary for backup and self-refresh 
mode)
+ * @wakeup_source: wakeup source mask
+ */
+struct mchp_eic {
+   void __iomem *base;
+   struct device *dev;
+   struct clk *clk;
+   struct irq_chip *chip;
+   struct irq_domain *domain;
+   u32 irqs[MCHP_EIC_NIRQ];
+   u32 scfg[MCHP_EIC_NIRQ];
+   u32 wakeup_source;
+};
+
+static void mchp_eic_wait_rdy(struct mchp_eic *eic, unsigned int hwirq,
+ int delay_us)
+{
+   unsigned int tmp = readl(eic->base + MCHP_EIC_SCFG(hwirq));
+
+   while (delay_us >= 0 && tmp & BIT(hwirq)) {
+   udelay(1);
+   delay_us -= 1;
+   tmp = readl(eic->base + MCHP_EIC_SCFG(hwirq));
+   }
+
+   if (delay_us < 0)
+   dev_err(eic->dev, "Failed to configure IRQ=%u!\n", hwirq);
+}
+
+static void mchp_eic_irq_mask(struct irq_data *d)
+{
+   struct mchp_eic *eic = irq_data_get_irq_chip_data(d);
+   unsigned int tmp;
+
+   tmp = readl(eic->base + MCHP_EIC_SCFG(d->hwirq));
+   tmp &= ~MCHP_EIC_SCFG_EN;
+   writel(tmp, eic->base + MCHP_EIC_SCFG(d->hwirq));
+}
+
+static void mchp_eic_irq_unmask(struct irq_data *d)
+{
+   struct mchp_eic *eic = irq_data_get_irq_chip_data(d);
+   unsigned int tmp;
+
+   tmp = readl(eic->base + MCHP_EIC_SCFG(d->hwirq));
+   tmp |= MCHP_EIC_SCFG_EN;
+   writel(tmp, eic->base + MCHP_EIC_SCFG(d->hwirq));
+   mchp_eic_wait_rdy(eic, d->hwirq, MCHP_EIC_DEFAULT_WAIT_US);
+}
+
+static int mchp_eic_irq_set_type(struct irq_data *d, unsigned int type)
+{
+   struct mchp_eic *eic = irq_data_get_irq_chip_data(d);
+   unsigned int tmp;
+
+   tmp = readl(eic->base + MCHP_EIC_SCFG(d->hwirq));
+   tmp &= ~(MCHP_EIC

[PATCH 1/2] dt-bindings: mchp-eic: add bindings

2021-03-02 Thread Claudiu Beznea
Add DT bindings for Microchip External Interrupt Controller.

Signed-off-by: Claudiu Beznea 
---
 .../interrupt-controller/mchp,eic.yaml| 74 +++
 1 file changed, 74 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/interrupt-controller/mchp,eic.yaml

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/mchp,eic.yaml 
b/Documentation/devicetree/bindings/interrupt-controller/mchp,eic.yaml
new file mode 100644
index ..5a927817aa7d
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/mchp,eic.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/mchp,eic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip External Interrupt Controller
+
+maintainers:
+  - Claudiu Beznea 
+
+description:
+  This interrupt controller is found in Microchip SoCs (SAMA7G5) and provides
+  support for handling up to 2 external interrupt lines.
+
+properties:
+  compatible:
+enum:
+  - microchip,sama7g5-eic
+
+  reg:
+maxItems: 1
+
+  interrupt-controller: true
+
+  '#interrupt-cells':
+const: 3
+description:
+  The first cell is the input IRQ number (between 0 and 1), the second cell
+  is the trigger type as defined in interrupt.txt present in this directory
+  and the third cell is the glitch filter (1, 2, 4, 8) in clock cycles
+
+  'interrupts':
+description: |
+  Contains the GIC SPI IRQs mapped to the external interrupt lines. They
+  should be specified sequentially from output 0 to output 1.
+minItems: 2
+maxItems: 2
+
+  clocks:
+maxItems: 1
+
+  clock-names:
+const: pclk
+
+required:
+  - compatible
+  - reg
+  - interrupt-controller
+  - '#interrupt-cells'
+  - 'interrupts'
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+eic: eic@e1628000 {
+  compatible = "microchip,sama7g5-eic";
+  reg = <0xe1628000 0x100>;
+  interrupt-parent = <>;
+  interrupt-controller;
+  #interrupt-cells = <3>;
+  interrupts = ,
+   ;
+  clocks = < PMC_TYPE_PERIPHERAL 37>;
+  clock-names = "pclk";
+};
+
+...
-- 
2.25.1



[tip: timers/core] clocksource/drivers/timer-microchip-pit64b: Add clocksource suspend/resume

2021-02-10 Thread tip-bot2 for Claudiu Beznea
The following commit has been merged into the timers/core branch of tip:

Commit-ID: e85c1d21b16b278f50d191155bc674633270e9c6
Gitweb:
https://git.kernel.org/tip/e85c1d21b16b278f50d191155bc674633270e9c6
Author:Claudiu Beznea 
AuthorDate:Tue, 19 Jan 2021 14:59:25 +02:00
Committer: Daniel Lezcano 
CommitterDate: Wed, 03 Feb 2021 09:36:50 +01:00

clocksource/drivers/timer-microchip-pit64b: Add clocksource suspend/resume

Add suspend/resume support for clocksource timer.

Signed-off-by: Claudiu Beznea 
Signed-off-by: Daniel Lezcano 
Link: 
https://lore.kernel.org/r/1611061165-30180-1-git-send-email-claudiu.bez...@microchip.com
---
 drivers/clocksource/timer-microchip-pit64b.c | 86 +++
 1 file changed, 71 insertions(+), 15 deletions(-)

diff --git a/drivers/clocksource/timer-microchip-pit64b.c 
b/drivers/clocksource/timer-microchip-pit64b.c
index 59e11ca..ab623b2 100644
--- a/drivers/clocksource/timer-microchip-pit64b.c
+++ b/drivers/clocksource/timer-microchip-pit64b.c
@@ -71,10 +71,24 @@ struct mchp_pit64b_clkevt {
struct clock_event_device   clkevt;
 };
 
-#define to_mchp_pit64b_timer(x) \
+#define clkevt_to_mchp_pit64b_timer(x) \
((struct mchp_pit64b_timer *)container_of(x,\
struct mchp_pit64b_clkevt, clkevt))
 
+/**
+ * mchp_pit64b_clksrc - PIT64B clocksource data structure
+ * @timer: PIT64B timer
+ * @clksrc: clocksource
+ */
+struct mchp_pit64b_clksrc {
+   struct mchp_pit64b_timertimer;
+   struct clocksource  clksrc;
+};
+
+#define clksrc_to_mchp_pit64b_timer(x) \
+   ((struct mchp_pit64b_timer *)container_of(x,\
+   struct mchp_pit64b_clksrc, clksrc))
+
 /* Base address for clocksource timer. */
 static void __iomem *mchp_pit64b_cs_base;
 /* Default cycles for clockevent timer. */
@@ -116,6 +130,36 @@ static inline void mchp_pit64b_reset(struct 
mchp_pit64b_timer *timer,
writel_relaxed(MCHP_PIT64B_CR_START, timer->base + MCHP_PIT64B_CR);
 }
 
+static void mchp_pit64b_suspend(struct mchp_pit64b_timer *timer)
+{
+   writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR);
+   if (timer->mode & MCHP_PIT64B_MR_SGCLK)
+   clk_disable_unprepare(timer->gclk);
+   clk_disable_unprepare(timer->pclk);
+}
+
+static void mchp_pit64b_resume(struct mchp_pit64b_timer *timer)
+{
+   clk_prepare_enable(timer->pclk);
+   if (timer->mode & MCHP_PIT64B_MR_SGCLK)
+   clk_prepare_enable(timer->gclk);
+}
+
+static void mchp_pit64b_clksrc_suspend(struct clocksource *cs)
+{
+   struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs);
+
+   mchp_pit64b_suspend(timer);
+}
+
+static void mchp_pit64b_clksrc_resume(struct clocksource *cs)
+{
+   struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs);
+
+   mchp_pit64b_resume(timer);
+   mchp_pit64b_reset(timer, ULLONG_MAX, MCHP_PIT64B_MR_CONT, 0);
+}
+
 static u64 mchp_pit64b_clksrc_read(struct clocksource *cs)
 {
return mchp_pit64b_cnt_read(mchp_pit64b_cs_base);
@@ -128,7 +172,7 @@ static u64 mchp_pit64b_sched_read_clk(void)
 
 static int mchp_pit64b_clkevt_shutdown(struct clock_event_device *cedev)
 {
-   struct mchp_pit64b_timer *timer = to_mchp_pit64b_timer(cedev);
+   struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
 
writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR);
 
@@ -137,7 +181,7 @@ static int mchp_pit64b_clkevt_shutdown(struct 
clock_event_device *cedev)
 
 static int mchp_pit64b_clkevt_set_periodic(struct clock_event_device *cedev)
 {
-   struct mchp_pit64b_timer *timer = to_mchp_pit64b_timer(cedev);
+   struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
 
mchp_pit64b_reset(timer, mchp_pit64b_ce_cycles, MCHP_PIT64B_MR_CONT,
  MCHP_PIT64B_IER_PERIOD);
@@ -148,7 +192,7 @@ static int mchp_pit64b_clkevt_set_periodic(struct 
clock_event_device *cedev)
 static int mchp_pit64b_clkevt_set_next_event(unsigned long evt,
 struct clock_event_device *cedev)
 {
-   struct mchp_pit64b_timer *timer = to_mchp_pit64b_timer(cedev);
+   struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
 
mchp_pit64b_reset(timer, evt, MCHP_PIT64B_MR_ONE_SHOT,
  MCHP_PIT64B_IER_PERIOD);
@@ -158,21 +202,16 @@ static int mchp_pit64b_clkevt_set_next_event(unsigned 
long evt,
 
 static void mchp_pit64b_clkevt_suspend(struct clock_event_device *cedev)
 {
-   struct mchp_pit64b_timer *timer = to_mchp_pit64b_timer(cedev);
+   struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev);
 
-   writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR);
-   if (timer->mode & MCHP_PIT64B_MR_SGCLK)
-   clk_disable_unprepare(timer->gclk);
-   clk_disable_unprepare

[PATCH] power: reset: at91-reset: free resources on exit path

2021-02-09 Thread Claudiu Beznea
Free resources on exit path (failure path of probe and remove).

Reported-by: kernel test robot 
Reported-by: Dan Carpenter 
Signed-off-by: Claudiu Beznea 
---
 drivers/power/reset/at91-reset.c | 25 -
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
index 3ff9d93a5226..2ff7833153b6 100644
--- a/drivers/power/reset/at91-reset.c
+++ b/drivers/power/reset/at91-reset.c
@@ -206,7 +206,8 @@ static int __init at91_reset_probe(struct platform_device 
*pdev)
if (!reset->ramc_base[idx]) {
dev_err(>dev, "Could not map ram 
controller address\n");
of_node_put(np);
-   return -ENODEV;
+   ret = -ENODEV;
+   goto unmap;
}
idx++;
}
@@ -218,13 +219,15 @@ static int __init at91_reset_probe(struct platform_device 
*pdev)
reset->args = (u32)match->data;
 
reset->sclk = devm_clk_get(>dev, NULL);
-   if (IS_ERR(reset->sclk))
-   return PTR_ERR(reset->sclk);
+   if (IS_ERR(reset->sclk)) {
+   ret = PTR_ERR(reset->sclk);
+   goto unmap;
+   }
 
ret = clk_prepare_enable(reset->sclk);
if (ret) {
dev_err(>dev, "Could not enable slow clock\n");
-   return ret;
+   goto unmap;
}
 
platform_set_drvdata(pdev, reset);
@@ -239,21 +242,33 @@ static int __init at91_reset_probe(struct platform_device 
*pdev)
ret = register_restart_handler(>nb);
if (ret) {
clk_disable_unprepare(reset->sclk);
-   return ret;
+   goto unmap;
}
 
at91_reset_status(pdev, reset->rstc_base);
 
return 0;
+
+unmap:
+   iounmap(reset->rstc_base);
+   for (idx = 0; idx < ARRAY_SIZE(reset->ramc_base); idx++)
+   iounmap(reset->ramc_base[idx]);
+
+   return ret;
 }
 
 static int __exit at91_reset_remove(struct platform_device *pdev)
 {
struct at91_reset *reset = platform_get_drvdata(pdev);
+   int idx;
 
unregister_restart_handler(>nb);
clk_disable_unprepare(reset->sclk);
 
+   iounmap(reset->rstc_base);
+   for (idx = 0; idx < ARRAY_SIZE(reset->ramc_base); idx++)
+   iounmap(reset->ramc_base[idx]);
+
return 0;
 }
 
-- 
2.25.1



[PATCH] ARM: configs: at91: enable drivers for sam9x60

2021-02-05 Thread Claudiu Beznea
Enable drivers for sam9x60/sam9x60-ek:
- shutdown controller
- CAN
- AT24 EEPROM (present on SAM9X60-EK)
- MCP23S08 (present on SAM9X60-EK)
- AES, TDES, SHA

And use "make savedefconfig".

Signed-off-by: Claudiu Beznea 
---
 arch/arm/configs/at91_dt_defconfig | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/arm/configs/at91_dt_defconfig 
b/arch/arm/configs/at91_dt_defconfig
index 5f3415c743ec..e274f8c492d2 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -17,8 +17,6 @@ CONFIG_SOC_SAM9X60=y
 # CONFIG_ATMEL_CLOCKSOURCE_PIT is not set
 CONFIG_AEABI=y
 CONFIG_UACCESS_WITH_MEMCPY=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x2110,25165824 root=/dev/ram0 
rw"
@@ -38,6 +36,8 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_DIAG is not set
 CONFIG_IPV6_SIT_6RD=y
+CONFIG_CAN=y
+CONFIG_CAN_AT91=y
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_DEVTMPFS=y
@@ -58,6 +58,7 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=4
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_ATMEL_SSC=y
+CONFIG_EEPROM_AT24=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
@@ -91,7 +92,6 @@ CONFIG_RT2800USB_UNKNOWN=y
 CONFIG_RTL8187=m
 CONFIG_RTL8192CU=m
 # CONFIG_RTLWIFI_DEBUG is not set
-CONFIG_INPUT_POLLDEV=y
 CONFIG_INPUT_JOYDEV=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -111,8 +111,8 @@ CONFIG_I2C_GPIO=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_ATMEL_QUADSPI=y
+CONFIG_PINCTRL_MCP23S08=m
 CONFIG_POWER_RESET=y
-# CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -208,7 +208,9 @@ CONFIG_NLS_UTF8=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
-# CONFIG_CRYPTO_HW is not set
+CONFIG_CRYPTO_DEV_ATMEL_AES=y
+CONFIG_CRYPTO_DEV_ATMEL_TDES=y
+CONFIG_CRYPTO_DEV_ATMEL_SHA=y
 CONFIG_CRC_CCITT=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
-- 
2.7.4



[PATCH v2 0/3] pinctrl: at91-pio4: add support for slew-rate

2021-01-27 Thread Claudiu Beznea
Hi,

This series adds support for slew rate on SAMA7G5. Along with this
patch 3/3 fixes some checkpatch.pl warnings.

Thank you,
Claudiu Beznea

Changes in v2:
- s/sr/slew_rate_support/g in patch 2/3
- collected tags

Claudiu Beznea (3):
  dt-bindings: pinctrl: at91-pio4: add slew-rate
  pinctrl: at91-pio4: add support for slew-rate
  pinctrl: at91-pio4: fix "Prefer 'unsigned int' to bare use of
'unsigned'"

 .../bindings/pinctrl/atmel,at91-pio4-pinctrl.txt   |   8 +-
 drivers/pinctrl/pinctrl-at91-pio4.c| 137 +
 2 files changed, 89 insertions(+), 56 deletions(-)

-- 
2.7.4



  1   2   3   4   5   6   7   8   9   >