2021-03-31 11:00:59

by Claudiu Beznea

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

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


2021-03-31 11:01:05

by Claudiu Beznea

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

Move pm_bu to soc_pm data structure.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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(&canary);
- pm_bu->resume = __pa_symbol(cpu_resume);
+ soc_pm.bu->suspended = 0;
+ soc_pm.bu->canary = __pa_symbol(&canary);
+ soc_pm.bu->resume = __pa_symbol(cpu_resume);

return 0;

--
2.25.1

2021-03-31 11:01:09

by Claudiu Beznea

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

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 <[email protected]>
---
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

2021-03-31 11:01:22

by Claudiu Beznea

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

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 <[email protected]>
---
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(&pdev->dev, NULL);
@@ -697,64 +700,92 @@ static int __init at91_pm_backup_init(void)

securam_fail:
put_device(&pdev->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_IOMAP(SFRBU) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU)) {
+ np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
+ if (!np) {
+ pr_warn("%s: failed to find sfrbu!\n", __func__);
+
+ /*
+ * Use ULP0 if it doesn't need SHDWC or if SHDWC
+ * was already located.
+ */
+ if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)) ||
+ soc_pm.data.shdwc)
+ mode = AT91_PM_ULP0;
+ else
+ mode = AT91_PM_STANDBY;
+
+ if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU))
+ soc_pm.data.standby_mode = mode;
+ if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))
+ soc_pm.data.suspend_mode = mode;
+ } else {
+ soc_pm.data.sfrbu = of_iomap(np, 0);
+ of_node_put(np);
+ }
+ }

- ret = at91_pm_backup_init();
- if (ret) {
- if (!at91_is_pm_mode_active(AT91_PM_ULP1))
- goto unmap;
- else
- goto backup_default;
+ /* Unmap all unnecessary. */
+ if (soc_pm.data.shdwc &&
+ !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))) {
+ iounmap(soc_pm.data.shdwc);
+ soc_pm.data.shdwc = NULL;
}

- return;
+ if (soc_pm.data.sfrbu &&
+ !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))) {
+ iounmap(soc_pm.data.sfrbu);
+ soc_pm.data.sfrbu = NULL;
+ }

-unmap:
- iounmap(soc_pm.data.shdwc);
- soc_pm.data.shdwc = NULL;
-ulp1_default:
- at91_pm_use_default_mode(AT91_PM_ULP1);
-backup_default:
- at91_pm_use_default_mode(AT91_PM_BACKUP);
+ return;
}

