Hi, On Wed, Oct 26, 2016 at 02:10:31PM +0200, Antoine Tenart wrote: > Add the suspend psci function for sun5i and sun7i. Thus function > switches the cpu clk source to osc24M or to losc depending on the > SoC family. > > Signed-off-by: Antoine Tenart <antoine.ten...@free-electrons.com> > --- > arch/arm/cpu/armv7/sunxi/Makefile | 9 ++- > arch/arm/cpu/armv7/sunxi/psci.c | 2 +- > arch/arm/cpu/armv7/sunxi/psci_suspend.c | 108 > ++++++++++++++++++++++++++ > arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 6 ++ > 4 files changed, 123 insertions(+), 2 deletions(-) > create mode 100644 arch/arm/cpu/armv7/sunxi/psci_suspend.c > > diff --git a/arch/arm/cpu/armv7/sunxi/Makefile > b/arch/arm/cpu/armv7/sunxi/Makefile > index b35b9df4a9d6..80667268a0fc 100644 > --- a/arch/arm/cpu/armv7/sunxi/Makefile > +++ b/arch/arm/cpu/armv7/sunxi/Makefile > @@ -13,7 +13,14 @@ obj-$(CONFIG_MACH_SUN6I) += tzpc.o > obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o > > ifndef CONFIG_SPL_BUILD > -obj-$(CONFIG_ARMV7_PSCI) += psci.o > +ifdef CONFIG_ARMV7_PSCI > +obj-$(CONFIG_MACH_SUN6I) += psci.o > +obj-$(CONFIG_MACH_SUN7I) += psci.o > +obj-$(CONFIG_MACH_SUN8I) += psci.o > + > +obj-$(CONFIG_MACH_SUN5I) += psci_suspend.o > +obj-$(CONFIG_MACH_SUN7I) += psci_suspend.o > +endif > endif > > ifdef CONFIG_SPL_BUILD > diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c > index 766b8c79d93d..4525bc7bf26b 100644 > --- a/arch/arm/cpu/armv7/sunxi/psci.c > +++ b/arch/arm/cpu/armv7/sunxi/psci.c > @@ -48,7 +48,7 @@ static u32 __secure cp15_read_cntp_ctl(void) > > #define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000) > > -static void __secure __mdelay(u32 ms) > +void __secure __mdelay(u32 ms) > { > u32 reg = ONE_MS * ms; > > diff --git a/arch/arm/cpu/armv7/sunxi/psci_suspend.c > b/arch/arm/cpu/armv7/sunxi/psci_suspend.c > new file mode 100644 > index 000000000000..e5c000ff2d3d > --- /dev/null > +++ b/arch/arm/cpu/armv7/sunxi/psci_suspend.c > @@ -0,0 +1,108 @@ > +/* > + * Copyright (C) 2016 Antoine Tenart <antoine.ten...@free-electrons.com> > + * > + * Based on Allwinner code. > + * Copyright 2007-2012 (C) Allwinner Technology Co., Ltd. > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > +#include <config.h> > +#include <common.h> > + > +#include <asm/atomic.h> > +#include <asm/arch/clock.h> > +#include <asm/arch/dram.h> > +#include <asm/armv7.h> > +#include <asm/io.h> > +#include <asm/psci.h> > +#include <asm/secure.h> > +#include <asm/system.h> > + > +#include <linux/bitops.h> > + > +void __mdelay(u32); > + > +#if defined(CONFIG_MACH_SUN5I) > +#define NR_CPUS 1 > +#elif defined(CONFIG_MACH_SUN7I) > +#define NR_CPUS 2 > +#endif > + > +/* > + * The PSCI suspend function switch cpuclk to another source and disable > + * pll1. As this function is called per-CPU, it should only do this when > + * all the CPUs are in idle state. > + * > + * The 'cnt' variable keeps track of the number of CPU which are in the idle > + * state. The last one setup cpuclk for idle. > + * > + * The 'clk_state' varibale holds the cpu clk state (idle or normal). > + */ > +atomic_t __secure_data cnt, clk_state; > + > +#define CLK_NORMAL 0 > +#define CLK_IDLE 1 > + > +static void __secure sunxi_clock_enter_idle(struct sunxi_ccm_reg *ccm) > +{ > + /* switch cpuclk to osc24m */ > + clrsetbits_le32(&ccm->cpu_ahb_apb0_cfg, 0x3 << CPU_CLK_SRC_SHIFT, > + CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT); > + > + /* disable pll1 */ > + clrbits_le32(&ccm->pll1_cfg, CCM_PLL1_CTRL_EN); > + > +#ifndef CONFIG_MACH_SUN7I > + /* switch cpuclk to losc */ > + clrbits_le32(&ccm->cpu_ahb_apb0_cfg, 0x3 << CPU_CLK_SRC_SHIFT); > +#endif
Some kind of comment here would be nice. > + > + /* disable ldo */ > + clrbits_le32(&ccm->osc24m_cfg, OSC24M_LDO_EN); I realise I'm the one who suggested doing this, but that might turn out to be wrong. Have you tested devices that use the oscillator directly, like the PWM? > +} > + > +static void __secure sunxi_clock_leave_idle(struct sunxi_ccm_reg *ccm) > +{ > + /* enable ldo */ > + setbits_le32(&ccm->osc24m_cfg, OSC24M_LDO_EN); > + > +#ifndef CONFIG_MACH_SUN7I > + /* switch cpuclk to osc24m */ > + clrsetbits_le32(&ccm->cpu_ahb_apb0_cfg, 0x3 << CPU_CLK_SRC_SHIFT, > + CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT); > +#endif > + > + /* enable pll1 */ > + setbits_le32(&ccm->pll1_cfg, CCM_PLL1_CTRL_EN); It might be worth waiting for the PLL to lock by polling the bit 28 before switching the mux to it. > + > + /* switch cpuclk to pll1 */ > + clrsetbits_le32(&ccm->cpu_ahb_apb0_cfg, 0x3 << CPU_CLK_SRC_SHIFT, > + CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT); > +} > + > +void __secure psci_cpu_suspend(void) > +{ > + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; > + > + if (atomic_inc_return(&cnt) == NR_CPUS) { > + /* wait for any sunxi_clock_leave_idle() to finish */ > + while (atomic_read(&clk_state) != CLK_NORMAL) > + __mdelay(1); > + > + sunxi_clock_enter_idle(ccm); > + atomic_set(&clk_state, CLK_IDLE); > + } > + > + /* idle */ > + DSB; > + wfi(); > + > + if (atomic_dec_return(&cnt) == NR_CPUS - 1) { > + /* wait for any sunxi_clock_enter_idle() to finish */ > + while (atomic_read(&clk_state) != CLK_IDLE) > + __mdelay(1); > + > + sunxi_clock_leave_idle(ccm); > + atomic_set(&clk_state, CLK_NORMAL); > + } > +} > diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h > b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h > index d1c5ad0a739b..0d7df5bba543 100644 > --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h > +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h > @@ -90,6 +90,10 @@ struct sunxi_ccm_reg { > u32 gmac_clk_cfg; /* 0x164 */ > }; > > +/* osc24m_cfg bit field */ > +#define OSC24M_EN (0x1 << 0) > +#define OSC24M_LDO_EN (0x1 << 16) > + > /* apb1 bit field */ > #define APB1_CLK_SRC_OSC24M (0x0 << 24) > #define APB1_CLK_SRC_PLL6 (0x1 << 24) > @@ -208,6 +212,8 @@ struct sunxi_ccm_reg { > #define CCM_AHB_GATE_DLL (0x1 << 15) > #define CCM_AHB_GATE_ACE (0x1 << 16) > > +#define CCM_PLL1_CTRL_EN (0x1 << 31) > + > #define CCM_PLL3_CTRL_M_SHIFT 0 > #define CCM_PLL3_CTRL_M_MASK (0x7f << CCM_PLL3_CTRL_M_SHIFT) > #define CCM_PLL3_CTRL_M(n) (((n) & 0x7f) << 0) > -- > 2.10.1 Looks good otherwise, Thanks! Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
signature.asc
Description: PGP signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot