#define IRAM_SUSPEND_SIZE (1 << 12)
/*************************************************************
-mx6q_suspend:
+mx6_suspend:
Suspend the processor (eg, wait for interrupt).
Set the DDR into Self Refresh
r1: iram_paddr
r2: suspend_iram_base
*************************************************************/
+ .macro sl_ddr_io_save
+
+ ldr r4, [r1, #0x30c] /* DRAM_DQM0 */
+ ldr r5, [r1, #0x310] /* DRAM_DQM1 */
+ ldr r6, [r1, #0x314] /* DRAM_DQM2 */
+ ldr r7, [r1, #0x318] /* DRAM_DQM3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x344] /* DRAM_SDQS0 */
+ ldr r5, [r1, #0x348] /* DRAM_SDQS1 */
+ ldr r6, [r1, #0x34c] /* DRAM_SDQS2 */
+ ldr r7, [r1, #0x350] /* DRAM_SDQS3 */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x5c4] /* GPR_B0DS */
+ ldr r5, [r1, #0x5cc] /* GPR_B1DS */
+ ldr r6, [r1, #0x5d4] /* GPR_B2DS */
+ ldr r7, [r1, #0x5d8] /* GPR_B3DS */
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x300] /* DRAM_CAS */
+ ldr r5, [r1, #0x31c] /* DRAM_RAS */
+ ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */
+ ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ ldr r5, [r1, #0x5c0] /* DDRMODE */
+ ldr r6, [r1, #0x33c] /* DRAM_SODT0*/
+ ldr r7, [r1, #0x340] /* DRAM_SODT1*/
+ stmfd r0!, {r4-r7}
+
+ ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */
+ ldr r6, [r1, #0x320] /* DRAM_RESET */
+ ldr r7, [r1, #0x5c8] /* GPR_CTLDS */
+ stmfd r0!, {r4-r7}
+
+ .endm
+
+ .macro sl_ddr_io_restore
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x30c] /* DRAM_DQM0 */
+ str r5, [r1, #0x310] /* DRAM_DQM1 */
+ str r6, [r1, #0x314] /* DRAM_DQM2 */
+ str r7, [r1, #0x318] /* DRAM_DQM3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x344] /* DRAM_SDQS0 */
+ str r5, [r1, #0x348] /* DRAM_SDQS1 */
+ str r6, [r1, #0x34c] /* DRAM_SDQS2 */
+ str r7, [r1, #0x350] /* DRAM_SDQS3 */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x5c4] /* GPR_B0DS */
+ str r5, [r1, #0x5cc] /* GPR_B1DS */
+ str r6, [r1, #0x5d4] /* GPR_B2DS */
+ str r7, [r1, #0x5d8] /* GPR_B3DS */
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x300] /* DRAM_CAS */
+ str r5, [r1, #0x31c] /* DRAM_RAS */
+ str r6, [r1, #0x338] /* DRAM_SDCLK_0 */
+ str r7, [r1, #0x5ac] /* GPR_ADDS*/
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x5b0] /* DDRMODE_CTL */
+ str r5, [r1, #0x5c0] /* DDRMODE */
+ str r6, [r1, #0x33c] /* DRAM_SODT0*/
+ str r7, [r1, #0x340] /* DRAM_SODT1*/
+
+ ldmea r0!, {r4-r7}
+ str r4, [r1, #0x330] /* DRAM_SDCKE0 */
+ str r5, [r1, #0x334] /* DRAM_SDCKE1 */
+ str r6, [r1, #0x320] /* DRAM_RESET */
+ str r7, [r1, #0x5c8] /* GPR_CTLDS */
+
+ .endm
+
+ .macro sl_ddr_io_set_lpm
+
+ mov r0, #0
+ str r0, [r1, #0x30c] /* DRAM_DQM0 */
+ str r0, [r1, #0x310] /* DRAM_DQM1 */
+ str r0, [r1, #0x314] /* DRAM_DQM2 */
+ str r0, [r1, #0x318] /* DRAM_DQM3 */
+
+ str r0, [r1, #0x344] /* DRAM_SDQS0 */
+ str r0, [r1, #0x348] /* DRAM_SDQS1 */
+ str r0, [r1, #0x34c] /* DRAM_SDQS2 */
+ str r0, [r1, #0x350] /* DRAM_SDQS3 */
+
+ str r0, [r1, #0x5c4] /* GPR_B0DS */
+ str r0, [r1, #0x5cc] /* GPR_B1DS */
+ str r0, [r1, #0x5d4] /* GPR_B2DS */
+ str r0, [r1, #0x5d8] /* GPR_B3DS */
+
+ str r0, [r1, #0x300] /* DRAM_CAS */
+ str r0, [r1, #0x31c] /* DRAM_RAS */
+ str r0, [r1, #0x338] /* DRAM_SDCLK_0 */
+ str r0, [r1, #0x5ac] /* GPR_ADDS*/
+
+ str r0, [r1, #0x5b0] /* DDRMODE_CTL */
+ str r0, [r1, #0x5c0] /* DDRMODE */
+ str r0, [r1, #0x33c] /* DRAM_SODT0*/
+ str r0, [r1, #0x340] /* DRAM_SODT1*/
+
+ str r0, [r1, #0x5c8] /* GPR_CTLDS */
+ mov r0, #0x80000
+ str r0, [r1, #0x320] /* DRAM_RESET */
+ mov r0, #0x1000
+ str r0, [r1, #0x330] /* DRAM_SDCKE0 */
+ str r0, [r1, #0x334] /* DRAM_SDCKE1 */
+
+ .endm
+
.macro dl_ddr_io_save
ldr r4, [r1, #0x470] /* DRAM_DQM0 */
.endm
-ENTRY(mx6q_suspend)
+ENTRY(mx6_suspend)
stmfd sp!, {r0-r12} @ Save registers
/*************************************************************
suspend mode entry
*************************************************************/
+ mov r12, r3 /* Save CPU type to r12*/
cmp r0, #0x1
bne dormant /* dormant mode */
CPSR
SCTLR
************************************************************/
-ddr_iomux_save:
/* save mmdc iomux setting, stack is from the tail of
iram_suspend base */
mov r0, r2 /* get suspend_iram_base */
add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+
+ mov r4, sp @ Store sp
+ mrs r5, spsr @ Store spsr
+ mov r6, lr @ Store lr
+ mov r7, r12 @ Store cpu type
+ stmfd r0!, {r4-r7}
+
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_save
dq_ddr_io_save
+ b ddr_io_save_done
+dl_io_save:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_save
+ dl_ddr_io_save
+ b ddr_io_save_done
+sl_io_save:
+ sl_ddr_io_save
- mov r4, sp @ Store sp
- mrs r5, spsr @ Store spsr
- mov r6, lr @ Store lr
- stmfd r0!, {r4-r6}
+ddr_io_save_done:
/* c1 and c2 registers */
mrc p15, 0, r4, c1, c0, 2 @ CPACR
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_set_lpm
dq_ddr_io_set_lpm
+ b ddr_io_set_lpm_done
+dl_io_set_lpm:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_set_lpm
+ dl_ddr_io_set_lpm
+ b ddr_io_set_lpm_done
+sl_io_set_lpm:
+ sl_ddr_io_set_lpm
+
+ddr_io_set_lpm_done:
+
/****************************************************************
save resume pointer into SRC_GPR1
****************************************************************/
- ldr r0, =mx6q_suspend
+ ldr r0, =mx6_suspend
ldr r1, =resume
sub r1, r1, r0
add r3, r3, r1
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_restore
dq_ddr_io_restore
+ b ddr_io_restore_done
+dl_io_restore:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_restore
+ dl_ddr_io_restore
+ b ddr_io_restore_done
+sl_io_restore:
+ sl_ddr_io_restore
+
+ddr_io_restore_done:
mrc p15, 0, r1, c1, c0, 0
orr r1, r1, #(1 << 2) @ Enable the C bit
str r1, [r0, #SRC_GPR1_OFFSET] /* clear SRC_GPR1 */
ldr r0, [r0, #SRC_GPR2_OFFSET]
+ /* Restore cp15 registers and cpu type */
+ ldmea r0!, {r4-r7}
+ mov sp, r4 @ Restore sp
+ msr spsr_cxsf, r5 @ Restore spsr
+ mov lr, r6 @ Restore lr
+ mov r12, r7 @ Restore cpu type
+
+ /* Restore DDR IO */
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
+
+ cmp r12, #MXC_CPU_MX6Q
+ bne dl_io_dsm_restore
dq_ddr_io_restore
+ b ddr_io_restore_dsm_done
+dl_io_dsm_restore:
+ cmp r12, #MXC_CPU_MX6DL
+ bne sl_io_dsm_restore
+ dl_ddr_io_restore
+ b ddr_io_restore_dsm_done
+sl_io_dsm_restore:
+ sl_ddr_io_restore
- /* Restore cp15 registers */
- ldmea r0!, {r4-r6}
- mov sp, r4
- msr spsr_cxsf, r5 @ Restore spsr
- mov lr, r6 @ Restore lr
+ddr_io_restore_dsm_done:
/* c1 and c2 registers */
ldmea r0!, {r4-r7}
* enabling MMU.
*/
ldr r4, =PAGE_OFFSET
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne dq_dl_phy_offset
+ ldr r5, =MX6SL_PHYS_OFFSET
+ b get_phy_offset_done
+dq_dl_phy_offset:
ldr r5, =MX6_PHYS_OFFSET
+get_phy_offset_done:
+
sub r4, r4, r5
add r4, r4, r10
str r9, [r4]
ldmfd sp!, {r0-r12}
mov pc, lr
- .equ va2pa_offset, (PAGE_OFFSET - MX6_PHYS_OFFSET)
- .type mx6q_do_suspend, #object
-ENTRY(mx6q_do_suspend)
- .word mx6q_suspend
- .size mx6q_suspend, . - mx6q_suspend
+ .type mx6_do_suspend, #object
+ENTRY(mx6_do_suspend)
+ .word mx6_suspend
+ .size mx6_suspend, . - mx6_suspend
#define GPC_ISR3_OFFSET 0x20
#define GPC_ISR4_OFFSET 0x24
#define GPC_CNTR_OFFSET 0x0
+#define GPC_PGC_DISP_PGCR_OFFSET 0x240
#define GPC_PGC_GPU_PGCR_OFFSET 0x260
#define GPC_PGC_CPU_PDN_OFFSET 0x2a0
#define GPC_PGC_CPU_PUPSCR_OFFSET 0x2a4
#if defined(CONFIG_CPU_FREQ)
extern int set_cpu_freq(int wp);
#endif
-extern void mx6q_suspend(suspend_state_t state);
+extern void mx6_suspend(suspend_state_t state);
extern void mx6_init_irq(void);
extern unsigned int gpc_wake_irq[4];
static void *suspend_iram_base;
static void (*suspend_in_iram)(suspend_state_t state,
- unsigned long iram_paddr, unsigned long suspend_iram_base) = NULL;
+ unsigned long iram_paddr, unsigned long suspend_iram_base, unsigned int cpu_type) = NULL;
static unsigned long iram_paddr, cpaddr;
static u32 ccm_ccr, ccm_clpcr, scu_ctrl;
-static u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn, gpc_cpu, gpc_ctr;
+static u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn, gpc_cpu, gpc_ctr, gpc_disp;
static u32 anatop[2], ccgr1, ccgr2, ccgr3, ccgr6;
static u32 ccm_analog_pfd528;
static bool usb_vbus_wakeup_enabled;
gpc_cpu_pdn = __raw_readl(gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
gpc_cpu = __raw_readl(gpc_base + GPC_PGC_CPU_PDN_OFFSET);
gpc_ctr = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ if (cpu_is_mx6sl())
+ gpc_disp = __raw_readl(gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
anatop[0] = __raw_readl(anatop_base + ANATOP_REG_2P5_OFFSET);
anatop[1] = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
}
__raw_writel(gpc_cpu_pup, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
__raw_writel(gpc_cpu_pdn, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
__raw_writel(gpc_cpu, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
-
+ if (cpu_is_mx6sl())
+ __raw_writel(gpc_disp, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
__raw_writel(ccgr1, MXC_CCM_CCGR1);
__raw_writel(ccgr2, MXC_CCM_CCGR2);
__raw_writel(ccgr3, MXC_CCM_CCGR3);
static int mx6_suspend_enter(suspend_state_t state)
{
unsigned int wake_irq_isr[4];
+ unsigned int cpu_type;
struct gic_dist_state gds;
struct gic_cpu_state gcs;
+ if (cpu_is_mx6q())
+ cpu_type = MXC_CPU_MX6Q;
+ else if (cpu_is_mx6dl())
+ cpu_type = MXC_CPU_MX6DL;
+ else
+ cpu_type = MXC_CPU_MX6SL;
+
wake_irq_isr[0] = __raw_readl(gpc_base +
GPC_ISR1_OFFSET) & gpc_wake_irq[0];
wake_irq_isr[1] = __raw_readl(gpc_base +
}
suspend_in_iram(state, (unsigned long)iram_paddr,
- (unsigned long)suspend_iram_base);
+ (unsigned long)suspend_iram_base, cpu_type);
if (state == PM_SUSPEND_MEM) {
/* restore gic registers */
* Need to run the suspend code from IRAM as the DDR needs
* to be put into low power mode manually.
*/
- memcpy((void *)cpaddr, mx6q_suspend, SZ_4K);
+ memcpy((void *)cpaddr, mx6_suspend, SZ_4K);
suspend_in_iram = (void *)suspend_iram_base;
#define SCU_INVALIDATE 0x0c
#define SCU_FPGA_REVISION 0x10
#define GPC_CNTR_OFFSET 0x0
+#define GPC_PGC_DISP_PGCR_OFFSET 0x240
#define GPC_PGC_GPU_PGCR_OFFSET 0x260
#define GPC_PGC_CPU_PDN_OFFSET 0x2a0
#define GPC_PGC_CPU_PUPSCR_OFFSET 0x2a4
int stop_mode = 0;
void __iomem *anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR);
- u32 ccm_clpcr, anatop_val;
+ u32 ccm_clpcr, anatop_val, reg;
ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
- ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
stop_mode = 0;
} else if (mode == STOP_POWER_OFF) {
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
- ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
stop_mode = 1;
} else {
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
- ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
stop_mode = 2;
}
break;
__raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
__raw_writel(0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
__raw_writel(0x1, gpc_base + GPC_CNTR_OFFSET);
- if (cpu_is_mx6q()) {
+ if (cpu_is_mx6sl()) {
+ __raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+ __raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET);
+ }
+ if (cpu_is_mx6q() || cpu_is_mx6dl()) {
/* Enable weak 2P5 linear regulator */
anatop_val = __raw_readl(anatop_base +
HW_ANADIG_REG_2P5);
__raw_writel(anatop_val, anatop_base +
HW_ANADIG_REG_CORE);
}
+ } else {
+ /* Disable VDDHIGH_IN to VDDSNVS_IN power path,
+ * only used when VDDSNVS_IN is powered by dedicated
+ * power rail */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ /* We need to allow the memories to be clock gated
+ * in STOP mode, else the power consumption will
+ * be very high. */
+ reg = __raw_readl(MXC_CCM_CGPR);
+ reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK;
+ __raw_writel(reg, MXC_CCM_CGPR);
}
- if (cpu_is_mx6q())
+
+ if (!cpu_is_mx6dl())
__raw_writel(__raw_readl(MXC_CCM_CCR) |
MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR);
/* Make sure we clear WB_COUNT and re-config it */