struct pmc_info {
@@ -917,12 +948,15 @@ void __init sam9x60_pm_init(void)
static const int modes[] __initconst = {
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
};
+ static const int iomaps[] __initconst = {
+ [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
+ };

if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
return;

at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- at91_pm_modes_init();
+ at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_dt_ramc();
at91_pm_init(NULL);

@@ -967,12 +1001,17 @@ void __init sama5d2_pm_init(void)
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
AT91_PM_BACKUP,
};
+ static const u32 iomaps[] __initconst = {
+ [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
+ [AT91_PM_BACKUP] = AT91_PM_IOMAP(SHDWC) |
+ AT91_PM_IOMAP(SFRBU),
+ };

if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return;

at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- at91_pm_modes_init();
+ at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_dt_ramc();
at91_pm_init(NULL);

--
2.25.1

2021-03-31 11:01:28

by Claudiu Beznea

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

There is no need to initialize pdev.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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

2021-03-31 11:01:40

by Claudiu Beznea

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

Use r7 instead of tmp1 in macros. This prepares the filed for
next commits.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 .req r6

/*
* 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

2021-03-31 11:02:00

by Claudiu Beznea

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

Add registers and bits definitions for SAMA7G5's UDDRC and DDR3PHY.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 000000000000..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 <[email protected]>
+ */
+
+#ifndef __SAMA7_DDR_H__
+#define __SAMA7_DDR_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+/* DDR3PHY */
+#define DDR3PHY_PIR (0x04) /* DDR3PHY PHY Initialization Register */
+#define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */
+#define DDR3PHY_PIR_ITMSRST (1 << 4) /* Interface Timing Module Soft Reset */
+#define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */
+#define DDR3PHY_PIR_DLLSRST (1 << 1) /* DLL Soft Rest */
+#define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */
+
+#define DDR3PHY_PGCR (0x08) /* DDR3PHY PHY General Configuration Register */
+#define DDR3PHY_PGCR_CKDV1 (1 << 13) /* CK# Disable Value */
+#define DDR3PHY_PGCR_CKDV0 (1 << 12) /* CK Disable Value */
+
+#define DDR3PHY_PGSR (0x0C) /* DDR3PHY PHY General Status Register */
+#define DDR3PHY_PGSR_IDONE (1 << 0) /* Initialization Done */
+
+#define DDR3PHY_ACIOCR (0x24) /* DDR3PHY AC I/O Configuration Register */
+#define DDR3PHY_ACIOCR_CSPDD_CS0 (1 << 18) /* CS#[0] Power Down Driver */
+#define DDR3PHY_ACIOCR_CKPDD_CK0 (1 << 8) /* CK[0] Power Down Driver */
+#define DDR3PHY_ACIORC_ACPDD (1 << 3) /* AC Power Down Driver */
+
+#define DDR3PHY_DXCCR (0x28) /* DDR3PHY DATX8 Common Configuration Register */
+#define DDR3PHY_DXCCR_DXPDR (1 << 3) /* Data Power Down Receiver */
+
+#define DDR3PHY_DSGCR (0x2C) /* DDR3PHY DDR System General Configuration Register */
+#define DDR3PHY_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 */
+#define UDDRC_STAT_SELFREF_TYPE_DIS (0x0 << 4) /* SDRAM is not in Self-refresh */
+#define UDDRC_STAT_SELFREF_TYPE_PHY (0x1 << 4) /* SDRAM is in Self-refresh, which was caused by PHY Master Request */
+#define UDDRC_STAT_SELFREF_TYPE_SW (0x2 << 4) /* SDRAM is in Self-refresh, which was not caused solely under Automatic Self-refresh control */
+#define UDDRC_STAT_SELFREF_TYPE_AUTO (0x3 << 4) /* SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
+#define UDDRC_STAT_SELFREF_TYPE_MSK (0x3 << 4) /* Self-refresh type mask */
+#define UDDRC_STAT_OPMODE_INIT (0x0 << 0) /* Init */
+#define UDDRC_STAT_OPMODE_NORMAL (0x1 << 0) /* Normal */
+#define UDDRC_STAT_OPMODE_PWRDOWN (0x2 << 0) /* Power-down */
+#define UDDRC_STAT_OPMODE_SELF_REFRESH (0x3 << 0) /* Self-refresh */
+#define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */
+
+#define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */
+#define UDDRC_PWRCTRL_SELFREF_SW (1 << 5) /* Software self-refresh */
+
+#define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */
+#define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY initialization complete enable signal */
+
+#define UDDRC_SWCTRL (0x320) /* UDDRC Software Register Programming Control Enable */
+#define UDDRC_SWCTRL_SW_DONE (1 << 0) /* Enable quasi-dynamic register programming outside reset */
+
+#define UDDRC_SWSTAT (0x324) /* UDDRC Software Register Programming Control Status */
+#define UDDRC_SWSTAT_SW_DONE_ACK (1 << 0) /* Register programming done */
+
+#define UDDRC_PSTAT (0x3FC) /* UDDRC Port Status Register */
+#define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */
+
+#define UDDRC_PCTRL_0 (0x490) /* UDDRC Port 0 Control Register */
+#define UDDRC_PCTRL_1 (0x540) /* UDDRC Port 1 Control Register */
+#define UDDRC_PCTRL_2 (0x5F0) /* UDDRC Port 2 Control Register */
+#define UDDRC_PCTRL_3 (0x6A0) /* UDDRC Port 3 Control Register */
+#define UDDRC_PCTRL_4 (0x750) /* UDDRC Port 4 Control Register */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_DDR_H__ */
--
2.25.1

2021-03-31 11:02:01

by Claudiu Beznea

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

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 <[email protected]>
---
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 .req r6

/*
* 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

2021-03-31 11:02:02

by Claudiu Beznea

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

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 <[email protected]>
---
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

2021-03-31 11:02:10

by Claudiu Beznea

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

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 <[email protected]>
---
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 .req r6

.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 clock source to slow clock. */
- ldr pmc, .pmc_base
- ldr tmp2, .mckr_offset
- ldr tmp1, [pmc, tmp2]
- bic tmp1, tmp1, #AT91_PMC_CSS
- str tmp1, [pmc, tmp2]
+sr_ena_no_2nd_ddrc:
+ b sr_ena_exit

- wait_mckrdy
+ /*
+ * SDRAMC Memory controller
+ */
+sr_ena_sdramc_sf:
+ /* Active SDRAMC self-refresh mode */
+ ldr r3, [r2, #AT91_SDRAMC_LPR]
+ str r3, .saved_sam9_lpr
+ bic r3, r3, #AT91_SDRAMC_LPCB
+ orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
+ str r3, [r2, #AT91_SDRAMC_LPR]

- /*BUMEN*/
- ldr r0, .sfrbu
- mov tmp1, #0x1
- str tmp1, [r0, #0x10]
+ ldr r3, .saved_sam9_lpr
+ str r3, [r2, #AT91_SDRAMC_LPR]

- /* Shutdown */
- ldr r0, .shdwc
- mov tmp1, #0xA5000000
- add tmp1, tmp1, #0x1
- str tmp1, [r0, #0]
-ENDPROC(at91_backup_mode)
+sr_ena_exit:
+.endm
+
+/**
+ * Disable self-refresh
+ *
+ * register usage:
+ * @r1: memory type
+ * @r2: base address of the sram controller
+ * @r3: temporary
+ */
+.macro at91_sramc_self_refresh_dis
+ ldr r1, .memtype
+ ldr r2, .sramc_base
+
+ cmp r1, #AT91_MEMCTRL_MC
+ bne sr_dis_ddrc_exit_sf
+
+ /*
+ * at91rm9200 Memory controller
+ */
+
+ /*
+ * For exiting the self-refresh mode, do nothing,
+ * automatically exit the self-refresh mode.
+ */
+ b sr_dis_exit
+
+sr_dis_ddrc_exit_sf:
+ cmp r1, #AT91_MEMCTRL_DDRSDR
+ bne sdramc_exit_sf
+
+ /* DDR Memory controller */
+
+ /* Restore MDR in case of LPDDR1 */
+ ldr r3, .saved_sam9_mdr
+ str r3, [r2, #AT91_DDRSDRC_MDR]
+ /* Restore LPR on AT91 with DDRAM */
+ ldr r3, .saved_sam9_lpr
+ str r3, [r2, #AT91_DDRSDRC_LPR]
+
+ /* If using the 2nd ddr controller */
+ ldr r2, .sramc1_base
+ cmp r2, #0
+ ldrne r3, .saved_sam9_mdr1
+ strne r3, [r2, #AT91_DDRSDRC_MDR]
+ ldrne r3, .saved_sam9_lpr1
+ strne r3, [r2, #AT91_DDRSDRC_LPR]
+
+ b sr_dis_exit
+
+sdramc_exit_sf:
+ /* SDRAMC Memory controller */
+ ldr r3, .saved_sam9_lpr
+ str r3, [r2, #AT91_SDRAMC_LPR]
+
+sr_dis_exit:
+.endm

.macro at91_pm_ulp0_mode
ldr pmc, .pmc_base
@@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode)
2:
.endm

-ENTRY(at91_ulp_mode)
+.macro at91_ulp_mode
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode
@@ -552,133 +601,97 @@ ulp_exit:

wait_mckrdy

- mov pc, lr
-ENDPROC(at91_ulp_mode)
-
-/*
- * void at91_sramc_self_refresh(unsigned int is_active)
- *
- * @input param:
- * @r0: 1 - active self-refresh mode
- * 0 - exit self-refresh mode
- * register usage:
- * @r1: memory type
- * @r2: base address of the sram controller
- */
-
-ENTRY(at91_sramc_self_refresh)
- ldr r1, .memtype
- ldr r2, .sramc_base
-
- cmp r1, #AT91_MEMCTRL_MC
- bne ddrc_sf
-
- /*
- * at91rm9200 Memory controller
- */
-
- /*
- * For exiting the self-refresh mode, do nothing,
- * automatically exit the self-refresh mode.
- */
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq exit_sramc_sf
-
- /* Active SDRAM self-refresh mode */
- mov r3, #1
- str r3, [r2, #AT91_MC_SDRAMC_SRR]
- b exit_sramc_sf
-
-ddrc_sf:
- cmp r1, #AT91_MEMCTRL_DDRSDR
- bne sdramc_sf
+.endm

- /*
- * DDR Memory controller
- */
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq ddrc_exit_sf
+.macro at91_backup_mode
+ /* Switch the master clock source to slow clock. */
+ ldr pmc, .pmc_base
+ ldr tmp2, .mckr_offset
+ ldr tmp1, [pmc, tmp2]
+ bic tmp1, tmp1, #AT91_PMC_CSS
+ str tmp1, [pmc, tmp2]

- /* 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]
+ wait_mckrdy

- /* 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]
+ /*BUMEN*/
+ ldr r0, .sfrbu
+ mov tmp1, #0x1
+ str tmp1, [r0, #0x10]

- /* If using the 2nd ddr controller */
- ldr r2, .sramc1_base
- cmp r2, #0
- beq no_2nd_ddrc
+ /* Shutdown */
+ ldr r0, .shdwc
+ mov tmp1, #0xA5000000
+ add tmp1, tmp1, #0x1
+ str tmp1, [r0, #0]
+.endm

- 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]
+/*
+ * void at91_suspend_sram_fn(struct at91_pm_data*)
+ * @input param:
+ * @r0: base address of struct at91_pm_data
+ */
+/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
+ .align 3
+ENTRY(at91_pm_suspend_in_sram)
+ /* Save registers on stack */
+ stmfd sp!, {r4 - r12, lr}

- /* 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]
+ /* Drain write buffer */
+ mov tmp1, #0
+ mcr p15, 0, tmp1, c7, c10, 4

-no_2nd_ddrc:
- b exit_sramc_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]

-ddrc_exit_sf:
- /* Restore MDR in case of LPDDR1 */
- ldr r3, .saved_sam9_mdr
- str r3, [r2, #AT91_DDRSDRC_MDR]
- /* Restore LPR on AT91 with DDRAM */
- ldr r3, .saved_sam9_lpr
- str r3, [r2, #AT91_DDRSDRC_LPR]
+ /* Active the self-refresh mode */
+ at91_sramc_self_refresh_ena

- /* If using the 2nd ddr controller */
- ldr r2, .sramc1_base
- cmp r2, #0
- ldrne r3, .saved_sam9_mdr1
- strne r3, [r2, #AT91_DDRSDRC_MDR]
- ldrne r3, .saved_sam9_lpr1
- strne r3, [r2, #AT91_DDRSDRC_LPR]
+ ldr r0, .pm_mode
+ cmp r0, #AT91_PM_STANDBY
+ beq standby
+ cmp r0, #AT91_PM_BACKUP
+ beq backup_mode

- b exit_sramc_sf
+ at91_ulp_mode
+ b exit_suspend

- /*
- * SDRAMC Memory controller
- */
-sdramc_sf:
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq sdramc_exit_sf
+standby:
+ /* Wait for interrupt */
+ ldr pmc, .pmc_base
+ at91_cpu_idle
+ b exit_suspend

- /* Active SDRAMC self-refresh mode */
- ldr r3, [r2, #AT91_SDRAMC_LPR]
- str r3, .saved_sam9_lpr
- bic r3, r3, #AT91_SDRAMC_LPCB
- orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_SDRAMC_LPR]
+backup_mode:
+ at91_backup_mode

-sdramc_exit_sf:
- ldr r3, .saved_sam9_lpr
- str r3, [r2, #AT91_SDRAMC_LPR]
+exit_suspend:
+ /* Exit the self-refresh mode */
+ at91_sramc_self_refresh_dis

-exit_sramc_sf:
- mov pc, lr
-ENDPROC(at91_sramc_self_refresh)
+ /* Restore registers, and return */
+ ldmfd sp!, {r4 - r12, pc}
+ENDPROC(at91_pm_suspend_in_sram)

.pmc_base:
.word 0
--
2.25.1

2021-03-31 11:02:11

by Claudiu Beznea

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

Add support for MCK1..4 save restore for ULP modes.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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

2021-03-31 11:02:18

by Claudiu Beznea

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

Add self-refresh support for SAMA7G5.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 <linux/mfd/syscon/atmel-mc.h>
#include <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.h>
+#include <soc/at91/sama7-ddr.h>

#define AT91_MEMCTRL_MC 0
#define AT91_MEMCTRL_SDRAMC 1
@@ -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 .req r6

.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 tmp1, [r3, #DDR3PHY_ACIOCR]
+
+ /* Power up ODT. */
+ ldr tmp1, [r3, #DDR3PHY_DSGCR]
+ bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+ str tmp1, [r3, #DDR3PHY_DSGCR]
+
+ /* Take DDR PHY's DLL out of bypass mode. */
+ ldr tmp1, [r3, #DDR3PHY_PIR]
+ bic tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
+ str tmp1, [r3, #DDR3PHY_PIR]
+
+ /* Enable quasi-dynamic programming. */
+ mov tmp1, #0
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+ /* De-assert SDRAM initialization. */
+ ldr tmp1, [r2, #UDDRC_DFIMISC]
+ bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
+ str tmp1, [r2, #UDDRC_DFIMISC]
+
+ /* Quasi-dynamic programming done. */
+ mov tmp1, #UDDRC_SWCTRL_SW_DONE
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+sr_dis_1:
+ ldr tmp1, [r2, #UDDRC_SWSTAT]
+ tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
+ beq sr_dis_1
+
+ /* DLL soft-reset + DLL lock wait + ITM reset */
+ mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
+ DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
+ str tmp1, [r3, #DDR3PHY_PIR]
+
+sr_dis_4:
+ /* Wait for it. */
+ ldr tmp1, [r3, #DDR3PHY_PGSR]
+ tst tmp1, #DDR3PHY_PGSR_IDONE
+ beq sr_dis_4
+
+ /* Enable quasi-dynamic programming. */
+ mov tmp1, #0
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+ /* Assert PHY init complete enable signal. */
+ ldr tmp1, [r2, #UDDRC_DFIMISC]
+ orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
+ str tmp1, [r2, #UDDRC_DFIMISC]
+
+ /* Programming is done. Set sw_done. */
+ mov tmp1, #UDDRC_SWCTRL_SW_DONE
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+sr_dis_5:
+ /* Wait for it. */
+ ldr tmp1, [r2, #UDDRC_SWSTAT]
+ tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
+ beq sr_dis_5
+
+ /* Trigger self-refresh exit. */
+ ldr tmp1, [r2, #UDDRC_PWRCTL]
+ bic tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
+ str tmp1, [r2, #UDDRC_PWRCTL]
+
+sr_dis_6:
+ /* Wait for self-refresh exit done. */
+ ldr tmp1, [r2, #UDDRC_STAT]
+ bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
+ cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL
+ bne sr_dis_6
+
+ /* Enable all AXI ports. */
+ ldr tmp1, [r2, #UDDRC_PCTRL_0]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_0]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_1]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_1]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_2]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_2]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_3]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_3]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_4]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_4]
+
+ dsb
+.endm
+#else
/**
* Enable self-refresh
*
@@ -228,6 +422,7 @@ sdramc_exit_sf:

sr_dis_exit:
.endm
+#endif

.macro at91_pm_ulp0_mode
ldr pmc, .pmc_base
@@ -668,6 +863,8 @@ ENTRY(at91_pm_suspend_in_sram)
str tmp1, .sramc_base
ldr tmp1, [r0, #PM_DATA_RAMC1]
str tmp1, .sramc1_base
+ ldr tmp1, [r0, #PM_DATA_RAMC_PHY]
+ str tmp1, .sramc_phy_base
ldr tmp1, [r0, #PM_DATA_MEMCTRL]
str tmp1, .memtype
ldr tmp1, [r0, #PM_DATA_MODE]
@@ -721,6 +918,8 @@ ENDPROC(at91_pm_suspend_in_sram)
.word 0
.sramc1_base:
.word 0
+.sramc_phy_base:
+ .word 0
.shdwc:
.word 0
.sfrbu:
--
2.25.1

2021-03-31 11:02:30

by Claudiu Beznea

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

Add support to disable/enable 2.5V LDO regulator when entering/exiting
any ULP mode.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.h>
#include <soc/at91/sama7-ddr.h>
+#include <soc/at91/sama7-sfrbu.h>

#define AT91_MEMCTRL_MC 0
#define AT91_MEMCTRL_SDRAMC 1
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 .req r6

.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

2021-03-31 11:02:32

by Claudiu Beznea

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

Wait for DDR power mode off before shutting down the core.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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, #0xA5000000
--
2.25.1

2021-03-31 11:02:41

by Claudiu Beznea

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

Add RAM controller and RAM PHY controller DT bindings.

Signed-off-by: Claudiu Beznea <[email protected]>
---
.../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 = <0xffffe800 0x200>;
};

+RAMC PHY Controller required properties:
+- compatible: Should be "microchip,sama7g5-ddr3phy", "syscon"
+- reg: Should contain registers location and length
+
+Example:
+
+ ddr3phy: [email protected] {
+ compatible = "microchip,sama7g5-ddr3phy", "syscon";
+ reg = <0xe3804000 0x1000>;
+ status = "okay";
+};
+
SHDWC Shutdown Controller

required properties:
--
2.25.1

2021-03-31 11:02:57

by Claudiu Beznea

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

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 <[email protected]>
---
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, &of_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

2021-03-31 11:02:56

by Claudiu Beznea

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

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 <[email protected]>
---
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 = &ramc_infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = &ramc_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

2021-03-31 11:02:59

by Claudiu Beznea

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

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 <[email protected]>
---
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, #0x200000
+#endif
+ .endm
+
.text

.arm
@@ -989,6 +995,7 @@ ulp_exit:
ldr r0, .shdwc
mov tmp1, #0xA5000000
add tmp1, tmp1, #0x1
+ at91_backup_set_lpm tmp1
str tmp1, [r0, #0]
.endm

--
2.25.1

2021-03-31 11:02:59

by Claudiu Beznea

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

Add support for SAMA7G5 power management modes: standby, ulp0, ulp1, backup.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 = &ws_info[1] },
+ { .compatible = "microchip,sama7g5-ohci", .data = &ws_info[2] },
+ { .compatible = "usb-ohci", .data = &ws_info[2] },
+ { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
+ { .compatible = "usb-ehci", .data = &ws_info[2] },
+ { .compatible = "microchip,sama7g5-sdhci", .data = &ws_info[3] },
+ { .compatible = "atmel,at91sam9260-rtt", .data = &ws_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

2021-03-31 11:03:00

by Claudiu Beznea

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

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 <[email protected]>
---
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 <linux/io.h>
#include <linux/of_address.h>
#include <linux/of.h>
+#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/parser.h>
#include <linux/suspend.h>
@@ -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", &size);
+ 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(&canary);
soc_pm.bu->resume = __pa_symbol(cpu_resume);
+ if (soc_pm.data.ramc_phy) {
+ of_scan_flat_dt(at91_pm_backup_scan_memcs, &located);
+ 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

2021-03-31 11:03:00

by Claudiu Beznea

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

Add SAMA7G5 SHDWC.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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

2021-03-31 11:03:02

by Claudiu Beznea

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

Add SAMA7G5's PMC to compatible list.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 = &pmc_infos[1] },
{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
+ { .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] },
{ /* sentinel */ },
};

--
2.25.1

2021-03-31 11:03:12

by Claudiu Beznea

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

Document at91_soc_pm structure.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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

2021-03-31 11:04:04

by Claudiu Beznea

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

Add SFRBU registers definitions for SAMA7G5.

Signed-off-by: Claudiu Beznea <[email protected]>
---
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 000000000000..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 <[email protected]>
+ */
+
+#ifndef __SAMA7_SFRBU_H__
+#define __SAMA7_SFRBU_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+#define AT91_SFRBU_PSWBU (0x00) /* SFRBU Power Switch BU Control Register */
+#define AT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* Specific value mandatory to allow writing of other register bits */
+#define AT91_SFRBU_PSWBU_STATE (1 << 2) /* Power switch BU state */
+#define AT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1) /* Power switch BU source selection */
+#define AT91_SFRBU_PSWBU_CTRL (1 << 0) /* Power switch BU control */
+
+#define AT91_SFRBU_25LDOCR (0x0C) /* SFRBU 2.5V LDO Control Register */
+#define AT91_SFRBU_25LDOCR_LDOANAKEY (0x3B6E18 << 8) /* Specific value mandatory to allow writing of other register bits. */
+#define AT91_SFRBU_25LDOCR_STATE (1 << 3) /* LDOANA Switch On/Off Control */
+#define AT91_SFRBU_25LDOCR_LP (1 << 2) /* LDOANA Low-Power Mode Control */
+#define AT91_SFRBU_PD_VALUE_MSK (0x3)
+#define AT91_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 */
+#define AT91_FRBU_DDRPWR_STATE (1 << 0) /* DDR Power Mode State */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_SFRBU_H__ */
+
--
2.25.1

2021-03-31 11:04:57

by Claudiu Beznea

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

From: Eugen Hristev <[email protected]>

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

Signed-off-by: Eugen Hristev <[email protected]>
Signed-off-by: Claudiu Beznea <[email protected]>
---
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 000000000000..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 <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/system_misc.h>
+
+#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

2021-03-31 14:45:40

by Alexandre Belloni

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

On 31/03/2021 13:58:45+0300, Claudiu Beznea wrote:
> Move pm_bu to soc_pm data structure.
>
> Signed-off-by: Claudiu Beznea <[email protected]>
Reviewed-by: Alexandre Belloni <[email protected]>

> ---
> 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(&canary);
> - pm_bu->resume = __pa_symbol(cpu_resume);
> + soc_pm.bu->suspended = 0;
> + soc_pm.bu->canary = __pa_symbol(&canary);
> + soc_pm.bu->resume = __pa_symbol(cpu_resume);
>
> return 0;
>
> --
> 2.25.1
>

--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2021-03-31 15:56:12

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 10/24] ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5

On 31/03/2021 13:58:54+0300, Claudiu Beznea wrote:
> Add SFRBU registers definitions for SAMA7G5.
>
> Signed-off-by: Claudiu Beznea <[email protected]>
> ---
> 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 000000000000..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 <[email protected]>
> + */
> +
> +#ifndef __SAMA7_SFRBU_H__
> +#define __SAMA7_SFRBU_H__
> +
> +#ifdef CONFIG_SOC_SAMA7
> +
> +#define AT91_SFRBU_PSWBU (0x00) /* SFRBU Power Switch BU Control Register */
> +#define AT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* Specific value mandatory to allow writing of other register bits */
> +#define AT91_SFRBU_PSWBU_STATE (1 << 2) /* Power switch BU state */
> +#define AT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1) /* Power switch BU source selection */
> +#define AT91_SFRBU_PSWBU_CTRL (1 << 0) /* Power switch BU control */

Please use BIT

> +
> +#define AT91_SFRBU_25LDOCR (0x0C) /* SFRBU 2.5V LDO Control Register */
> +#define AT91_SFRBU_25LDOCR_LDOANAKEY (0x3B6E18 << 8) /* Specific value mandatory to allow writing of other register bits. */
> +#define AT91_SFRBU_25LDOCR_STATE (1 << 3) /* LDOANA Switch On/Off Control */
> +#define AT91_SFRBU_25LDOCR_LP (1 << 2) /* LDOANA Low-Power Mode Control */
> +#define AT91_SFRBU_PD_VALUE_MSK (0x3)

GENMASK

> +#define AT91_SFRBU_25LDOCR_PD_VALUE(v) ((v) & AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */

this macro is not necessary, you can use FIELD_PREP with the previous
define.


--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2021-03-31 16:04:06

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

On 31/03/2021 13:59:06+0300, Claudiu Beznea wrote:
> From: Eugen Hristev <[email protected]>
>
> Introduce new family of SoCs, sama7, and first SoC, sama7g5.
>
> Signed-off-by: Eugen Hristev <[email protected]>
> Signed-off-by: Claudiu Beznea <[email protected]>
> ---
> 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 000000000000..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 <linux/of.h>
> +#include <linux/of_platform.h>
> +
> +#include <asm/mach/arch.h>
> +#include <asm/system_misc.h>
> +
> +#include "generic.h"
> +
> +static void __init sama7_common_init(void)
> +{
> + of_platform_default_populate(NULL, NULL, NULL);

Is this necessary? This is left as a workaround for the old SoCs using
pinctrl-at91. I guess this will be using pio4 so this has to be removed.

> +}
> +
> +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
>

--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2021-04-01 09:36:31

by Claudiu Beznea

[permalink] [raw]
Subject: Re: [PATCH 10/24] ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5

On 31.03.2021 18:54, Alexandre Belloni wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> On 31/03/2021 13:58:54+0300, Claudiu Beznea wrote:
>> Add SFRBU registers definitions for SAMA7G5.
>>
>> Signed-off-by: Claudiu Beznea <[email protected]>
>> ---
>> 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 000000000000..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 <[email protected]>
>> + */
>> +
>> +#ifndef __SAMA7_SFRBU_H__
>> +#define __SAMA7_SFRBU_H__
>> +
>> +#ifdef CONFIG_SOC_SAMA7
>> +
>> +#define AT91_SFRBU_PSWBU (0x00) /* SFRBU Power Switch BU Control Register */
>> +#define AT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* Specific value mandatory to allow writing of other register bits */
>> +#define AT91_SFRBU_PSWBU_STATE (1 << 2) /* Power switch BU state */
>> +#define AT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1) /* Power switch BU source selection */
>> +#define AT91_SFRBU_PSWBU_CTRL (1 << 0) /* Power switch BU control */
>
> Please use BIT
>
>> +
>> +#define AT91_SFRBU_25LDOCR (0x0C) /* SFRBU 2.5V LDO Control Register */
>> +#define AT91_SFRBU_25LDOCR_LDOANAKEY (0x3B6E18 << 8) /* Specific value mandatory to allow writing of other register bits. */
>> +#define AT91_SFRBU_25LDOCR_STATE (1 << 3) /* LDOANA Switch On/Off Control */
>> +#define AT91_SFRBU_25LDOCR_LP (1 << 2) /* LDOANA Low-Power Mode Control */
>> +#define AT91_SFRBU_PD_VALUE_MSK (0x3)
>
> GENMASK
>
>> +#define AT91_SFRBU_25LDOCR_PD_VALUE(v) ((v) & AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */
>
> this macro is not necessary, you can use FIELD_PREP with the previous
> define.
>

This file (as well as include/soc/at91/sama7-ddr.h) is used in
arch/arm/mach-at91/pm_suspend.S who's content is executed from CPU internal
SRAM. I chose to have these defines w/o BIT(), GENMASK() and friends to not
depend on the bitops.h who's size might be changed at any time.

>
> --
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>

2021-04-01 09:42:50

by Claudiu Beznea

[permalink] [raw]
Subject: Re: [PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

On 31.03.2021 19:01, Alexandre Belloni wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> On 31/03/2021 13:59:06+0300, Claudiu Beznea wrote:
>> From: Eugen Hristev <[email protected]>
>>
>> Introduce new family of SoCs, sama7, and first SoC, sama7g5.
>>
>> Signed-off-by: Eugen Hristev <[email protected]>
>> Signed-off-by: Claudiu Beznea <[email protected]>
>> ---
>> 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 000000000000..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 <linux/of.h>
>> +#include <linux/of_platform.h>
>> +
>> +#include <asm/mach/arch.h>
>> +#include <asm/system_misc.h>
>> +
>> +#include "generic.h"
>> +
>> +static void __init sama7_common_init(void)
>> +{
>> + of_platform_default_populate(NULL, NULL, NULL);
>
> Is this necessary? This is left as a workaround for the old SoCs using
> pinctrl-at91. I guess this will be using pio4 so this has to be removed.

OK, I'll have a look. BTW, SAMA5D2 which is also using PIO4 calls
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
>>
>
> --
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>

2021-04-01 10:34:17

by Claudiu Beznea

[permalink] [raw]
Subject: Re: [PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

On 01.04.2021 12:38, Claudiu Beznea - M18063 wrote:
> On 31.03.2021 19:01, Alexandre Belloni wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>
>> On 31/03/2021 13:59:06+0300, Claudiu Beznea wrote:
>>> From: Eugen Hristev <[email protected]>
>>>
>>> Introduce new family of SoCs, sama7, and first SoC, sama7g5.
>>>
>>> Signed-off-by: Eugen Hristev <[email protected]>
>>> Signed-off-by: Claudiu Beznea <[email protected]>
>>> ---
>>> 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 000000000000..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 <linux/of.h>
>>> +#include <linux/of_platform.h>
>>> +
>>> +#include <asm/mach/arch.h>
>>> +#include <asm/system_misc.h>
>>> +
>>> +#include "generic.h"
>>> +
>>> +static void __init sama7_common_init(void)
>>> +{
>>> + of_platform_default_populate(NULL, NULL, NULL);
>>
>> Is this necessary? This is left as a workaround for the old SoCs using
>> pinctrl-at91. I guess this will be using pio4 so this has to be removed.
>
> OK, I'll have a look. BTW, SAMA5D2 which is also using PIO4 calls
> of_platform_default_populate(NULL, NULL, NULL);

Without this call the PM code (arch/arm/mach-at/pm.c) is not able to locate
proper DT nodes:

[ 0.194615] at91_pm_backup_init: failed to find securam device!
[ 0.201393] at91_pm_sram_init: failed to find sram device!
[ 0.207449] AT91: PM not supported, due to no SRAM allocated

>
>>
>>> +}
>>> +
>>> +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
>>>
>>
>> --
>> Alexandre Belloni, co-owner and COO, Bootlin
>> Embedded Linux and Kernel engineering
>> https://bootlin.com
>>
>

2021-04-08 15:28:10

by Nicolas Ferre

[permalink] [raw]
Subject: Re: [PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

On 01/04/2021 at 12:24, Claudiu Beznea - M18063 wrote:
> On 01.04.2021 12:38, Claudiu Beznea - M18063 wrote:
>> On 31.03.2021 19:01, Alexandre Belloni wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> On 31/03/2021 13:59:06+0300, Claudiu Beznea wrote:
>>>> From: Eugen Hristev <[email protected]>
>>>>
>>>> Introduce new family of SoCs, sama7, and first SoC, sama7g5.
>>>>
>>>> Signed-off-by: Eugen Hristev <[email protected]>
>>>> Signed-off-by: Claudiu Beznea <[email protected]>
>>>> ---
>>>> 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 000000000000..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 <linux/of.h>
>>>> +#include <linux/of_platform.h>
>>>> +
>>>> +#include <asm/mach/arch.h>
>>>> +#include <asm/system_misc.h>
>>>> +
>>>> +#include "generic.h"
>>>> +
>>>> +static void __init sama7_common_init(void)
>>>> +{
>>>> + of_platform_default_populate(NULL, NULL, NULL);
>>>
>>> Is this necessary? This is left as a workaround for the old SoCs using
>>> pinctrl-at91. I guess this will be using pio4 so this has to be removed.
>>
>> OK, I'll have a look. BTW, SAMA5D2 which is also using PIO4 calls
>> of_platform_default_populate(NULL, NULL, NULL);
>
> Without this call the PM code (arch/arm/mach-at/pm.c) is not able to locate
> proper DT nodes:
>
> [ 0.194615] at91_pm_backup_init: failed to find securam device!
> [ 0.201393] at91_pm_sram_init: failed to find sram device!
> [ 0.207449] AT91: PM not supported, due to no SRAM allocated

Okay, so we can't afford removing these calls to sama5d2 and upcoming
sama7g5 right now.

Is it a common pattern to have to reach DT content in the early stages
that explicit call to of_platform_default_populate() tries to solve?

Best regards,
Nicolas


>>>> +}
>>>> +
>>>> +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
>>>>
>>>
>>> --
>>> Alexandre Belloni, co-owner and COO, Bootlin
>>> Embedded Linux and Kernel engineering
>>> https://bootlin.com
>>>
>>
>


--
Nicolas Ferre

2021-04-08 15:31:37

by Nicolas Ferre

[permalink] [raw]
Subject: Re: [PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

Hi,

On 31/03/2021 at 12:59, Claudiu Beznea wrote:
> From: Eugen Hristev <[email protected]>
>
> Introduce new family of SoCs, sama7, and first SoC, sama7g5.
>
> Signed-off-by: Eugen Hristev <[email protected]>
> Signed-off-by: Claudiu Beznea <[email protected]>
> ---
> 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

Nit: alphabetic order tells that it should be before samv7

>
> # 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 000000000000..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 <linux/of.h>
> +#include <linux/of_platform.h>
> +
> +#include <asm/mach/arch.h>
> +#include <asm/system_misc.h>
> +
> +#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

I'm not sure we need two DT_MACHINE_START() entries and associated
functions right now. Probably the most generic one is sufficient.
We can add such distinction in the future if the need arises.

Regards,
Nicolas

--
Nicolas Ferre

2021-04-08 17:48:04

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 22/24] ARM: at91: sama7: introduce sama7 SoC family

On 08/04/2021 17:24:39+0200, Nicolas Ferre wrote:
> On 01/04/2021 at 12:24, Claudiu Beznea - M18063 wrote:
> > On 01.04.2021 12:38, Claudiu Beznea - M18063 wrote:
> > > On 31.03.2021 19:01, Alexandre Belloni wrote:
> > > > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > > >
> > > > On 31/03/2021 13:59:06+0300, Claudiu Beznea wrote:
> > > > > From: Eugen Hristev <[email protected]>
> > > > >
> > > > > Introduce new family of SoCs, sama7, and first SoC, sama7g5.
> > > > >
> > > > > Signed-off-by: Eugen Hristev <[email protected]>
> > > > > Signed-off-by: Claudiu Beznea <[email protected]>
> > > > > ---
> > > > > 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 000000000000..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 <linux/of.h>
> > > > > +#include <linux/of_platform.h>
> > > > > +
> > > > > +#include <asm/mach/arch.h>
> > > > > +#include <asm/system_misc.h>
> > > > > +
> > > > > +#include "generic.h"
> > > > > +
> > > > > +static void __init sama7_common_init(void)
> > > > > +{
> > > > > + of_platform_default_populate(NULL, NULL, NULL);
> > > >
> > > > Is this necessary? This is left as a workaround for the old SoCs using
> > > > pinctrl-at91. I guess this will be using pio4 so this has to be removed.
> > >
> > > OK, I'll have a look. BTW, SAMA5D2 which is also using PIO4 calls
> > > of_platform_default_populate(NULL, NULL, NULL);
> >
> > Without this call the PM code (arch/arm/mach-at/pm.c) is not able to locate
> > proper DT nodes:
> >
> > [ 0.194615] at91_pm_backup_init: failed to find securam device!
> > [ 0.201393] at91_pm_sram_init: failed to find sram device!
> > [ 0.207449] AT91: PM not supported, due to no SRAM allocated
>
> Okay, so we can't afford removing these calls to sama5d2 and upcoming
> sama7g5 right now.
>
> Is it a common pattern to have to reach DT content in the early stages that
> explicit call to of_platform_default_populate() tries to solve?
>

That's fine, I didn't remember about that one, we can keep the call.


--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com