rockchip: close the PD center logic during suspend
The RK3399 supports close the center logic enter power mode, so we can close PD_CENTER to save more power during suspend. Therefore, we need to support save/restore the DDR PHY and controller registers during suspend/resume. Also, need CL (http://crosreview.com/397399) to check disabling center logic. Change-Id: I288defd8e9caa3846d9fa663a33e4d51df1aaa5d Signed-off-by: Xing Zheng <zhengxing@rock-chips.com> Signed-off-by: Derek Basehore <dbasehore@chromium.org> Signed-off-by: Caesar Wang <wxt@rock-chips.com>
This commit is contained in:
parent
2831bc3a5f
commit
4c127e687f
|
@ -27,9 +27,25 @@
|
|||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
#include <pmu_regs.h>
|
||||
|
||||
.globl clst_warmboot_data
|
||||
|
||||
.macro sram_func _name
|
||||
.section .sram.text, "ax"
|
||||
.type \_name, %function
|
||||
.func \_name
|
||||
\_name:
|
||||
.endm
|
||||
|
||||
#define CRU_CLKSEL_CON6 0x118
|
||||
|
||||
#define DDRCTL0_C_SYSREQ_CFG 0x0100
|
||||
#define DDRCTL1_C_SYSREQ_CFG 0x1000
|
||||
|
||||
#define DDRC0_SREF_DONE_EXT 0x01
|
||||
#define DDRC1_SREF_DONE_EXT 0x04
|
||||
|
||||
#define PLL_MODE_SHIFT (0x8)
|
||||
#define PLL_NORMAL_MODE ((0x3 << (PLL_MODE_SHIFT + 16)) | \
|
||||
(0x1 << PLL_MODE_SHIFT))
|
||||
|
@ -65,3 +81,75 @@ clst_warmboot_data:
|
|||
.word 0
|
||||
.endr
|
||||
.endm
|
||||
|
||||
/* -----------------------------------------------
|
||||
* void sram_func_set_ddrctl_pll(uint32_t pll_src)
|
||||
* Function to switch the PLL source for ddrctrl
|
||||
* In: x0 - The PLL of the clk_ddrc clock source
|
||||
* out: None
|
||||
* Clobber list : x0 - x3, x5, x8 - x10
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
|
||||
.globl sram_func_set_ddrctl_pll
|
||||
|
||||
sram_func sram_func_set_ddrctl_pll
|
||||
/* backup parameter */
|
||||
mov x8, x0
|
||||
|
||||
/* disable the MMU at EL3 */
|
||||
mrs x9, sctlr_el3
|
||||
bic x10, x9, #(SCTLR_M_BIT)
|
||||
msr sctlr_el3, x10
|
||||
isb
|
||||
dsb sy
|
||||
|
||||
/* enable ddrctl0_1 idle request */
|
||||
mov x5, PMU_BASE
|
||||
ldr w0, [x5, #PMU_SFT_CON]
|
||||
orr w0, w0, #DDRCTL0_C_SYSREQ_CFG
|
||||
orr w0, w0, #DDRCTL1_C_SYSREQ_CFG
|
||||
str w0, [x5, #PMU_SFT_CON]
|
||||
|
||||
check_ddrc0_1_sref_enter:
|
||||
ldr w1, [x5, #PMU_DDR_SREF_ST]
|
||||
and w2, w1, #DDRC0_SREF_DONE_EXT
|
||||
and w3, w1, #DDRC1_SREF_DONE_EXT
|
||||
orr w2, w2, w3
|
||||
cmp w2, #(DDRC0_SREF_DONE_EXT | DDRC1_SREF_DONE_EXT)
|
||||
b.eq check_ddrc0_1_sref_enter
|
||||
|
||||
/*
|
||||
* select a PLL for ddrctrl:
|
||||
* x0 = 0: ALPLL
|
||||
* x0 = 1: ABPLL
|
||||
* x0 = 2: DPLL
|
||||
* x0 = 3: GPLLL
|
||||
*/
|
||||
mov x5, CRU_BASE
|
||||
lsl w0, w8, #4
|
||||
orr w0, w0, #0x00300000
|
||||
str w0, [x5, #CRU_CLKSEL_CON6]
|
||||
|
||||
/* disable ddrctl0_1 idle request */
|
||||
mov x5, PMU_BASE
|
||||
ldr w0, [x5, #PMU_SFT_CON]
|
||||
bic w0, w0, #DDRCTL0_C_SYSREQ_CFG
|
||||
bic w0, w0, #DDRCTL1_C_SYSREQ_CFG
|
||||
str w0, [x5, #PMU_SFT_CON]
|
||||
|
||||
check_ddrc0_1_sref_exit:
|
||||
ldr w1, [x5, #PMU_DDR_SREF_ST]
|
||||
and w2, w1, #DDRC0_SREF_DONE_EXT
|
||||
and w3, w1, #DDRC1_SREF_DONE_EXT
|
||||
orr w2, w2, w3
|
||||
cmp w2, #0x0
|
||||
b.eq check_ddrc0_1_sref_exit
|
||||
|
||||
/* reenable the MMU at EL3 */
|
||||
msr sctlr_el3, x9
|
||||
isb
|
||||
dsb sy
|
||||
|
||||
ret
|
||||
endfunc sram_func_set_ddrctl_pll
|
||||
|
|
|
@ -46,9 +46,9 @@
|
|||
#include <pmu.h>
|
||||
#include <pmu_com.h>
|
||||
#include <pwm.h>
|
||||
#include <soc.h>
|
||||
#include <bl31.h>
|
||||
#include <rk3399m0.h>
|
||||
#include <suspend.h>
|
||||
|
||||
DEFINE_BAKERY_LOCK(rockchip_pd_lock);
|
||||
|
||||
|
@ -102,7 +102,6 @@ static void pmu_bus_idle_req(uint32_t bus, uint32_t state)
|
|||
mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK),
|
||||
bus_ack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct pmu_slpdata_s pmu_slpdata;
|
||||
|
@ -818,10 +817,19 @@ static void init_pmu_counts(void)
|
|||
mmio_write_32(PMU_BASE + PMU_GPU_PWRUP_CNT, CYCL_24M_CNT_US(1));
|
||||
}
|
||||
|
||||
static uint32_t clk_ddrc_save;
|
||||
|
||||
static void sys_slp_config(void)
|
||||
{
|
||||
uint32_t slp_mode_cfg = 0;
|
||||
|
||||
/* keep enabling clk_ddrc_bpll_src_en gate for DDRC */
|
||||
clk_ddrc_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(3));
|
||||
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), WMSK_BIT(1));
|
||||
|
||||
prepare_abpll_for_ddrctrl();
|
||||
sram_func_set_ddrctl_pll(ABPLL_ID);
|
||||
|
||||
mmio_write_32(GRF_BASE + GRF_SOC_CON4, CCI_FORCE_WAKEUP);
|
||||
mmio_write_32(PMU_BASE + PMU_CCI500_CON,
|
||||
BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) |
|
||||
|
@ -849,6 +857,7 @@ static void sys_slp_config(void)
|
|||
BIT(PMU_DDRIO0_RET_EN) |
|
||||
BIT(PMU_DDRIO1_RET_EN) |
|
||||
BIT(PMU_DDRIO_RET_HW_DE_REQ) |
|
||||
BIT(PMU_CENTER_PD_EN) |
|
||||
BIT(PMU_PLL_PD_EN) |
|
||||
BIT(PMU_CLK_CENTER_SRC_GATE_EN) |
|
||||
BIT(PMU_OSC_DIS) |
|
||||
|
@ -857,7 +866,6 @@ static void sys_slp_config(void)
|
|||
mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, BIT(PMU_GPIO_WKUP_EN));
|
||||
mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg);
|
||||
|
||||
|
||||
mmio_write_32(PMU_BASE + PMU_PLL_CON, PLL_PD_HW);
|
||||
mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON0, EXTERNAL_32K);
|
||||
mmio_write_32(PMUGRF_BASE, IOMUX_CLK_32K); /* 32k iomux */
|
||||
|
@ -1094,6 +1102,9 @@ static int sys_pwr_domain_suspend(void)
|
|||
uint32_t wait_cnt = 0;
|
||||
uint32_t status = 0;
|
||||
|
||||
dmc_save();
|
||||
pmu_scu_b_pwrdn();
|
||||
|
||||
pmu_power_domains_suspend();
|
||||
set_hw_idle(BIT(PMU_CLR_CENTER1) |
|
||||
BIT(PMU_CLR_ALIVE) |
|
||||
|
@ -1114,8 +1125,6 @@ static int sys_pwr_domain_suspend(void)
|
|||
(PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
|
||||
CPU_BOOT_ADDR_WMASK);
|
||||
|
||||
pmu_scu_b_pwrdn();
|
||||
|
||||
mmio_write_32(PMU_BASE + PMU_ADB400_CON,
|
||||
BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) |
|
||||
BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) |
|
||||
|
@ -1134,6 +1143,7 @@ static int sys_pwr_domain_suspend(void)
|
|||
}
|
||||
}
|
||||
mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN));
|
||||
|
||||
/*
|
||||
* Disabling PLLs/PWM/DVFS is approaching WFI which is
|
||||
* the last steps in suspend.
|
||||
|
@ -1163,6 +1173,10 @@ static int sys_pwr_domain_resume(void)
|
|||
enable_dvfs_plls();
|
||||
plls_resume_finish();
|
||||
|
||||
/* restore clk_ddrc_bpll_src_en gate */
|
||||
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
|
||||
BITS_WITH_WMASK(clk_ddrc_save, 0xff, 0));
|
||||
|
||||
/*
|
||||
* The wakeup status is not cleared by itself, we need to clear it
|
||||
* manually. Otherwise we will alway query some interrupt next time.
|
||||
|
@ -1209,8 +1223,12 @@ static int sys_pwr_domain_resume(void)
|
|||
|
||||
pmu_sgrf_rst_hld_release();
|
||||
pmu_scu_b_pwrup();
|
||||
|
||||
pmu_power_domains_resume();
|
||||
|
||||
restore_dpll();
|
||||
sram_func_set_ddrctl_pll(DPLL_ID);
|
||||
restore_abpll();
|
||||
|
||||
clr_hw_idle(BIT(PMU_CLR_CENTER1) |
|
||||
BIT(PMU_CLR_ALIVE) |
|
||||
BIT(PMU_CLR_MSCH0) |
|
||||
|
@ -1301,9 +1319,10 @@ void plat_rockchip_pmu_init(void)
|
|||
for (cpu = 0; cpu < PLATFORM_CLUSTER_COUNT; cpu++)
|
||||
clst_warmboot_data[cpu] = 0;
|
||||
|
||||
psram_sleep_cfg->ddr_func = 0x00;
|
||||
psram_sleep_cfg->ddr_data = 0x00;
|
||||
psram_sleep_cfg->ddr_flag = 0x00;
|
||||
psram_sleep_cfg->ddr_func = (uint64_t)dmc_restore;
|
||||
psram_sleep_cfg->ddr_data = (uint64_t)&sdram_config;
|
||||
psram_sleep_cfg->ddr_flag = 0x01;
|
||||
|
||||
psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
|
||||
|
||||
/* config cpu's warm boot address */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define __PMU_H__
|
||||
|
||||
#include <pmu_regs.h>
|
||||
#include <soc.h>
|
||||
|
||||
/* Allocate sp reginon in pmusram */
|
||||
#define PSRAM_SP_SIZE 0x80
|
||||
|
@ -843,4 +844,7 @@ struct pmu_slpdata_s {
|
|||
};
|
||||
|
||||
extern uint32_t clst_warmboot_data[PLATFORM_CLUSTER_COUNT];
|
||||
|
||||
extern void sram_func_set_ddrctl_pll(uint32_t pll_src);
|
||||
|
||||
#endif /* __PMU_H__ */
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
const mmap_region_t plat_rk_mmap[] = {
|
||||
MAP_REGION_FLAT(RK3399_DEV_RNG0_BASE, RK3399_DEV_RNG0_SIZE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
|
||||
MT_MEMORY | MT_RW | MT_SECURE),
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
@ -238,21 +240,105 @@ static void _pll_suspend(uint32_t pll_id)
|
|||
set_pll_bypass(pll_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_dvfs_plls - To suspend the specific PLLs
|
||||
*
|
||||
* When we close the center logic, the DPLL will be closed,
|
||||
* so we need to keep the ABPLL and switch to it to supply
|
||||
* clock for DDR during suspend, then we should not close
|
||||
* the ABPLL and exclude ABPLL_ID.
|
||||
*/
|
||||
void disable_dvfs_plls(void)
|
||||
{
|
||||
_pll_suspend(CPLL_ID);
|
||||
_pll_suspend(NPLL_ID);
|
||||
_pll_suspend(VPLL_ID);
|
||||
_pll_suspend(GPLL_ID);
|
||||
_pll_suspend(ABPLL_ID);
|
||||
_pll_suspend(ALPLL_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_nodvfs_plls - To suspend the PPLL
|
||||
*/
|
||||
void disable_nodvfs_plls(void)
|
||||
{
|
||||
_pll_suspend(PPLL_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* restore_pll - Copy PLL settings from memory to a PLL.
|
||||
*
|
||||
* This will copy PLL settings from an array in memory to the memory mapped
|
||||
* registers for a PLL.
|
||||
*
|
||||
* Note that: above the PLL exclude PPLL.
|
||||
*
|
||||
* pll_id: One of the values from enum plls_id
|
||||
* src: Pointer to the array of values to restore from
|
||||
*/
|
||||
static void restore_pll(int pll_id, uint32_t *src)
|
||||
{
|
||||
/* Nice to have PLL off while configuring */
|
||||
mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
|
||||
|
||||
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
|
||||
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
|
||||
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
|
||||
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
|
||||
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
|
||||
|
||||
/* Do PLL_CON3 since that will enable things */
|
||||
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
|
||||
|
||||
/* Wait for PLL lock done */
|
||||
while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
|
||||
0x80000000) == 0x0)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* save_pll - Copy PLL settings a PLL to memory
|
||||
*
|
||||
* This will copy PLL settings from the memory mapped registers for a PLL to
|
||||
* an array in memory.
|
||||
*
|
||||
* Note that: above the PLL exclude PPLL.
|
||||
*
|
||||
* pll_id: One of the values from enum plls_id
|
||||
* src: Pointer to the array of values to save to.
|
||||
*/
|
||||
static void save_pll(uint32_t *dst, int pll_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PLL_CON_COUNT; i++)
|
||||
dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i));
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL
|
||||
*
|
||||
* This will copy DPLL settings from the memory mapped registers for a PLL to
|
||||
* an array in memory.
|
||||
*/
|
||||
void prepare_abpll_for_ddrctrl(void)
|
||||
{
|
||||
save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID);
|
||||
save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID);
|
||||
|
||||
restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]);
|
||||
}
|
||||
|
||||
void restore_abpll(void)
|
||||
{
|
||||
restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
|
||||
}
|
||||
|
||||
void restore_dpll(void)
|
||||
{
|
||||
restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]);
|
||||
}
|
||||
|
||||
void plls_suspend_prepare(void)
|
||||
{
|
||||
uint32_t i, pll_id;
|
||||
|
@ -343,16 +429,25 @@ void plls_resume_finish(void)
|
|||
REG_SOC_WMSK | slp_data.pmucru_clksel_con[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_dvfs_plls - To resume the specific PLLs
|
||||
*
|
||||
* Please see the comment at the disable_dvfs_plls()
|
||||
* we don't suspend the ABPLL, so don't need resume
|
||||
* it too.
|
||||
*/
|
||||
void enable_dvfs_plls(void)
|
||||
{
|
||||
_pll_resume(ALPLL_ID);
|
||||
_pll_resume(ABPLL_ID);
|
||||
_pll_resume(GPLL_ID);
|
||||
_pll_resume(VPLL_ID);
|
||||
_pll_resume(NPLL_ID);
|
||||
_pll_resume(CPLL_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_nodvfs_plls - To resume the PPLL
|
||||
*/
|
||||
void enable_nodvfs_plls(void)
|
||||
{
|
||||
_pll_resume(PPLL_ID);
|
||||
|
|
|
@ -336,7 +336,11 @@ void disable_nodvfs_plls(void);
|
|||
void plls_resume_finish(void);
|
||||
void enable_dvfs_plls(void);
|
||||
void enable_nodvfs_plls(void);
|
||||
void prepare_abpll_for_ddrctrl(void);
|
||||
void restore_abpll(void);
|
||||
void restore_dpll(void);
|
||||
void clk_gate_con_save(void);
|
||||
void clk_gate_con_disable(void);
|
||||
void clk_gate_con_restore(void);
|
||||
void sgrf_init(void);
|
||||
#endif /* __SOC_H__ */
|
||||
|
|
Loading…
Reference in New Issue