/* * Copyright (C) 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 "regs-pinctrl.h" #include "regs-clkctrl.h" #include "regs-dram.h" #include "sleep.h" #define BM_DRAM_CTL17_SREFRESH 0x00000001 #define HW_CLKCTRL_CPU_ADDR \ (MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR) + HW_CLKCTRL_CPU) #define HW_POWER_MINPWR_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_MINPWR) #define HW_POWER_RESET_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_RESET) #define HW_DRAM_CTL17_ADDR \ (MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL17) #define HW_DRAM_CTL22_ADDR \ (MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL22) #define HW_RTC_PERSISTENT0_ADDR \ (MX28_SOC_IO_ADDRESS(RTC_PHYS_ADDR) + HW_RTC_PERSISTENT0) #define HW_CLKCTRL_EMI_ADDR \ (MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR) + HW_CLKCTRL_EMI) #define HW_CLKCTRL_PLL0CTRL0_ADDR \ (MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR) + HW_CLKCTRL_PLL0CTRL0) #define HW_POWER_VDDIOCTRL_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_VDDIOCTRL) #define HW_POWER_VDDDCTRL_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_VDDDCTRL) #define HW_POWER_VDDACTRL_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_VDDACTRL) #define HW_PINCTRL_EMI_DS_CTRL_ADDR \ (MX28_SOC_IO_ADDRESS(PINCTRL_PHYS_ADDR) + HW_PINCTRL_EMI_DS_CTRL) #define HW_POWER_5VCTRL_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_5VCTRL) #define HW_POWER_LOOPCTRL_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_LOOPCTRL) #define HW_POWER_STS_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_STS) #define HW_POWER_MINPWR_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_MINPWR) #define PHYS_RAM_START 0x40000000 #define LOWER_VDDIO 5 #define LOWER_VDDA 9 #define LOWER_VDDD 12 #define VDDIOCTRL_BACKUP 0 #define VDDACTRL_BACKUP 1 #define VDDDCTRL_BACKUP 2 #define POWER_LOOPCTRL_BACKUP 3 #define POWER_MINPWR_BACKUP 4 .macro PM_BITS_SET, addr, val mov r0, #(\addr & 0x000000FF) orr r0, r0, #(\addr & 0x0000FF00) orr r0, r0, #(\addr & 0x00FF0000) orr r0, r0, #(\addr & 0xFF000000) ldr r1, [r0] orr r1, r1, #(\val) str r1, [r0] .endm .macro PM_BITS_CLR, addr, val mov r0, #(\addr & 0x000000FF) orr r0, r0, #(\addr & 0x0000FF00) orr r0, r0, #(\addr & 0x00FF0000) orr r0, r0, #(\addr & 0xFF000000) ldr r1, [r0] bic r1, r1, #(\val) str r1, [r0] .endm .macro PM_BACKUP_REG, addr, num mov r0, #(\addr & 0x000000FF) orr r0, r0, #(\addr & 0x0000FF00) orr r0, r0, #(\addr & 0x00FF0000) orr r0, r0, #(\addr & 0xFF000000) ldr r1, [r0] str r1, __mx28_temp_stack + \num * 4 .endm .macro PM_WRITE_REG_MASK, addr, bitmask, val mov r0, #(\addr & 0x000000FF) orr r0, r0, #(\addr & 0x0000FF00) orr r0, r0, #(\addr & 0x00FF0000) orr r0, r0, #(\addr & 0xFF000000) ldr r1, [r0] bic r1, r1, #(\bitmask) orr r1, r1, #(\val) str r1, [r0] .endm .macro PM_SET_AND_BACKUP_REG, addr, bitmask, val, num mov r0, #(\addr & 0x000000FF) orr r0, r0, #(\addr & 0x0000FF00) orr r0, r0, #(\addr & 0x00FF0000) orr r0, r0, #(\addr & 0xFF000000) ldr r1, [r0] str r1, __mx28_temp_stack + \num * 4 bic r1, r1, #(\bitmask) orr r1, r1, #(\val) str r1, [r0] .endm .macro PM_SET_RESTORE_REG, addr, num mov r0, #(\addr & 0x000000FF) orr r0, r0, #(\addr & 0x0000FF00) orr r0, r0, #(\addr & 0x00FF0000) orr r0, r0, #(\addr & 0xFF000000) ldr r1, __mx28_temp_stack + \num * 4 str r1, [r0] .endm .global cpu_arm926_switch_mm .text .align 8 ENTRY(mx28_cpu_standby) @ save registers on stack stmfd sp!, {r0 - r9, lr} adr r9, __mx28_temp_stack @ clean cache ldr r1, __mx28_flush_cache_addr mov lr, pc mov pc, r1 @ put DRAM into self refresh mov r0, #(HW_DRAM_CTL22_ADDR & 0x000000FF) orr r0, r0, #(HW_DRAM_CTL22_ADDR & 0x0000FF00) orr r0, r0, #(HW_DRAM_CTL22_ADDR & 0x00FF0000) orr r0, r0, #(HW_DRAM_CTL22_ADDR & 0xFF000000) ldr r1,[r0] and r1, r1, #(~BM_DRAM_CTL22_LOWPOWER_CONTROL) orr r1, r1, #(BF_DRAM_CTL22_LOWPOWER_CONTROL(2)) str r1, [r0] @ wait for it to actually happen mov r0, #24 << 12 11: sub r0, r0, #1 cmp r0, #0 bne 11b @ gate clk mov r0, #(HW_CLKCTRL_EMI_ADDR & 0x000000FF) orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x0000FF00) orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x00FF0000) orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0xFF000000) ldr r1, [r0] orr r1, r1, #(BM_CLKCTRL_EMI_CLKGATE) str r1, [r0] // PM_SET_AND_BACKUP_REG HW_PINCTRL_EMI_DS_CTRL_ADDR,\ // BM_PINCTRL_EMI_DS_CTRL_DDR_MODE,\ // BF_PINCTRL_EMI_DS_CTRL_DDR_MODE(0x1), 4 mov r0, #(HW_PINCTRL_EMI_DS_CTRL_ADDR & 0x000000FF) orr r0, r0, #(HW_PINCTRL_EMI_DS_CTRL_ADDR & 0x0000FF00) orr r0, r0, #(HW_PINCTRL_EMI_DS_CTRL_ADDR & 0x00FF0000) orr r0, r0, #(HW_PINCTRL_EMI_DS_CTRL_ADDR & 0xFF000000) ldr r1, [r0] and r1, r1, #(~BM_PINCTRL_EMI_DS_CTRL_DDR_MODE) orr r1, r1, #(BF_PINCTRL_EMI_DS_CTRL_DDR_MODE(0x1)) str r1, [r0] mov r2, #(HW_POWER_STS_ADDR & 0x000000FF) orr r2, r2, #(HW_POWER_STS_ADDR & 0x0000FF00) orr r2, r2, #(HW_POWER_STS_ADDR & 0x00FF0000) orr r2, r2, #(HW_POWER_STS_ADDR & 0xFF000000) // vddio PM_SET_AND_BACKUP_REG HW_POWER_VDDIOCTRL_ADDR,\ BM_POWER_VDDIOCTRL_TRG, LOWER_VDDIO, VDDIOCTRL_BACKUP 7: mov r0, #24 << 10 1: sub r0, r0, #1 cmp r0, #0 bne 1b ldr r0,[r2] and r0,r0,#(BM_POWER_STS_DC_OK) cmp r0,#(BM_POWER_STS_DC_OK) bne 7b PM_SET_AND_BACKUP_REG HW_POWER_VDDACTRL_ADDR,\ BM_POWER_VDDACTRL_TRG, LOWER_VDDA, VDDACTRL_BACKUP 8: mov r0, #24 << 10 2: sub r0, r0, #1 cmp r0, #0 bne 2b ldr r0,[r2] and r0,r0,#(BM_POWER_STS_DC_OK) cmp r0,#(BM_POWER_STS_DC_OK) bne 8b PM_SET_AND_BACKUP_REG HW_POWER_VDDDCTRL_ADDR,\ BM_POWER_VDDDCTRL_TRG, LOWER_VDDD, VDDDCTRL_BACKUP 9: mov r0, #24 << 10 3: sub r0, r0, #1 cmp r0, #0 bne 3b ldr r0,[r2] and r0,r0,#(BM_POWER_STS_DC_OK) cmp r0,#(BM_POWER_STS_DC_OK) bne 9b @ wait for DC OK mov r0, #(HW_POWER_STS_ADDR & 0x000000FF) orr r0, r0, #(HW_POWER_STS_ADDR & 0x0000FF00) orr r0, r0, #(HW_POWER_STS_ADDR & 0x00FF0000) orr r0, r0, #(HW_POWER_STS_ADDR & 0xFF000000) 4: ldr r1,[r0] and r1,r1,#(BM_POWER_STS_DC_OK) cmp r1,#(BM_POWER_STS_DC_OK) bne 4b PM_BACKUP_REG HW_POWER_LOOPCTRL_ADDR, POWER_LOOPCTRL_BACKUP PM_BACKUP_REG HW_POWER_MINPWR_ADDR, POWER_MINPWR_BACKUP PM_BITS_CLR HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_EN_RCSCALE PM_WRITE_REG_MASK HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_DC_R,\ (2<