All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
To: Wenyou Yang <wenyou.yang@atmel.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>,
	Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>,
	Russell King <linux@arm.linux.org.uk>,
	Stephen Boyd <sboyd@codeaurora.org>,
	Michael Turquette <mturquette@baylibre.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org
Subject: Re: [PATCH 2/2] ARM: at91/pm: add ultra Low-power mode 1(ULP1) support
Date: Thu, 15 Oct 2015 15:22:04 +0200	[thread overview]
Message-ID: <20151015132204.GC3421@piout.net> (raw)
In-Reply-To: <1444880467-18598-3-git-send-email-wenyou.yang@atmel.com>

Hello Wenyou,

On 15/10/2015 at 11:41:07 +0800, Wenyou Yang wrote :
> +#define ULP0_MODE      0x00
> +#define ULP1_MODE      0x11

Those are not used.

> +static void at91_config_ulp1_wkup_source(void)
> +{
> +	if (at91_pmc_read(AT91_PMC_VERSION) >= SAMA5D2_PMC_VERSION) {
> +		at91_pmc_write(AT91_PMC_FSMR, AT91_PMC_RTCAL |
> +					      AT91_PMC_FSTT9 |
> +					      AT91_PMC_FSTT8 |
> +					      AT91_PMC_FSTT7 |
> +					      AT91_PMC_FSTT6 |
> +					      AT91_PMC_FSTT5 |
> +					      AT91_PMC_FSTT4 |
> +					      AT91_PMC_FSTT3 |
> +					      AT91_PMC_FSTT2 |
> +					      AT91_PMC_FSTT0);
> +
> +		at91_pmc_write(AT91_PMC_FSPR, 0);

Shouldn't those be configured from irq_set_wake() in the aic driver
instead of activating all the wakeup sources?
I think you need to get the PMC syscon from the aic5 driver and
implement a new irq_set_wake function when you can find the sam5d2 pmc.

The PMC syscon is introduced with that series:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-October/376493.html

> @@ -140,6 +165,10 @@ static void at91_pm_suspend(suspend_state_t state)
>  	pm_data |= (state == PM_SUSPEND_MEM) ?
>  				AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
>  
> +	pm_data |= ((state == PM_SUSPEND_MEM) &&
> +		    (at91_pmc_read(AT91_PMC_VERSION) >= SAMA5D2_PMC_VERSION)) ?
> +		    AT91_PM_ULP(AT91_PM_ULP1_MODE) : 0;
> +

I would prefer not relying on the AT91_PMC_VERSION. Also, you probably
shouldn't read the register each time you go to suspend.
Finally, this could be better written by testing state only once.


>  	flush_cache_all();
>  	outer_disable();
>  
> diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
> index 3fcf881..2e76745 100644
> --- a/arch/arm/mach-at91/pm.h
> +++ b/arch/arm/mach-at91/pm.h
> @@ -39,4 +39,11 @@ extern void __iomem *at91_ramc_base[];
>  
>  #define	AT91_PM_SLOW_CLOCK	0x01
>  
> +#define AT91_PM_ULP_OFFSET	5
> +#define AT91_PM_ULP_MASK	0x03
> +#define AT91_PM_ULP(x)		(((x) & AT91_PM_ULP_MASK) << AT91_PM_ULP_OFFSET)
> +
> +#define AT91_PM_ULP0_MODE	0x00
> +#define AT91_PM_ULP1_MODE	0x01
> +
>  #endif
> diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
> index 825347b..543c430 100644
> --- a/arch/arm/mach-at91/pm_suspend.S
> +++ b/arch/arm/mach-at91/pm_suspend.S
> @@ -41,6 +41,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
> @@ -99,6 +108,10 @@ ENTRY(at91_pm_suspend_in_sram)
>  	and	r0, r0, #AT91_PM_MODE_MASK
>  	str	r0, .pm_mode
>  
> +	lsr	r0, r3, #AT91_PM_ULP_OFFSET
> +	and	r0, r0, #AT91_PM_ULP_MASK
> +	str	r0, .ulp_mode
> +
>  	/* Active the self-refresh mode */
>  	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
>  	bl	at91_sramc_self_refresh
> @@ -107,6 +120,14 @@ ENTRY(at91_pm_suspend_in_sram)
>  	tst	r0, #AT91_PM_SLOW_CLOCK
>  	beq	standby_mode
>  
> +	ldr	r0, .ulp_mode
> +	tst	r0, #AT91_PM_ULP1_MODE
> +	beq	ulp0_mode
> +
> +ulp1_mode:
> +	bl	at91_pm_ulp1_mode
> +	b	pm_exit
> +
>  ulp0_mode:
>  	bl	at91_pm_ulp0_mode
>  	b	pm_exit
> @@ -313,6 +334,94 @@ ENTRY(at91_pm_ulp0_mode)
>  	mov	pc, lr
>  ENDPROC(at91_pm_ulp0_mode)
>  
> +/*
> + * void at91_pm_ulp1_mode(void)
> + *
> + */
> +ENTRY(at91_pm_ulp1_mode)
> +	ldr	pmc, .pmc_base
> +
> +	/* Save PMC_MCKR config */
> +	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
> +	str	tmp1, .saved_mckr
> +
> +	/* Switch the master clock source to main clock */
> +	bic	tmp1, tmp1, #AT91_PMC_CSS
> +	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
> +	str	tmp1, [pmc, #AT91_PMC_MCKR]
> +
> +	wait_mckrdy
> +
> +	/* Save PLLA config, then and disable PLLA */
> +	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
> +	str	tmp1, .saved_pllar
> +
> +	bic	tmp1, tmp1, #AT91_PMC3_MUL
> +	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
> +
> +	/* Switch main clock 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_moscsels
> +
> +	/* Disable the main 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	/* Enter the ULP1 mode by setting 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_mckrdy
> +
> +	/* Enable the main 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_moscrdy
> +
> +	/* Switch main clock to the main 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_moscsels
> +
> +	/* Restore PLLA config */
> +	ldr	tmp1, .saved_pllar
> +	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
> +
> +	wait_pllalock
> +
> +	/* Restore PMC_MCKR config */
> +	ldr	tmp1, .saved_mckr
> +	str	tmp1, [pmc, #AT91_PMC_MCKR]
> +
> +	wait_mckrdy
> +
> +	mov	pc, lr
> +ENDPROC(at91_pm_ulp1_mode)
> +

This makes a lot of duplication anyway, why not having separate code for
ULP0 and ULP1 that would be copied in SRAM? This would avoid the test on .ulp_mode

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

WARNING: multiple messages have this Message-ID (diff)
From: alexandre.belloni@free-electrons.com (Alexandre Belloni)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] ARM: at91/pm: add ultra Low-power mode 1(ULP1) support
Date: Thu, 15 Oct 2015 15:22:04 +0200	[thread overview]
Message-ID: <20151015132204.GC3421@piout.net> (raw)
In-Reply-To: <1444880467-18598-3-git-send-email-wenyou.yang@atmel.com>

Hello Wenyou,

On 15/10/2015 at 11:41:07 +0800, Wenyou Yang wrote :
> +#define ULP0_MODE      0x00
> +#define ULP1_MODE      0x11

Those are not used.

> +static void at91_config_ulp1_wkup_source(void)
> +{
> +	if (at91_pmc_read(AT91_PMC_VERSION) >= SAMA5D2_PMC_VERSION) {
> +		at91_pmc_write(AT91_PMC_FSMR, AT91_PMC_RTCAL |
> +					      AT91_PMC_FSTT9 |
> +					      AT91_PMC_FSTT8 |
> +					      AT91_PMC_FSTT7 |
> +					      AT91_PMC_FSTT6 |
> +					      AT91_PMC_FSTT5 |
> +					      AT91_PMC_FSTT4 |
> +					      AT91_PMC_FSTT3 |
> +					      AT91_PMC_FSTT2 |
> +					      AT91_PMC_FSTT0);
> +
> +		at91_pmc_write(AT91_PMC_FSPR, 0);

Shouldn't those be configured from irq_set_wake() in the aic driver
instead of activating all the wakeup sources?
I think you need to get the PMC syscon from the aic5 driver and
implement a new irq_set_wake function when you can find the sam5d2 pmc.

The PMC syscon is introduced with that series:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-October/376493.html

> @@ -140,6 +165,10 @@ static void at91_pm_suspend(suspend_state_t state)
>  	pm_data |= (state == PM_SUSPEND_MEM) ?
>  				AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
>  
> +	pm_data |= ((state == PM_SUSPEND_MEM) &&
> +		    (at91_pmc_read(AT91_PMC_VERSION) >= SAMA5D2_PMC_VERSION)) ?
> +		    AT91_PM_ULP(AT91_PM_ULP1_MODE) : 0;
> +

I would prefer not relying on the AT91_PMC_VERSION. Also, you probably
shouldn't read the register each time you go to suspend.
Finally, this could be better written by testing state only once.


>  	flush_cache_all();
>  	outer_disable();
>  
> diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
> index 3fcf881..2e76745 100644
> --- a/arch/arm/mach-at91/pm.h
> +++ b/arch/arm/mach-at91/pm.h
> @@ -39,4 +39,11 @@ extern void __iomem *at91_ramc_base[];
>  
>  #define	AT91_PM_SLOW_CLOCK	0x01
>  
> +#define AT91_PM_ULP_OFFSET	5
> +#define AT91_PM_ULP_MASK	0x03
> +#define AT91_PM_ULP(x)		(((x) & AT91_PM_ULP_MASK) << AT91_PM_ULP_OFFSET)
> +
> +#define AT91_PM_ULP0_MODE	0x00
> +#define AT91_PM_ULP1_MODE	0x01
> +
>  #endif
> diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
> index 825347b..543c430 100644
> --- a/arch/arm/mach-at91/pm_suspend.S
> +++ b/arch/arm/mach-at91/pm_suspend.S
> @@ -41,6 +41,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
> @@ -99,6 +108,10 @@ ENTRY(at91_pm_suspend_in_sram)
>  	and	r0, r0, #AT91_PM_MODE_MASK
>  	str	r0, .pm_mode
>  
> +	lsr	r0, r3, #AT91_PM_ULP_OFFSET
> +	and	r0, r0, #AT91_PM_ULP_MASK
> +	str	r0, .ulp_mode
> +
>  	/* Active the self-refresh mode */
>  	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
>  	bl	at91_sramc_self_refresh
> @@ -107,6 +120,14 @@ ENTRY(at91_pm_suspend_in_sram)
>  	tst	r0, #AT91_PM_SLOW_CLOCK
>  	beq	standby_mode
>  
> +	ldr	r0, .ulp_mode
> +	tst	r0, #AT91_PM_ULP1_MODE
> +	beq	ulp0_mode
> +
> +ulp1_mode:
> +	bl	at91_pm_ulp1_mode
> +	b	pm_exit
> +
>  ulp0_mode:
>  	bl	at91_pm_ulp0_mode
>  	b	pm_exit
> @@ -313,6 +334,94 @@ ENTRY(at91_pm_ulp0_mode)
>  	mov	pc, lr
>  ENDPROC(at91_pm_ulp0_mode)
>  
> +/*
> + * void at91_pm_ulp1_mode(void)
> + *
> + */
> +ENTRY(at91_pm_ulp1_mode)
> +	ldr	pmc, .pmc_base
> +
> +	/* Save PMC_MCKR config */
> +	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
> +	str	tmp1, .saved_mckr
> +
> +	/* Switch the master clock source to main clock */
> +	bic	tmp1, tmp1, #AT91_PMC_CSS
> +	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
> +	str	tmp1, [pmc, #AT91_PMC_MCKR]
> +
> +	wait_mckrdy
> +
> +	/* Save PLLA config, then and disable PLLA */
> +	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
> +	str	tmp1, .saved_pllar
> +
> +	bic	tmp1, tmp1, #AT91_PMC3_MUL
> +	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
> +
> +	/* Switch main clock 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_moscsels
> +
> +	/* Disable the main 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	/* Enter the ULP1 mode by setting 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_mckrdy
> +
> +	/* Enable the main 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_moscrdy
> +
> +	/* Switch main clock to the main 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
> +	bic	tmp1, tmp1, #(7 << 4)
> +	str	tmp1, [pmc, #AT91_CKGR_MOR]
> +
> +	wait_moscsels
> +
> +	/* Restore PLLA config */
> +	ldr	tmp1, .saved_pllar
> +	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
> +
> +	wait_pllalock
> +
> +	/* Restore PMC_MCKR config */
> +	ldr	tmp1, .saved_mckr
> +	str	tmp1, [pmc, #AT91_PMC_MCKR]
> +
> +	wait_mckrdy
> +
> +	mov	pc, lr
> +ENDPROC(at91_pm_ulp1_mode)
> +

This makes a lot of duplication anyway, why not having separate code for
ULP0 and ULP1 that would be copied in SRAM? This would avoid the test on .ulp_mode

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

  parent reply	other threads:[~2015-10-15 13:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-15  3:41 [PATCH 0/2] ARM: at91/pm: add ULP1 support Wenyou Yang
2015-10-15  3:41 ` Wenyou Yang
2015-10-15  3:41 ` [PATCH 1/2] ARM: at91/pm: move enter sleep code to a procedure Wenyou Yang
2015-10-15  3:41   ` Wenyou Yang
2015-10-15  3:41 ` [PATCH 2/2] ARM: at91/pm: add ultra Low-power mode 1(ULP1) support Wenyou Yang
2015-10-15  3:41   ` Wenyou Yang
2015-10-15  9:31   ` Michael Turquette
2015-10-15  9:31     ` Michael Turquette
2015-10-15  9:31     ` Michael Turquette
2015-10-15 13:22   ` Alexandre Belloni [this message]
2015-10-15 13:22     ` Alexandre Belloni
2015-10-23  1:53     ` Yang, Wenyou
2015-10-23  1:53       ` Yang, Wenyou
2015-10-23  1:53       ` Yang, Wenyou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151015132204.GC3421@piout.net \
    --to=alexandre.belloni@free-electrons.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=mturquette@baylibre.com \
    --cc=nicolas.ferre@atmel.com \
    --cc=plagnioj@jcrosoft.com \
    --cc=sboyd@codeaurora.org \
    --cc=wenyou.yang@atmel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.