diff options
author | Oleksij Rempel <o.rempel@pengutronix.de> | 2017-07-07 10:04:00 +0200 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2017-07-07 16:50:57 +0200 |
commit | 1e9458720a2379f65cb9b50b2e9214f6790ad84c (patch) | |
tree | 240f31eca68f510dd56865f78200a445b0d8edcd /arch | |
parent | e16c539d9479aeb0d7e9ce9b4345e8c335dd485a (diff) | |
download | barebox-1e9458720a2379f65cb9b50b2e9214f6790ad84c.tar.gz barebox-1e9458720a2379f65cb9b50b2e9214f6790ad84c.tar.xz |
ARM: i.MX: provide handler for power off over standby
One of the Freescale recommended sequences for power off with external
PMIC is the following:
...
3. SoC is programming PMIC for power off when standby is asserted.
4. In CCM STOP mode, Standby is asserted, PMIC gates SoC supplies.
See:
http://www.nxp.com/assets/documents/data/en/reference-manuals/IMX6DQRM.pdf
page 5083
This patch implements step 4. of this sequence.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/imx6.c | 49 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx6.h | 1 |
2 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index 5afbf6b30f..96c1f64093 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -25,6 +25,19 @@ #include <asm/mmu.h> #include <asm/cache-l2x0.h> +#include <poweroff.h> +#include <mach/imx6-regs.h> +#include <io.h> + +#define CLPCR 0x54 +#define BP_CLPCR_LPM(mode) ((mode) & 0x3) +#define BM_CLPCR_LPM (0x3 << 0) +#define BM_CLPCR_SBYOS (0x1 << 6) +#define BM_CLPCR_VSTBY (0x1 << 8) +#define BP_CLPCR_STBY_COUNT 9 +#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) + void imx6_init_lowlevel(void) { void __iomem *aips1 = (void *)MX6_AIPS1_ON_BASE_ADDR; @@ -296,3 +309,39 @@ static int imx6_fixup_cpus_register(void) return of_register_fixup(imx6_fixup_cpus, NULL); } device_initcall(imx6_fixup_cpus_register); + +void __noreturn imx6_pm_stby_poweroff(void) +{ + void *ccm_base = IOMEM(MX6_CCM_BASE_ADDR); + void *gpc_base = IOMEM(MX6_GPC_BASE_ADDR); + u32 val; + + /* + * All this is done to get the PMIC_STBY_REQ line high which will + * cause the PMIC to turn off the i.MX6. + */ + + /* + * First mask all interrupts in the GPC. This is necessary for + * unknown reasons + */ + writel(0xffffffff, gpc_base + 0x8); + writel(0xffffffff, gpc_base + 0xc); + writel(0xffffffff, gpc_base + 0x10); + writel(0xffffffff, gpc_base + 0x14); + + val = readl(ccm_base + CLPCR); + + val &= ~BM_CLPCR_LPM; + val |= BP_CLPCR_LPM(2); + val |= 0x3 << BP_CLPCR_STBY_COUNT; + val |= BM_CLPCR_VSTBY; + val |= BM_CLPCR_SBYOS; + val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; + + writel(val, ccm_base + CLPCR); + + asm("wfi"); + + while(1); +} diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h index 6ad53433cb..e4633ed5f2 100644 --- a/arch/arm/mach-imx/include/mach/imx6.h +++ b/arch/arm/mach-imx/include/mach/imx6.h @@ -7,6 +7,7 @@ #include <mach/revision.h> void imx6_init_lowlevel(void); +void __noreturn imx6_pm_stby_poweroff(void); #define IMX6_ANATOP_SI_REV 0x260 #define IMX6SL_ANATOP_SI_REV 0x280 |