linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] rework ULP1 patches
@ 2018-07-17  8:26 Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 1/4] ARM: at91: pm: Use ULP0 naming instead of slow clock Claudiu Beznea
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17  8:26 UTC (permalink / raw)
  To: nicolas.ferre, alexandre.belloni, linux, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-clk, Claudiu Beznea

Hi,

Based on the discussion at [1] and private discussion I had with Alexandre
Belloni on IRC, I reworked ULP1 patches to remove device tree bindings
proposed in [1].

The implementation from this patches (mostly patch 4/4) is using
device_may_wakeup() API that current Linux code provides and the fact that
for the ULP1 the wakeup souces are known and well defined.
Basically, this rework (mostly patch 4/4) loops through well defined ULP1
wakeup sources and check if those wakeup sources were configured to wake
up the system (vid DT or sysfs) and, based on that (and in case of RTC,
based on SHDWC.MR), set the PMC fast startup mode and polarity registers.
In [1] PMC fast startup mode and polarity registers were configured by
introducing new DT bindings.

Since with these patches SHDWC registers are used in ULP1 wakeup sources
configuration the patch 4/4 changed a bit the PM initialization phase for
SAMA5D2 in order to have mapped also the SHDWC in case ULP1 needs to be
initialized. In case ULP1 configuration fails the ULP0 mode is used (same
approach as in backup mode case).

I measure the delay introduced in suspend sequence by using an oscilloscope
connected to a GPIO and calling gpio_direction_output(PIN, 0) at the beginning
of at91_pm_config_ws() and gpio_direction_output(PIN, 1) at the end of
at91_pm_config_ws(). With these I measureed on oscilloscope the difference
b/w the front changes. The measured time was *1.56ms*. Keep in mind that
gpio_direction_output() will call, in the end,
atmel_gpio_direction_output() which access 4 registers to toggle the PIN
(in at91_pm_config_ws() there are also 4 peripheral register accesses).

Besides this rework, I took the chance and I appended few other patches to
this series, based on Wenyou Yang's previous work, related to ULP modes.

Patch 1/4: replaces slow clock with ULP0
Patch 2/4: is the Wenyou's patch wich adds ULP1 support
Patch 3/4: is defining PMC fast startup registers

The patches were based on v4.18-rc1.

[1] https://patchwork.kernel.org/patch/8595091/

Claudiu Beznea (3):
  ARM: at91: pm: Use ULP0 naming instead of slow clock
  ARM: at91: pm: add PMC fast startup registers defines
  ARM: at91: pm: configure wakeup sources for ULP1 mode

Wenyou Yang (1):
  ARM: at91: pm: Add ULP1 mode support

 arch/arm/mach-at91/pm.c         | 184 +++++++++++++++++++++++++++++++++-------
 arch/arm/mach-at91/pm.h         |   6 +-
 arch/arm/mach-at91/pm_suspend.S | 142 ++++++++++++++++++++++++++-----
 include/linux/clk/at91_pmc.h    |  15 ++++
 4 files changed, 294 insertions(+), 53 deletions(-)

-- 
2.7.4


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

* [PATCH 1/4] ARM: at91: pm: Use ULP0 naming instead of slow clock
  2018-07-17  8:26 [PATCH 0/4] rework ULP1 patches Claudiu Beznea
@ 2018-07-17  8:26 ` Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 2/4] ARM: at91: pm: Add ULP1 mode support Claudiu Beznea
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17  8:26 UTC (permalink / raw)
  To: nicolas.ferre, alexandre.belloni, linux, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-clk, Claudiu Beznea

Switch to use ULP0 naming instead of slow clock naming for power modes, to
be as closed as possible to datasheet. This commit does the necessary
renaming and macro addition to be as close as possible to the namings
from [1].

[1] https://lore.kernel.org/lkml/1470650705-31418-3-git-send-email-wenyou.yang@atmel.com

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 arch/arm/mach-at91/pm.c         | 18 +++++++++---------
 arch/arm/mach-at91/pm.h         |  3 ++-
 arch/arm/mach-at91/pm_suspend.S | 12 ++++++------
 3 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 849014c01cf4..d43f00a715d7 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -40,15 +40,15 @@ extern void at91_pinctrl_gpio_resume(void);
 #endif
 
 static const match_table_t pm_modes __initconst = {
-	{ 0, "standby" },
-	{ AT91_PM_SLOW_CLOCK, "ulp0" },
+	{ AT91_PM_STANDBY, "standby" },
+	{ AT91_PM_ULP0, "ulp0" },
 	{ AT91_PM_BACKUP, "backup" },
 	{ -1, NULL },
 };
 
 static struct at91_pm_data pm_data = {
-	.standby_mode = 0,
-	.suspend_mode = AT91_PM_SLOW_CLOCK,
+	.standby_mode = AT91_PM_STANDBY,
+	.suspend_mode = AT91_PM_ULP0,
 };
 
 #define at91_ramc_read(id, field) \
@@ -145,7 +145,7 @@ static int at91_pm_verify_clocks(void)
  */
 int at91_suspend_entering_slow_clock(void)
 {
-	return (pm_data.mode >= AT91_PM_SLOW_CLOCK);
+	return (pm_data.mode >= AT91_PM_ULP0);
 }
 EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
@@ -186,7 +186,7 @@ static void at91_pm_suspend(suspend_state_t state)
  * event sources; and reduces DRAM power.  But otherwise it's identical to
  * PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
  *
- * AT91_PM_SLOW_CLOCK is like STANDBY plus slow clock mode, so drivers must
+ * AT91_PM_ULP0 is like STANDBY plus slow clock mode, so drivers must
  * suspend more deeply, the master clock switches to the clk32k and turns off
  * the main oscillator
  *
@@ -204,7 +204,7 @@ static int at91_pm_enter(suspend_state_t state)
 		/*
 		 * Ensure that clocks are in a valid state.
 		 */
-		if ((pm_data.mode >= AT91_PM_SLOW_CLOCK) &&
+		if (pm_data.mode >= AT91_PM_ULP0 &&
 		    !at91_pm_verify_clocks())
 			goto error;
 
@@ -546,9 +546,9 @@ static void __init at91_pm_backup_init(void)
 	pm_data.sfrbu = NULL;
 
 	if (pm_data.standby_mode == AT91_PM_BACKUP)
-		pm_data.standby_mode = AT91_PM_SLOW_CLOCK;
+		pm_data.standby_mode = AT91_PM_ULP0;
 	if (pm_data.suspend_mode == AT91_PM_BACKUP)
-		pm_data.suspend_mode = AT91_PM_SLOW_CLOCK;
+		pm_data.suspend_mode = AT91_PM_ULP0;
 }
 
 struct pmc_info {
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index f95d31496f08..c44eaf17db86 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,7 +21,8 @@
 #define AT91_MEMCTRL_SDRAMC	1
 #define AT91_MEMCTRL_DDRSDR	2
 
-#define	AT91_PM_SLOW_CLOCK	0x01
+#define	AT91_PM_STANDBY		0x00
+#define AT91_PM_ULP0		0x01
 #define	AT91_PM_BACKUP		0x02
 
 #ifndef __ASSEMBLY__
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index daca91feea6a..821322d1a64d 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -112,8 +112,8 @@ ENTRY(at91_pm_suspend_in_sram)
 	bl	at91_sramc_self_refresh
 
 	ldr	r0, .pm_mode
-	cmp	r0, #AT91_PM_SLOW_CLOCK
-	beq	slow_clock
+	cmp	r0, #AT91_PM_ULP0
+	beq	ulp0_mode
 	cmp	r0, #AT91_PM_BACKUP
 	beq	backup_mode
 
@@ -122,8 +122,8 @@ ENTRY(at91_pm_suspend_in_sram)
 	at91_cpu_idle
 	b	exit_suspend
 
-slow_clock:
-	bl	at91_slowck_mode
+ulp0_mode:
+	bl	at91_ulp0_mode
 	b	exit_suspend
 backup_mode:
 	bl	at91_backup_mode
@@ -151,7 +151,7 @@ ENTRY(at91_backup_mode)
 	str	tmp1, [r0, #0]
 ENDPROC(at91_backup_mode)
 
-ENTRY(at91_slowck_mode)
+ENTRY(at91_ulp0_mode)
 	ldr	pmc, .pmc_base
 
 	/* Save Master clock setting */
@@ -212,7 +212,7 @@ ENTRY(at91_slowck_mode)
 	wait_mckrdy
 
 	mov	pc, lr
-ENDPROC(at91_slowck_mode)
+ENDPROC(at91_ulp0_mode)
 
 /*
  * void at91_sramc_self_refresh(unsigned int is_active)
-- 
2.7.4


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

* [PATCH 2/4] ARM: at91: pm: Add ULP1 mode support
  2018-07-17  8:26 [PATCH 0/4] rework ULP1 patches Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 1/4] ARM: at91: pm: Use ULP0 naming instead of slow clock Claudiu Beznea
@ 2018-07-17  8:26 ` Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 3/4] ARM: at91: pm: add PMC fast startup registers defines Claudiu Beznea
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17  8:26 UTC (permalink / raw)
  To: nicolas.ferre, alexandre.belloni, linux, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-clk, Wenyou Yang,
	Ludovic Desroches, Claudiu Beznea

