From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753122AbbJON3w (ORCPT ); Thu, 15 Oct 2015 09:29:52 -0400 Received: from down.free-electrons.com ([37.187.137.238]:35859 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752690AbbJON3v (ORCPT ); Thu, 15 Oct 2015 09:29:51 -0400 Date: Thu, 15 Oct 2015 15:22:04 +0200 From: Alexandre Belloni To: Wenyou Yang Cc: Nicolas Ferre , Jean-Christophe Plagniol-Villard , Russell King , Stephen Boyd , Michael Turquette , 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 Message-ID: <20151015132204.GC3421@piout.net> References: <1444880467-18598-1-git-send-email-wenyou.yang@atmel.com> <1444880467-18598-3-git-send-email-wenyou.yang@atmel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1444880467-18598-3-git-send-email-wenyou.yang@atmel.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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