/* * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "regs-clkctrl.h" #include "regs-pinctrl.h" #include #include #include #include #include "regs-dram.h" #include "sleep.h" #define PENDING_IRQ_RETRY 100 static void *saved_sram; static int saved_sleep_state; #define WAIT_DC_OK_CYCLES 24000 #define WAIT_CYCLE(n) for (i = 0; i < n; i++); #define LOWER_VDDIO 10 #define LOWER_VDDA 9 #define LOWER_VDDD 8 #define MAX_POWEROFF_CODE_SIZE (6 * 1024) #define REGS_CLKCTRL_BASE IO_ADDRESS(CLKCTRL_PHYS_ADDR) static void mx23_standby(void) { int i; u32 reg_vddd, reg_vdda, reg_vddio; /* DDR EnterSelfrefreshMode */ __raw_writel( BF_DRAM_CTL16_LOWPOWER_AUTO_ENABLE(0x2) | __raw_readl(IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL16), IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL16); __raw_writel( BF_DRAM_CTL16_LOWPOWER_CONTROL(0x2) | __raw_readl(IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL16), IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL16); /* Gating EMI CLock */ __raw_writel(BM_CLKCTRL_EMI_CLKGATE | __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI), REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI); /* Disable PLL */ __raw_writel(BM_CLKCTRL_PLLCTRL0_POWER, REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0_CLR); /* Reduce the VDDIO (3.050 volt) */ reg_vddio = __raw_readl(REGS_POWER_BASE + HW_POWER_VDDIOCTRL); __raw_writel(reg_vddio | BM_POWER_VDDIOCTRL_BO_OFFSET, REGS_POWER_BASE + HW_POWER_VDDIOCTRL); __raw_writel((__raw_readl(REGS_POWER_BASE + HW_POWER_VDDIOCTRL) & ~BM_POWER_VDDIOCTRL_TRG) | LOWER_VDDIO, REGS_POWER_BASE + HW_POWER_VDDIOCTRL); WAIT_CYCLE(WAIT_DC_OK_CYCLES) while (!(__raw_readl(REGS_POWER_BASE + HW_POWER_STS) & BM_POWER_STS_DC_OK)) ; /* Reduce VDDA 1.725volt */ reg_vdda = __raw_readl(REGS_POWER_BASE + HW_POWER_VDDACTRL); __raw_writel(reg_vdda | BM_POWER_VDDACTRL_BO_OFFSET, REGS_POWER_BASE + HW_POWER_VDDACTRL); __raw_writel((__raw_readl(REGS_POWER_BASE + HW_POWER_VDDACTRL) & ~BM_POWER_VDDACTRL_TRG) | LOWER_VDDA, REGS_POWER_BASE + HW_POWER_VDDACTRL); WAIT_CYCLE(WAIT_DC_OK_CYCLES) /* wait for DC_OK */ while (!(__raw_readl(REGS_POWER_BASE + HW_POWER_STS) & BM_POWER_STS_DC_OK)) ; /* Reduce VDDD 1.000 volt */ reg_vddd = __raw_readl(REGS_POWER_BASE + HW_POWER_VDDDCTRL); __raw_writel(reg_vddd | BM_POWER_VDDDCTRL_BO_OFFSET, REGS_POWER_BASE + HW_POWER_VDDDCTRL); __raw_writel((__raw_readl(REGS_POWER_BASE + HW_POWER_VDDDCTRL) & ~BM_POWER_VDDDCTRL_TRG) | LOWER_VDDD, REGS_POWER_BASE + HW_POWER_VDDDCTRL); WAIT_CYCLE(WAIT_DC_OK_CYCLES) while (!(__raw_readl(REGS_POWER_BASE + HW_POWER_STS) & BM_POWER_STS_DC_OK)) ; /* optimize the DCDC loop gain */ __raw_writel((__raw_readl(REGS_POWER_BASE + HW_POWER_LOOPCTRL) & ~BM_POWER_LOOPCTRL_EN_RCSCALE), REGS_POWER_BASE + HW_POWER_LOOPCTRL); __raw_writel((__raw_readl(REGS_POWER_BASE + HW_POWER_LOOPCTRL) & ~BM_POWER_LOOPCTRL_DC_R) | (2<