From: Wenyou Yang <wenyou.yang@atmel.com>

In the ULP1 mode, in order to achieve the lowest power consumption
with the system in retention mode and be able to resume on the wake
up events, all the clocks are shut off, inclusive the embedded 12MHz
RC oscillator, and the number of wake up sources is limited as well.
When the wake up event is asserted, the embedded 12MHz RC oscillator
restarts automatically.

The ULP1 (Ultra Low-power mode 1) is introduced by SAMA5D2.

The previous size of pm_suspend.o was 2148 bytes. With the addition of
ULP1 mode the new size of pm_suspend.o raised at 2456 bytes.

Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
[claudiu.beznea@microchip.com: aligned with 4.18-rc1]
Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 arch/arm/mach-at91/pm.c         |   1 +
 arch/arm/mach-at91/pm.h         |   3 +-
 arch/arm/mach-at91/pm_suspend.S | 142 ++++++++++++++++++++++++++++++++++------
 include/linux/clk/at91_pmc.h    |   2 +
 4 files changed, 127 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index d43f00a715d7..099d8094018c 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -42,6 +42,7 @@ extern void at91_pinctrl_gpio_resume(void);
 static const match_table_t pm_modes __initconst = {
 	{ AT91_PM_STANDBY, "standby" },
 	{ AT91_PM_ULP0, "ulp0" },
+	{ AT91_PM_ULP1, "ulp1" },
 	{ AT91_PM_BACKUP, "backup" },
 	{ -1, NULL },
 };
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index c44eaf17db86..9bd4e6ca672a 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -23,7 +23,8 @@
 
 #define	AT91_PM_STANDBY		0x00
 #define AT91_PM_ULP0		0x01
