/* * 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_LOOPCTRL_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_LOOPCTRL) #define HW_POWER_MINPWR_ADDR \ (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_MINPWR) #define PHYS_RAM_START 0x40000000 #define LOWER_VDDIO 6 #define LOWER_VDDA 9 #define LOWER_VDDD 0x16 #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_CTL17_ADDR & 0x000000FF) orr r0, r0, #(HW_DRAM_CTL17_ADDR & 0x0000FF00) orr r0, r0, #(HW_DRAM_CTL17_ADDR & 0x00FF0000) orr r0, r0, #(HW_DRAM_CTL17_ADDR & 0xFF000000) ldr r1, [r0] orr r1, r1, #(BM_DRAM_CTL17_SREFRESH) str r1, [r0] @ wait for it to actually happen mov r0, #24 << 5 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 // vddio PM_SET_AND_BACKUP_REG HW_POWER_VDDIOCTRL_ADDR,\ BM_POWER_VDDIOCTRL_TRG, LOWER_VDDIO, VDDIOCTRL_BACKUP mov r0, #24 << 10 1: sub r0, r0, #1 cmp r0, #0 bne 1b PM_SET_AND_BACKUP_REG HW_POWER_VDDACTRL_ADDR,\ BM_POWER_VDDACTRL_TRG, LOWER_VDDA, VDDACTRL_BACKUP mov r0, #24 << 10 2: sub r0, r0, #1 cmp r0, #0 bne 2b PM_SET_AND_BACKUP_REG HW_POWER_VDDDCTRL_ADDR,\ BM_POWER_VDDDCTRL_TRG, LOWER_VDDD, VDDDCTRL_BACKUP mov r0, #24 << 10 3: sub r0, r0, #1 cmp r0, #0 bne 3b 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<