-#define	AT91_PM_BACKUP		0x02
+#define AT91_PM_ULP1		0x02
+#define	AT91_PM_BACKUP		0x03
 
 #ifndef __ASSEMBLY__
 struct at91_pm_data {
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 821322d1a64d..a7c6ae13c945 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -42,6 +42,15 @@ tmp2	.req	r5
 	.endm
 
 /*
+ * Wait for main oscillator selection is done
+ */
+	.macro wait_moscsels
+1:	ldr	tmp1, [pmc, #AT91_PMC_SR]
+	tst	tmp1, #AT91_PMC_MOSCSELS
+	beq	1b
+	.endm
+
+/*
  * Wait until PLLA has locked.
  */
 	.macro wait_pllalock
@@ -112,19 +121,20 @@ ENTRY(at91_pm_suspend_in_sram)
 	bl	at91_sramc_self_refresh
 
 	ldr	r0, .pm_mode
-	cmp	r0, #AT91_PM_ULP0
-	beq	ulp0_mode
+	cmp	r0, #AT91_PM_STANDBY
+	beq	standby
 	cmp	r0, #AT91_PM_BACKUP
 	beq	backup_mode
 
+	bl	at91_ulp_mode
+	b	exit_suspend
+
+standby:
 	/* Wait for interrupt */
 	ldr	pmc, .pmc_base
 	at91_cpu_idle
 	b	exit_suspend
 
-ulp0_mode:
-	bl	at91_ulp0_mode
-	b	exit_suspend
 backup_mode:
 	bl	at91_backup_mode
 	b	exit_suspend
@@ -151,7 +161,102 @@ ENTRY(at91_backup_mode)
 	str	tmp1, [r0, #0]
 ENDPROC(at91_backup_mode)
 
-ENTRY(at91_ulp0_mode)
+.macro at91_pm_ulp0_mode
+	ldr	pmc, .pmc_base
+
+	/* Turn off the crystal oscillator */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	/* Wait for interrupt */
+	at91_cpu_idle
+
+	/* Turn on the crystal oscillator */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	wait_moscrdy
+.endm
+
+/**
+ * Note: This procedure only applies on the platform which uses
+ * the external crystal oscillator as a main clock source.
+ */
+.macro at91_pm_ulp1_mode
+	ldr	pmc, .pmc_base
+
+	/* Switch the main clock source to 12-MHz RC oscillator */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
+	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	wait_moscsels
+
+	/* Disable the crystal oscillator */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
+	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	/* Switch the master clock source to main clock */
+	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
+	bic	tmp1, tmp1, #AT91_PMC_CSS
+	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
+	str	tmp1, [pmc, #AT91_PMC_MCKR]
+
+	wait_mckrdy
+
+	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
+	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	wait_mckrdy
+
+	/* Enable the crystal oscillator */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
+	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	wait_moscrdy
+
+	/* Switch the master clock source to slow clock */
+	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
+	bic	tmp1, tmp1, #AT91_PMC_CSS
+	str	tmp1, [pmc, #AT91_PMC_MCKR]
+
+	wait_mckrdy
+
+	/* Switch main clock source to crystal oscillator */
+	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
+	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
+	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
+	orr	tmp1, tmp1, #AT91_PMC_KEY
+	str	tmp1, [pmc, #AT91_CKGR_MOR]
+
+	wait_moscsels
+
+	/* Switch the master clock source to main clock */
+	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
+	bic	tmp1, tmp1, #AT91_PMC_CSS
+	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
+	str	tmp1, [pmc, #AT91_PMC_MCKR]
+
+	wait_mckrdy
+.endm
+
+ENTRY(at91_ulp_mode)
 	ldr	pmc, .pmc_base
 
 	/* Save Master clock setting */
@@ -174,22 +279,19 @@ ENTRY(at91_ulp0_mode)
 	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
 	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
 
-	/* Turn off the main oscillator */
-	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
-	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
-	orr	tmp1, tmp1, #AT91_PMC_KEY
-	str	tmp1, [pmc, #AT91_CKGR_MOR]
+	ldr	r0, .pm_mode
+	cmp	r0, #AT91_PM_ULP1
+	beq	ulp1_mode
 
-	/* Wait for interrupt */
-	at91_cpu_idle
+	at91_pm_ulp0_mode
+	b	ulp_exit
 
-	/* Turn on the main oscillator */
-	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
-	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
-	orr	tmp1, tmp1, #AT91_PMC_KEY
-	str	tmp1, [pmc, #AT91_CKGR_MOR]
+ulp1_mode:
+	at91_pm_ulp1_mode
+	b	ulp_exit
 
-	wait_moscrdy
+ulp_exit:
+	ldr	pmc, .pmc_base
 
 	/* Restore PLLA setting */
 	ldr	tmp1, .saved_pllar
@@ -212,7 +314,7 @@ ENTRY(at91_ulp0_mode)
 	wait_mckrdy
 
 	mov	pc, lr
-ENDPROC(at91_ulp0_mode)
+ENDPROC(at91_ulp_mode)
 
 /*
  * void at91_sramc_self_refresh(unsigned int is_active)
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h
index 6aca5ce8a99a..4ea2cbf9b50d 100644
--- a/include/linux/clk/at91_pmc.h
+++ b/include/linux/clk/at91_pmc.h
@@ -47,8 +47,10 @@
 #define	AT91_CKGR_MOR		0x20			/* Main Oscillator Register [not on SAM9RL] */
 #define		AT91_PMC_MOSCEN		(1    <<  0)		/* Main Oscillator Enable */
 #define		AT91_PMC_OSCBYPASS	(1    <<  1)		/* Oscillator Bypass */
+#define		AT91_PMC_WAITMODE	(1    <<  2)		/* Wait Mode Command */
 #define		AT91_PMC_MOSCRCEN	(1    <<  3)		/* Main On-Chip RC Oscillator Enable [some SAM9] */
 #define		AT91_PMC_OSCOUNT	(0xff <<  8)		/* Main Oscillator Start-up Time */
+#define		AT91_PMC_KEY_MASK	(0xff << 16)
 #define		AT91_PMC_KEY		(0x37 << 16)		/* MOR Writing Key */
 #define		AT91_PMC_MOSCSEL	(1    << 24)		/* Main Oscillator Selection [some SAM9] */
 #define		AT91_PMC_CFDEN		(1    << 25)		/* Clock Failure Detector Enable [some SAM9] */
-- 
2.7.4


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

* [PATCH 3/4] ARM: at91: pm: add PMC fast startup registers defines
  2018-07-17  8:26 [PATCH 0/4] rework ULP1 patches Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 1/4] ARM: at91: pm: Use ULP0 naming instead of slow clock Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 2/4] ARM: at91: pm: Add ULP1 mode support Claudiu Beznea
@ 2018-07-17  8:26 ` Claudiu Beznea
  2018-07-17  8:26 ` [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode Claudiu Beznea
  2018-07-17 19:16 ` [PATCH 0/4] rework ULP1 patches Alexandre Belloni
  4 siblings, 0 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17  8:26 UTC (permalink / raw)
  To: nicolas.ferre, alexandre.belloni, linux, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-clk, Claudiu Beznea

Add PMC fast startup registers defines.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 include/linux/clk/at91_pmc.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h
index 4ea2cbf9b50d..931ab05f771d 100644
--- a/include/linux/clk/at91_pmc.h
+++ b/include/linux/clk/at91_pmc.h
@@ -157,6 +157,19 @@
 #define		AT91_PMC_GCKRDY		(1 << 24)		/* Generated Clocks */
 #define	AT91_PMC_IMR		0x6c			/* Interrupt Mask Register */
 
+#define AT91_PMC_FSMR		0x70		/* Fast Startup Mode Register */
+#define AT91_PMC_FSTT(n)	BIT(n)
+#define AT91_PMC_RTCAL		BIT(17)		/* RTC Alarm Enable */
+#define AT91_PMC_USBAL		BIT(18)		/* USB Resume Enable */
+#define AT91_PMC_SDMMC_CD	BIT(19)		/* SDMMC Card Detect Enable */
+#define AT91_PMC_LPM		BIT(20)		/* Low-power Mode */
+#define AT91_PMC_RXLP_MCE	BIT(24)		/* Backup UART Receive Enable */
+#define AT91_PMC_ACC_CE		BIT(25)		/* ACC Enable */
+
+#define AT91_PMC_FSPR		0x74		/* Fast Startup Polarity Reg */
+
+#define AT91_PMC_FS_INPUT_MASK  0x7ff
+
 #define AT91_PMC_PLLICPR	0x80			/* PLL Charge Pump Current Register */
 
 #define AT91_PMC_PROT		0xe4			/* Write Protect Mode Register [some SAM9] */
-- 
2.7.4


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

* [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode
  2018-07-17  8:26 [PATCH 0/4] rework ULP1 patches Claudiu Beznea
                   ` (2 preceding siblings ...)
  2018-07-17  8:26 ` [PATCH 3/4] ARM: at91: pm: add PMC fast startup registers defines Claudiu Beznea
@ 2018-07-17  8:26 ` Claudiu Beznea
  2018-07-17 10:45   ` Alexandre Belloni
  2018-07-17 11:06   ` [RESEND PATCH] " Claudiu Beznea
  2018-07-17 19:16 ` [PATCH 0/4] rework ULP1 patches Alexandre Belloni
  4 siblings, 2 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17  8:26 UTC (permalink / raw)
  To: nicolas.ferre, alexandre.belloni, linux, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-clk, Claudiu Beznea

Since for ULP1 PM mode of SAMA5D2 the wakeup sources are limited and
well known add a method to check if these wakeup sources are defined by
user (either via DT or filesystem). In case there are no wakeup sources
defined for ULP1 the PM suspend will fail, otherwise these will be
configured in fast startup registers of PMC. Since wakeup sources of
ULP1 need also to be configured in SHDWC registers the code was a bit
changed to map the SHDWC also in case ULP1 is requested by user (this
was done in the initialization phase). In case the ULP1 initialization
fails the ULP0 mode is used (this mode was also used in case backup mode
initialization failed).

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 arch/arm/mach-at91/pm.c | 165 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 143 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 099d8094018c..c8ef696b83b6 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -80,6 +80,87 @@ static struct at91_pm_bu {
 	phys_addr_t resume;
 } *pm_bu;
 
+struct wakeup_source_info {
+	unsigned int pmc_fsmr_bit;
+	unsigned int shdwc_mr_bit;
+	bool set_polarity;
+};
+
+static const struct wakeup_source_info ws_info[] = {
+	{ .pmc_fsmr_bit = AT91_PMC_FSTT(10),	.set_polarity = true },
+	{ .pmc_fsmr_bit = AT91_PMC_RTCAL,	.shdwc_mr_bit = BIT(17) },
+	{ .pmc_fsmr_bit = AT91_PMC_USBAL },
+	{ .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
+};
+
+static const struct of_device_id sama5d2_ws_ids[] = {
+	{ .compatible = "atmel,sama5d2-gem",		.data = &ws_info[0] },
+	{ .compatible = "atmel,at91rm9200-rtc",		.data = &ws_info[1] },
+	{ .compatible = "atmel,sama5d3-udc",		.data = &ws_info[2] },
+	{ .compatible = "atmel,at91rm9200-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 = "atmel,sama5d2-sdhci",		.data = &ws_info[3] },
+	{ /* sentinel */ }
+};
+
+static int at91_pm_config_ws(unsigned int pm_mode, bool set)
+{
+	const struct wakeup_source_info *wsi;
+	const struct of_device_id *match;
+	struct platform_device *pdev;
+	struct device_node *np;
+	unsigned int mode = 0, polarity = 0, val = 0;
+
+	if (pm_mode != AT91_PM_ULP1)
+		return 0;
+
+	if (!pm_data.pmc || !pm_data.shdwc)
+		return -EPERM;
+
+	if (!set) {
+		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
+		return 0;
+	}
+
+	/* SHDWC.WUIR */
+	val = readl(pm_data.shdwc + 0x0c);
+	mode |= (val & 0x3ff);
+	polarity |= ((val >> 16) & 0x3ff);
+
+	/* SHDWC.MR */
+	val = readl(pm_data.shdwc + 0x04);
+
+	/* Loop through defined wakeup sources. */
+	for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) {
+		pdev = of_find_device_by_node(np);
+		if (!pdev)
+			continue;
+
+		if (device_may_wakeup(&pdev->dev)) {
+			wsi = match->data;
+
+			/* Check if enabled on SHDWC. */
+			if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
+				continue;
+
+			mode |= wsi->pmc_fsmr_bit;
+			if (wsi->set_polarity)
+				polarity |= wsi->pmc_fsmr_bit;
+		}
+	}
+
+	if (mode) {
+		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
+		writel(polarity, pm_data.pmc + AT91_PMC_FSPR);
+	} else {
+		pr_err("AT91: PM: no ULP1 wakeup sources found!");
+	}
+
+	return mode ? 0 : -EPERM;
+}
+
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
@@ -98,7 +179,7 @@ static int at91_pm_begin(suspend_state_t state)
 		pm_data.mode = -1;
 	}
 
-	return 0;
+	return at91_pm_config_ws(pm_data.mode, true);
 }
 
 /*
@@ -234,6 +315,7 @@ static int at91_pm_enter(suspend_state_t state)
  */
 static void at91_pm_end(void)
 {
+	at91_pm_config_ws(pm_data.mode, false);
 }
 
 
@@ -479,31 +561,28 @@ static void __init at91_pm_sram_init(void)
 			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
 }
 
-static void __init at91_pm_backup_init(void)
+static bool __init at91_is_pm_mode_active(int pm_mode)
+{
+	return (pm_data.standby_mode == pm_mode ||
+		pm_data.suspend_mode == pm_mode);
+}
+
+static int __init at91_pm_backup_init(void)
 {
 	struct gen_pool *sram_pool;
 	struct device_node *np;
 	struct platform_device *pdev = NULL;
+	int ret = -ENODEV;
 
-	if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
-	    (pm_data.suspend_mode != AT91_PM_BACKUP))
-		return;
+	if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
+		return 0;
 
 	pm_bu = NULL;
 
-	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
-	if (!np) {
-		pr_warn("%s: failed to find shdwc!\n", __func__);
-		return;
-	}
-
-	pm_data.shdwc = of_iomap(np, 0);
-	of_node_put(np);
-
 	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
 	if (!np) {
 		pr_warn("%s: failed to find sfrbu!\n", __func__);
-		goto sfrbu_fail;
+		return ret;
 	}
 
 	pm_data.sfrbu = of_iomap(np, 0);
@@ -530,6 +609,7 @@ static void __init at91_pm_backup_init(void)
 	pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
 	if (!pm_bu) {
 		pr_warn("%s: unable to alloc securam!\n", __func__);
+		ret = -ENOMEM;
 		goto securam_fail;
 	}
 
@@ -537,21 +617,62 @@ static void __init at91_pm_backup_init(void)
 	pm_bu->canary = __pa_symbol(&canary);
 	pm_bu->resume = __pa_symbol(cpu_resume);
 
-	return;
+	return 0;
 
-sfrbu_fail:
-	iounmap(pm_data.shdwc);
-	pm_data.shdwc = NULL;
 securam_fail:
 	iounmap(pm_data.sfrbu);
 	pm_data.sfrbu = NULL;
+	return ret;
+}
 
-	if (pm_data.standby_mode == AT91_PM_BACKUP)
+static void __init at91_pm_use_default_mode(int pm_mode)
+{
+	if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
+		return;
+
+	if (pm_data.standby_mode == pm_mode)
 		pm_data.standby_mode = AT91_PM_ULP0;
-	if (pm_data.suspend_mode == AT91_PM_BACKUP)
+	if (pm_data.suspend_mode == pm_mode)
 		pm_data.suspend_mode = AT91_PM_ULP0;
 }
 
+static void __init at91_pm_modes_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
+	    !at91_is_pm_mode_active(AT91_PM_ULP1))
+		return;
+
+	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
+	if (!np) {
+		pr_warn("%s: failed to find shdwc!\n", __func__);
+		goto ulp1_default;
+	}
+
+	pm_data.shdwc = 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;
+	}
+
+	return;
+
+unmap:
+	iounmap(pm_data.shdwc);
+	pm_data.shdwc = NULL;
+ulp1_default:
+	at91_pm_use_default_mode(AT91_PM_ULP1);
+backup_default:
+	at91_pm_use_default_mode(AT91_PM_BACKUP);
+}
+
 struct pmc_info {
 	unsigned long uhp_udp_mask;
 };
@@ -645,7 +766,7 @@ void __init sama5d2_pm_init(void)
 	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
 		return;
 
-	at91_pm_backup_init();
+	at91_pm_modes_init();
 	sama5_pm_init();
 }
 
-- 
2.7.4


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

* Re: [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode
  2018-07-17  8:26 ` [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode Claudiu Beznea
@ 2018-07-17 10:45   ` Alexandre Belloni
  2018-07-17 10:49     ` Claudiu Beznea
  2018-07-17 11:06   ` [RESEND PATCH] " Claudiu Beznea
  1 sibling, 1 reply; 9+ messages in thread
From: Alexandre Belloni @ 2018-07-17 10:45 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: nicolas.ferre, linux, mturquette, sboyd, linux-arm-kernel,
	linux-kernel, linux-clk

Hi,

On 17/07/2018 11:26:57+0300, Claudiu Beznea wrote:
> Since for ULP1 PM mode of SAMA5D2 the wakeup sources are limited and
> well known add a method to check if these wakeup sources are defined by
> user (either via DT or filesystem). In case there are no wakeup sources
> defined for ULP1 the PM suspend will fail, otherwise these will be
> configured in fast startup registers of PMC. Since wakeup sources of
> ULP1 need also to be configured in SHDWC registers the code was a bit
> changed to map the SHDWC also in case ULP1 is requested by user (this
> was done in the initialization phase). In case the ULP1 initialization
> fails the ULP0 mode is used (this mode was also used in case backup mode
> initialization failed).
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> ---
>  arch/arm/mach-at91/pm.c | 165 +++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 143 insertions(+), 22 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
> index 099d8094018c..c8ef696b83b6 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -80,6 +80,87 @@ static struct at91_pm_bu {
>  	phys_addr_t resume;
>  } *pm_bu;
>  
> +struct wakeup_source_info {
> +	unsigned int pmc_fsmr_bit;
> +	unsigned int shdwc_mr_bit;
> +	bool set_polarity;
> +};
> +
> +static const struct wakeup_source_info ws_info[] = {
> +	{ .pmc_fsmr_bit = AT91_PMC_FSTT(10),	.set_polarity = true },
> +	{ .pmc_fsmr_bit = AT91_PMC_RTCAL,	.shdwc_mr_bit = BIT(17) },
> +	{ .pmc_fsmr_bit = AT91_PMC_USBAL },
> +	{ .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
> +};
> +
> +static const struct of_device_id sama5d2_ws_ids[] = {
> +	{ .compatible = "atmel,sama5d2-gem",		.data = &ws_info[0] },
> +	{ .compatible = "atmel,at91rm9200-rtc",		.data = &ws_info[1] },
> +	{ .compatible = "atmel,sama5d3-udc",		.data = &ws_info[2] },
> +	{ .compatible = "atmel,at91rm9200-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 = "atmel,sama5d2-sdhci",		.data = &ws_info[3] },
> +	{ /* sentinel */ }
> +};
> +
> +static int at91_pm_config_ws(unsigned int pm_mode, bool set)
> +{
> +	const struct wakeup_source_info *wsi;
> +	const struct of_device_id *match;
> +	struct platform_device *pdev;
> +	struct device_node *np;
> +	unsigned int mode = 0, polarity = 0, val = 0;
> +
> +	if (pm_mode != AT91_PM_ULP1)
> +		return 0;
> +
> +	if (!pm_data.pmc || !pm_data.shdwc)
> +		return -EPERM;
> +
> +	if (!set) {
> +		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
> +		return 0;
> +	}
> +
> +	/* SHDWC.WUIR */
> +	val = readl(pm_data.shdwc + 0x0c);
> +	mode |= (val & 0x3ff);
> +	polarity |= ((val >> 16) & 0x3ff);
> +
> +	/* SHDWC.MR */
> +	val = readl(pm_data.shdwc + 0x04);
> +
> +	/* Loop through defined wakeup sources. */
> +	for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) {
> +		pdev = of_find_device_by_node(np);

of_find_device_by_node takes a reference to the embedded struct
device...

> +		if (!pdev)
> +			continue;
> +
> +		if (device_may_wakeup(&pdev->dev)) {
> +			wsi = match->data;
> +
> +			/* Check if enabled on SHDWC. */
> +			if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
> +				continue;
> +
> +			mode |= wsi->pmc_fsmr_bit;
> +			if (wsi->set_polarity)
> +				polarity |= wsi->pmc_fsmr_bit;
> +		}

So you need to drop it here.

Can you do that and resend, just that patch? thanks.

> +	}
> +
> +	if (mode) {
> +		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
> +		writel(polarity, pm_data.pmc + AT91_PMC_FSPR);
> +	} else {
> +		pr_err("AT91: PM: no ULP1 wakeup sources found!");
> +	}
> +
> +	return mode ? 0 : -EPERM;
> +}
> +
>  /*
>   * Called after processes are frozen, but before we shutdown devices.
>   */
> @@ -98,7 +179,7 @@ static int at91_pm_begin(suspend_state_t state)
>  		pm_data.mode = -1;
>  	}
>  
> -	return 0;
> +	return at91_pm_config_ws(pm_data.mode, true);
>  }
>  
>  /*
> @@ -234,6 +315,7 @@ static int at91_pm_enter(suspend_state_t state)
>   */
>  static void at91_pm_end(void)
>  {
> +	at91_pm_config_ws(pm_data.mode, false);
>  }
>  
>  
> @@ -479,31 +561,28 @@ static void __init at91_pm_sram_init(void)
>  			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
>  }
>  
> -static void __init at91_pm_backup_init(void)
> +static bool __init at91_is_pm_mode_active(int pm_mode)
> +{
> +	return (pm_data.standby_mode == pm_mode ||
> +		pm_data.suspend_mode == pm_mode);
> +}
> +
> +static int __init at91_pm_backup_init(void)
>  {
>  	struct gen_pool *sram_pool;
>  	struct device_node *np;
>  	struct platform_device *pdev = NULL;
> +	int ret = -ENODEV;
>  
> -	if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
> -	    (pm_data.suspend_mode != AT91_PM_BACKUP))
> -		return;
> +	if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
> +		return 0;
>  
>  	pm_bu = NULL;
>  
> -	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
> -	if (!np) {
> -		pr_warn("%s: failed to find shdwc!\n", __func__);
> -		return;
> -	}
> -
> -	pm_data.shdwc = of_iomap(np, 0);
> -	of_node_put(np);
> -
>  	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
>  	if (!np) {
>  		pr_warn("%s: failed to find sfrbu!\n", __func__);
> -		goto sfrbu_fail;
> +		return ret;
>  	}
>  
>  	pm_data.sfrbu = of_iomap(np, 0);
> @@ -530,6 +609,7 @@ static void __init at91_pm_backup_init(void)
>  	pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
>  	if (!pm_bu) {
>  		pr_warn("%s: unable to alloc securam!\n", __func__);
> +		ret = -ENOMEM;
>  		goto securam_fail;
>  	}
>  
> @@ -537,21 +617,62 @@ static void __init at91_pm_backup_init(void)
>  	pm_bu->canary = __pa_symbol(&canary);
>  	pm_bu->resume = __pa_symbol(cpu_resume);
>  
> -	return;
> +	return 0;
>  
> -sfrbu_fail:
> -	iounmap(pm_data.shdwc);
> -	pm_data.shdwc = NULL;
>  securam_fail:
>  	iounmap(pm_data.sfrbu);
>  	pm_data.sfrbu = NULL;
> +	return ret;
> +}
>  
> -	if (pm_data.standby_mode == AT91_PM_BACKUP)
> +static void __init at91_pm_use_default_mode(int pm_mode)
> +{
> +	if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
> +		return;
> +
> +	if (pm_data.standby_mode == pm_mode)
>  		pm_data.standby_mode = AT91_PM_ULP0;
> -	if (pm_data.suspend_mode == AT91_PM_BACKUP)
> +	if (pm_data.suspend_mode == pm_mode)
>  		pm_data.suspend_mode = AT91_PM_ULP0;
>  }
>  
> +static void __init at91_pm_modes_init(void)
> +{
> +	struct device_node *np;
> +	int ret;
> +
> +	if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
> +	    !at91_is_pm_mode_active(AT91_PM_ULP1))
> +		return;
> +
> +	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
> +	if (!np) {
> +		pr_warn("%s: failed to find shdwc!\n", __func__);
> +		goto ulp1_default;
> +	}
> +
> +	pm_data.shdwc = 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;
> +	}
> +
> +	return;
> +
> +unmap:
> +	iounmap(pm_data.shdwc);
> +	pm_data.shdwc = NULL;
> +ulp1_default:
> +	at91_pm_use_default_mode(AT91_PM_ULP1);
> +backup_default:
> +	at91_pm_use_default_mode(AT91_PM_BACKUP);
> +}
> +
>  struct pmc_info {
>  	unsigned long uhp_udp_mask;
>  };
> @@ -645,7 +766,7 @@ void __init sama5d2_pm_init(void)
>  	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
>  		return;
>  
> -	at91_pm_backup_init();
> +	at91_pm_modes_init();
>  	sama5_pm_init();
>  }
>  
> -- 
> 2.7.4
> 

-- 
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode
  2018-07-17 10:45   ` Alexandre Belloni
@ 2018-07-17 10:49     ` Claudiu Beznea
  0 siblings, 0 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17 10:49 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: sboyd, mturquette, linux-kernel, linux, linux-clk, linux-arm-kernel



On 17.07.2018 13:45, Alexandre Belloni wrote:
> Hi,
> 
> On 17/07/2018 11:26:57+0300, Claudiu Beznea wrote:
>> Since for ULP1 PM mode of SAMA5D2 the wakeup sources are limited and
>> well known add a method to check if these wakeup sources are defined by
>> user (either via DT or filesystem). In case there are no wakeup sources
>> defined for ULP1 the PM suspend will fail, otherwise these will be
>> configured in fast startup registers of PMC. Since wakeup sources of
>> ULP1 need also to be configured in SHDWC registers the code was a bit
>> changed to map the SHDWC also in case ULP1 is requested by user (this
>> was done in the initialization phase). In case the ULP1 initialization
>> fails the ULP0 mode is used (this mode was also used in case backup mode
>> initialization failed).
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>> ---
>>  arch/arm/mach-at91/pm.c | 165 +++++++++++++++++++++++++++++++++++++++++-------
>>  1 file changed, 143 insertions(+), 22 deletions(-)
>>
>> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
>> index 099d8094018c..c8ef696b83b6 100644
>> --- a/arch/arm/mach-at91/pm.c
>> +++ b/arch/arm/mach-at91/pm.c
>> @@ -80,6 +80,87 @@ static struct at91_pm_bu {
>>  	phys_addr_t resume;
>>  } *pm_bu;
>>  
>> +struct wakeup_source_info {
>> +	unsigned int pmc_fsmr_bit;
>> +	unsigned int shdwc_mr_bit;
>> +	bool set_polarity;
>> +};
>> +
>> +static const struct wakeup_source_info ws_info[] = {
>> +	{ .pmc_fsmr_bit = AT91_PMC_FSTT(10),	.set_polarity = true },
>> +	{ .pmc_fsmr_bit = AT91_PMC_RTCAL,	.shdwc_mr_bit = BIT(17) },
>> +	{ .pmc_fsmr_bit = AT91_PMC_USBAL },
>> +	{ .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
>> +};
>> +
>> +static const struct of_device_id sama5d2_ws_ids[] = {
>> +	{ .compatible = "atmel,sama5d2-gem",		.data = &ws_info[0] },
>> +	{ .compatible = "atmel,at91rm9200-rtc",		.data = &ws_info[1] },
>> +	{ .compatible = "atmel,sama5d3-udc",		.data = &ws_info[2] },
>> +	{ .compatible = "atmel,at91rm9200-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 = "atmel,sama5d2-sdhci",		.data = &ws_info[3] },
>> +	{ /* sentinel */ }
>> +};
>> +
>> +static int at91_pm_config_ws(unsigned int pm_mode, bool set)
>> +{
>> +	const struct wakeup_source_info *wsi;
>> +	const struct of_device_id *match;
>> +	struct platform_device *pdev;
>> +	struct device_node *np;
>> +	unsigned int mode = 0, polarity = 0, val = 0;
>> +
>> +	if (pm_mode != AT91_PM_ULP1)
>> +		return 0;
>> +
>> +	if (!pm_data.pmc || !pm_data.shdwc)
>> +		return -EPERM;
>> +
>> +	if (!set) {
>> +		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
>> +		return 0;
>> +	}
>> +
>> +	/* SHDWC.WUIR */
>> +	val = readl(pm_data.shdwc + 0x0c);
>> +	mode |= (val & 0x3ff);
>> +	polarity |= ((val >> 16) & 0x3ff);
>> +
>> +	/* SHDWC.MR */
>> +	val = readl(pm_data.shdwc + 0x04);
>> +
>> +	/* Loop through defined wakeup sources. */
>> +	for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) {
>> +		pdev = of_find_device_by_node(np);
> 
> of_find_device_by_node takes a reference to the embedded struct
> device...
> 

Yes, thank you!

>> +		if (!pdev)
>> +			continue;
>> +
>> +		if (device_may_wakeup(&pdev->dev)) {
>> +			wsi = match->data;
>> +
>> +			/* Check if enabled on SHDWC. */
>> +			if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
>> +				continue;
>> +
>> +			mode |= wsi->pmc_fsmr_bit;
>> +			if (wsi->set_polarity)
>> +				polarity |= wsi->pmc_fsmr_bit;
>> +		}
> 
> So you need to drop it here.
> 
> Can you do that and resend, just that patch? thanks.
> 
>> +	}
>> +
>> +	if (mode) {
>> +		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
>> +		writel(polarity, pm_data.pmc + AT91_PMC_FSPR);
>> +	} else {
>> +		pr_err("AT91: PM: no ULP1 wakeup sources found!");
>> +	}
>> +
>> +	return mode ? 0 : -EPERM;
>> +}
>> +
>>  /*
>>   * Called after processes are frozen, but before we shutdown devices.
>>   */
>> @@ -98,7 +179,7 @@ static int at91_pm_begin(suspend_state_t state)
>>  		pm_data.mode = -1;
>>  	}
>>  
>> -	return 0;
>> +	return at91_pm_config_ws(pm_data.mode, true);
>>  }
>>  
>>  /*
>> @@ -234,6 +315,7 @@ static int at91_pm_enter(suspend_state_t state)
>>   */
>>  static void at91_pm_end(void)
>>  {
>> +	at91_pm_config_ws(pm_data.mode, false);
>>  }
>>  
>>  
>> @@ -479,31 +561,28 @@ static void __init at91_pm_sram_init(void)
>>  			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
>>  }
>>  
>> -static void __init at91_pm_backup_init(void)
>> +static bool __init at91_is_pm_mode_active(int pm_mode)
>> +{
>> +	return (pm_data.standby_mode == pm_mode ||
>> +		pm_data.suspend_mode == pm_mode);
>> +}
>> +
>> +static int __init at91_pm_backup_init(void)
>>  {
>>  	struct gen_pool *sram_pool;
>>  	struct device_node *np;
>>  	struct platform_device *pdev = NULL;
>> +	int ret = -ENODEV;
>>  
>> -	if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
>> -	    (pm_data.suspend_mode != AT91_PM_BACKUP))
>> -		return;
>> +	if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
>> +		return 0;
>>  
>>  	pm_bu = NULL;
>>  
>> -	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
>> -	if (!np) {
>> -		pr_warn("%s: failed to find shdwc!\n", __func__);
>> -		return;
>> -	}
>> -
>> -	pm_data.shdwc = of_iomap(np, 0);
>> -	of_node_put(np);
>> -
>>  	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
>>  	if (!np) {
>>  		pr_warn("%s: failed to find sfrbu!\n", __func__);
>> -		goto sfrbu_fail;
>> +		return ret;
>>  	}
>>  
>>  	pm_data.sfrbu = of_iomap(np, 0);
>> @@ -530,6 +609,7 @@ static void __init at91_pm_backup_init(void)
>>  	pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
>>  	if (!pm_bu) {
>>  		pr_warn("%s: unable to alloc securam!\n", __func__);
>> +		ret = -ENOMEM;
>>  		goto securam_fail;
>>  	}
>>  
>> @@ -537,21 +617,62 @@ static void __init at91_pm_backup_init(void)
>>  	pm_bu->canary = __pa_symbol(&canary);
>>  	pm_bu->resume = __pa_symbol(cpu_resume);
>>  
>> -	return;
>> +	return 0;
>>  
>> -sfrbu_fail:
>> -	iounmap(pm_data.shdwc);
>> -	pm_data.shdwc = NULL;
>>  securam_fail:
>>  	iounmap(pm_data.sfrbu);
>>  	pm_data.sfrbu = NULL;
>> +	return ret;
>> +}
>>  
>> -	if (pm_data.standby_mode == AT91_PM_BACKUP)
>> +static void __init at91_pm_use_default_mode(int pm_mode)
>> +{
>> +	if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
>> +		return;
>> +
>> +	if (pm_data.standby_mode == pm_mode)
>>  		pm_data.standby_mode = AT91_PM_ULP0;
>> -	if (pm_data.suspend_mode == AT91_PM_BACKUP)
>> +	if (pm_data.suspend_mode == pm_mode)
>>  		pm_data.suspend_mode = AT91_PM_ULP0;
>>  }
>>  
>> +static void __init at91_pm_modes_init(void)
>> +{
>> +	struct device_node *np;
>> +	int ret;
>> +
>> +	if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
>> +	    !at91_is_pm_mode_active(AT91_PM_ULP1))
>> +		return;
>> +
>> +	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
>> +	if (!np) {
>> +		pr_warn("%s: failed to find shdwc!\n", __func__);
>> +		goto ulp1_default;
>> +	}
>> +
>> +	pm_data.shdwc = 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;
>> +	}
>> +
>> +	return;
>> +
>> +unmap:
>> +	iounmap(pm_data.shdwc);
>> +	pm_data.shdwc = NULL;
>> +ulp1_default:
>> +	at91_pm_use_default_mode(AT91_PM_ULP1);
>> +backup_default:
>> +	at91_pm_use_default_mode(AT91_PM_BACKUP);
>> +}
>> +
>>  struct pmc_info {
>>  	unsigned long uhp_udp_mask;
>>  };
>> @@ -645,7 +766,7 @@ void __init sama5d2_pm_init(void)
>>  	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
>>  		return;
>>  
>> -	at91_pm_backup_init();
>> +	at91_pm_modes_init();
>>  	sama5_pm_init();
>>  }
>>  
>> -- 
>> 2.7.4
>>
> 

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

* [RESEND PATCH] ARM: at91: pm: configure wakeup sources for ULP1 mode
  2018-07-17  8:26 ` [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode Claudiu Beznea
  2018-07-17 10:45   ` Alexandre Belloni
@ 2018-07-17 11:06   ` Claudiu Beznea
  1 sibling, 0 replies; 9+ messages in thread
From: Claudiu Beznea @ 2018-07-17 11:06 UTC (permalink / raw)
  To: nicolas.ferre, alexandre.belloni, mturquette, sboyd
  Cc: linux, linux-arm-kernel, linux-kernel, linux-clk, Claudiu Beznea

Since for ULP1 PM mode of SAMA5D2 the wakeup sources are limited and
well known add a method to check if these wakeup sources are defined by
user (either via DT or filesystem). In case there are no wakeup sources
defined for ULP1 the PM suspend will fail, otherwise these will be
configured in fast startup registers of PMC. Since wakeup sources of
ULP1 need also to be configured in SHDWC registers the code was a bit
changed to map the SHDWC also in case ULP1 is requested by user (this
was done in the initialization phase). In case the ULP1 initialization
fails the ULP0 mode is used (this mode was also used in case backup mode
initialization failed).

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 arch/arm/mach-at91/pm.c | 168 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 146 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 099d8094018c..e8f3d0f97e61 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -80,6 +80,90 @@ static struct at91_pm_bu {
 	phys_addr_t resume;
 } *pm_bu;
 
+struct wakeup_source_info {
+	unsigned int pmc_fsmr_bit;
+	unsigned int shdwc_mr_bit;
+	bool set_polarity;
+};
+
+static const struct wakeup_source_info ws_info[] = {
+	{ .pmc_fsmr_bit = AT91_PMC_FSTT(10),	.set_polarity = true },
+	{ .pmc_fsmr_bit = AT91_PMC_RTCAL,	.shdwc_mr_bit = BIT(17) },
+	{ .pmc_fsmr_bit = AT91_PMC_USBAL },
+	{ .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
+};
+
+static const struct of_device_id sama5d2_ws_ids[] = {
+	{ .compatible = "atmel,sama5d2-gem",		.data = &ws_info[0] },
+	{ .compatible = "atmel,at91rm9200-rtc",		.data = &ws_info[1] },
+	{ .compatible = "atmel,sama5d3-udc",		.data = &ws_info[2] },
+	{ .compatible = "atmel,at91rm9200-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 = "atmel,sama5d2-sdhci",		.data = &ws_info[3] },
+	{ /* sentinel */ }
+};
+
+static int at91_pm_config_ws(unsigned int pm_mode, bool set)
+{
+	const struct wakeup_source_info *wsi;
+	const struct of_device_id *match;
+	struct platform_device *pdev;
+	struct device_node *np;
+	unsigned int mode = 0, polarity = 0, val = 0;
+
+	if (pm_mode != AT91_PM_ULP1)
+		return 0;
+
+	if (!pm_data.pmc || !pm_data.shdwc)
+		return -EPERM;
+
+	if (!set) {
+		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
+		return 0;
+	}
+
+	/* SHDWC.WUIR */
+	val = readl(pm_data.shdwc + 0x0c);
+	mode |= (val & 0x3ff);
+	polarity |= ((val >> 16) & 0x3ff);
+
+	/* SHDWC.MR */
+	val = readl(pm_data.shdwc + 0x04);
+
+	/* Loop through defined wakeup sources. */
+	for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) {
+		pdev = of_find_device_by_node(np);
+		if (!pdev)
+			continue;
+
+		if (device_may_wakeup(&pdev->dev)) {
+			wsi = match->data;
+
+			/* Check if enabled on SHDWC. */
+			if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
+				goto put_node;
+
+			mode |= wsi->pmc_fsmr_bit;
+			if (wsi->set_polarity)
+				polarity |= wsi->pmc_fsmr_bit;
+		}
+
+put_node:
+		of_node_put(np);
+	}
+
+	if (mode) {
+		writel(mode, pm_data.pmc + AT91_PMC_FSMR);
+		writel(polarity, pm_data.pmc + AT91_PMC_FSPR);
+	} else {
+		pr_err("AT91: PM: no ULP1 wakeup sources found!");
+	}
+
+	return mode ? 0 : -EPERM;
+}
+
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
@@ -98,7 +182,7 @@ static int at91_pm_begin(suspend_state_t state)
 		pm_data.mode = -1;
 	}
 
-	return 0;
+	return at91_pm_config_ws(pm_data.mode, true);
 }
 
 /*
@@ -234,6 +318,7 @@ static int at91_pm_enter(suspend_state_t state)
  */
 static void at91_pm_end(void)
 {
+	at91_pm_config_ws(pm_data.mode, false);
 }
 
 
@@ -479,31 +564,28 @@ static void __init at91_pm_sram_init(void)
 			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
 }
 
-static void __init at91_pm_backup_init(void)
+static bool __init at91_is_pm_mode_active(int pm_mode)
+{
+	return (pm_data.standby_mode == pm_mode ||
+		pm_data.suspend_mode == pm_mode);
+}
+
+static int __init at91_pm_backup_init(void)
 {
 	struct gen_pool *sram_pool;
 	struct device_node *np;
 	struct platform_device *pdev = NULL;
+	int ret = -ENODEV;
 
-	if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
-	    (pm_data.suspend_mode != AT91_PM_BACKUP))
-		return;
+	if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
+		return 0;
 
 	pm_bu = NULL;
 
-	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
-	if (!np) {
-		pr_warn("%s: failed to find shdwc!\n", __func__);
-		return;
-	}
-
-	pm_data.shdwc = of_iomap(np, 0);
-	of_node_put(np);
-
 	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
 	if (!np) {
 		pr_warn("%s: failed to find sfrbu!\n", __func__);
-		goto sfrbu_fail;
+		return ret;
 	}
 
 	pm_data.sfrbu = of_iomap(np, 0);
@@ -530,6 +612,7 @@ static void __init at91_pm_backup_init(void)
 	pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
 	if (!pm_bu) {
 		pr_warn("%s: unable to alloc securam!\n", __func__);
+		ret = -ENOMEM;
 		goto securam_fail;
 	}
 
@@ -537,21 +620,62 @@ static void __init at91_pm_backup_init(void)
 	pm_bu->canary = __pa_symbol(&canary);
 	pm_bu->resume = __pa_symbol(cpu_resume);
 
-	return;
+	return 0;
 
-sfrbu_fail:
-	iounmap(pm_data.shdwc);
-	pm_data.shdwc = NULL;
 securam_fail:
 	iounmap(pm_data.sfrbu);
 	pm_data.sfrbu = NULL;
+	return ret;
+}
 
-	if (pm_data.standby_mode == AT91_PM_BACKUP)
+static void __init at91_pm_use_default_mode(int pm_mode)
+{
+	if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
+		return;
+
+	if (pm_data.standby_mode == pm_mode)
 		pm_data.standby_mode = AT91_PM_ULP0;
-	if (pm_data.suspend_mode == AT91_PM_BACKUP)
+	if (pm_data.suspend_mode == pm_mode)
 		pm_data.suspend_mode = AT91_PM_ULP0;
 }
 
+static void __init at91_pm_modes_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
+	    !at91_is_pm_mode_active(AT91_PM_ULP1))
+		return;
+
+	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
+	if (!np) {
+		pr_warn("%s: failed to find shdwc!\n", __func__);
+		goto ulp1_default;
+	}
+
+	pm_data.shdwc = 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;
+	}
+
+	return;
+
+unmap:
+	iounmap(pm_data.shdwc);
+	pm_data.shdwc = NULL;
+ulp1_default:
+	at91_pm_use_default_mode(AT91_PM_ULP1);
+backup_default:
+	at91_pm_use_default_mode(AT91_PM_BACKUP);
+}
+
 struct pmc_info {
 	unsigned long uhp_udp_mask;
 };
@@ -645,7 +769,7 @@ void __init sama5d2_pm_init(void)
 	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
 		return;
 
-	at91_pm_backup_init();
+	at91_pm_modes_init();
 	sama5_pm_init();
 }
 
-- 
2.7.4


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

* Re: [PATCH 0/4] rework ULP1 patches
  2018-07-17  8:26 [PATCH 0/4] rework ULP1 patches Claudiu Beznea
                   ` (3 preceding siblings ...)
  2018-07-17  8:26 ` [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode Claudiu Beznea
@ 2018-07-17 19:16 ` Alexandre Belloni
  4 siblings, 0 replies; 9+ messages in thread
From: Alexandre Belloni @ 2018-07-17 19:16 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: nicolas.ferre, linux, mturquette, sboyd, linux-arm-kernel,
	linux-kernel, linux-clk

On 17/07/2018 11:26:53+0300, Claudiu Beznea wrote:
> Hi,
> 
> Based on the discussion at [1] and private discussion I had with Alexandre
> Belloni on IRC, I reworked ULP1 patches to remove device tree bindings
> proposed in [1].
> 
> The implementation from this patches (mostly patch 4/4) is using
> device_may_wakeup() API that current Linux code provides and the fact that
> for the ULP1 the wakeup souces are known and well defined.
> Basically, this rework (mostly patch 4/4) loops through well defined ULP1
> wakeup sources and check if those wakeup sources were configured to wake
> up the system (vid DT or sysfs) and, based on that (and in case of RTC,
> based on SHDWC.MR), set the PMC fast startup mode and polarity registers.
> In [1] PMC fast startup mode and polarity registers were configured by
> introducing new DT bindings.
> 
> Since with these patches SHDWC registers are used in ULP1 wakeup sources
> configuration the patch 4/4 changed a bit the PM initialization phase for
> SAMA5D2 in order to have mapped also the SHDWC in case ULP1 needs to be
> initialized. In case ULP1 configuration fails the ULP0 mode is used (same
> approach as in backup mode case).
> 
> I measure the delay introduced in suspend sequence by using an oscilloscope
> connected to a GPIO and calling gpio_direction_output(PIN, 0) at the beginning
> of at91_pm_config_ws() and gpio_direction_output(PIN, 1) at the end of
> at91_pm_config_ws(). With these I measureed on oscilloscope the difference
> b/w the front changes. The measured time was *1.56ms*. Keep in mind that
> gpio_direction_output() will call, in the end,
> atmel_gpio_direction_output() which access 4 registers to toggle the PIN
> (in at91_pm_config_ws() there are also 4 peripheral register accesses).
> 
> Besides this rework, I took the chance and I appended few other patches to
> this series, based on Wenyou Yang's previous work, related to ULP modes.
> 
> Patch 1/4: replaces slow clock with ULP0
> Patch 2/4: is the Wenyou's patch wich adds ULP1 support
> Patch 3/4: is defining PMC fast startup registers
> 
> The patches were based on v4.18-rc1.
> 
> [1] https://patchwork.kernel.org/patch/8595091/
> 
> Claudiu Beznea (3):
>   ARM: at91: pm: Use ULP0 naming instead of slow clock
>   ARM: at91: pm: add PMC fast startup registers defines
>   ARM: at91: pm: configure wakeup sources for ULP1 mode
> 
> Wenyou Yang (1):
>   ARM: at91: pm: Add ULP1 mode support
> 
>  arch/arm/mach-at91/pm.c         | 184 +++++++++++++++++++++++++++++++++-------
>  arch/arm/mach-at91/pm.h         |   6 +-
>  arch/arm/mach-at91/pm_suspend.S | 142 ++++++++++++++++++++++++++-----
>  include/linux/clk/at91_pmc.h    |  15 ++++
>  4 files changed, 294 insertions(+), 53 deletions(-)
> 

Applied, thanks.

-- 
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

end of thread, other threads:[~2018-07-17 19:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-17  8:26 [PATCH 0/4] rework ULP1 patches Claudiu Beznea
2018-07-17  8:26 ` [PATCH 1/4] ARM: at91: pm: Use ULP0 naming instead of slow clock Claudiu Beznea
2018-07-17  8:26 ` [PATCH 2/4] ARM: at91: pm: Add ULP1 mode support Claudiu Beznea
2018-07-17  8:26 ` [PATCH 3/4] ARM: at91: pm: add PMC fast startup registers defines Claudiu Beznea
2018-07-17  8:26 ` [PATCH 4/4] ARM: at91: pm: configure wakeup sources for ULP1 mode Claudiu Beznea
2018-07-17 10:45   ` Alexandre Belloni
2018-07-17 10:49     ` Claudiu Beznea
2018-07-17 11:06   ` [RESEND PATCH] " Claudiu Beznea
2018-07-17 19:16 ` [PATCH 0/4] rework ULP1 patches Alexandre Belloni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).