ARM: rockchip: rv1106_pm: improve the accuracy of recovering hptimer

Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
Change-Id: I5ccc5f5fba0f7696fc2c0563ed715b78b5adf451
This commit is contained in:
XiaoDong Huang
2024-01-16 18:08:28 +08:00
committed by Tao Huang
parent 0196404b4f
commit 21f57eaf2d
4 changed files with 38 additions and 19 deletions

View File

@@ -92,18 +92,23 @@ static int rk_hptimer_wait_begin_end_valid(void __iomem *base, u64 wait_us)
}
}
static u64 rk_hptimer_get_soft_adjust_delt_cnt(void __iomem *base)
static u64 rk_hptimer_get_soft_adjust_delt_cnt(void __iomem *base, u32 hf, u32 lf)
{
u64 begin, end, delt;
u32 tmp;
if (rk_hptimer_wait_begin_end_valid(base, HPTIMER_WAIT_MAX_US))
return 0;
/* (T32_24END - T24_32BEGIN + 2) * (T24 - T32) / T32 + 2.5 * T24/T32 + 2 */
begin = (u64)readl_relaxed(base + TIMER_HP_T24_32BEGIN0) |
(u64)readl_relaxed(base + TIMER_HP_T24_32BEGIN1) << 32;
end = (u64)readl_relaxed(base + TIMER_HP_T32_24END0) |
(u64)readl_relaxed(base + TIMER_HP_T32_24END1) << 32;
delt = (end - begin) * T24M_GCD / T32K_GCD;
delt = (end - begin + 2) * (hf - lf);
delt = div_u64(delt, lf);
tmp = (2 * hf + hf / 2) / lf;
delt = delt + tmp + 2;
writel_relaxed(0x3, base + TIMER_HP_BEGIN_END_VALID);
@@ -167,18 +172,18 @@ int rk_hptimer_wait_mode(void __iomem *base, enum rk_hptimer_mode_t mode)
return 0;
}
void rk_hptimer_do_soft_adjust(void __iomem *base)
void rk_hptimer_do_soft_adjust(void __iomem *base, u32 hf, u32 lf)
{
u64 delt = rk_hptimer_get_soft_adjust_delt_cnt(base);
u64 delt = rk_hptimer_get_soft_adjust_delt_cnt(base, hf, lf);
rk_hptimer_soft_adjust_req(base, delt);
rk_hptimer_wait_mode(base, RK_HPTIMER_SOFT_ADJUST_MODE);
}
void rk_hptimer_do_soft_adjust_no_wait(void __iomem *base)
void rk_hptimer_do_soft_adjust_no_wait(void __iomem *base, u32 hf, u32 lf)
{
u64 delt = rk_hptimer_get_soft_adjust_delt_cnt(base);
u64 delt = rk_hptimer_get_soft_adjust_delt_cnt(base, hf, lf);
rk_hptimer_soft_adjust_req(base, delt);
}

View File

@@ -16,7 +16,7 @@ int rk_hptimer_is_enabled(void __iomem *base);
int rk_hptimer_get_mode(void __iomem *base);
u64 rk_hptimer_get_count(void __iomem *base);
int rk_hptimer_wait_mode(void __iomem *base, enum rk_hptimer_mode_t mode);
void rk_hptimer_do_soft_adjust(void __iomem *base);
void rk_hptimer_do_soft_adjust_no_wait(void __iomem *base);
void rk_hptimer_do_soft_adjust(void __iomem *base, u32 hf, u32 lf);
void rk_hptimer_do_soft_adjust_no_wait(void __iomem *base, u32 hf, u32 lf);
void rk_hptimer_mode_init(void __iomem *base, enum rk_hptimer_mode_t mode);
#endif

View File

@@ -55,6 +55,7 @@ struct rv1106_sleep_ddr_data {
u32 gpio0a_iomux_l, gpio0a_iomux_h, gpio0a0_pull;
u32 gpio0_ddr_l, gpio0_ddr_h;
u32 pmu_wkup_int_st, gpio0_int_st;
u32 sleep_clk_freq_hz;
};
static struct rv1106_sleep_ddr_data ddr_data;
@@ -604,9 +605,9 @@ static void clock_resume(void)
static void pvtm_32k_config(int flag)
{
int value;
int pvtm_freq_khz, pvtm_div;
int sleep_clk_freq_khz;
u64 value, pvtm_freq_hz;
int pvtm_div;
u32 pvtm_div_freq_hz;
ddr_data.pmucru_sel_con7 =
readl_relaxed(pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
@@ -623,7 +624,7 @@ static void pvtm_32k_config(int flag)
pmupvtm_base + RV1106_PVTM_CON(2));
writel_relaxed(RV1106_PVTM_CALC_CNT,
pmupvtm_base + RV1106_PVTM_CON(1));
writel_relaxed(BITS_WITH_WMASK(0, 0x3, PVTM_START),
writel_relaxed(BITS_WITH_WMASK(0, 0x1, PVTM_START),
pmupvtm_base + RV1106_PVTM_CON(0));
dsb();
@@ -648,8 +649,11 @@ static void pvtm_32k_config(int flag)
;
value = (readl_relaxed(pmupvtm_base + RV1106_PVTM_STATUS(1)));
pvtm_freq_khz = (value * 24000 + RV1106_PVTM_CALC_CNT / 2) / RV1106_PVTM_CALC_CNT;
pvtm_div = (pvtm_freq_khz + 16) / 32 - 1;
pvtm_freq_hz = (value * 24000000 + RV1106_PVTM_CALC_CNT / 2);
pvtm_freq_hz = div_u64(pvtm_freq_hz, RV1106_PVTM_CALC_CNT);
pvtm_div = ((u32)pvtm_freq_hz + RV1106_PVTM_TARGET_FREQ / 2) /
RV1106_PVTM_TARGET_FREQ - 1;
if (pvtm_div > 0xfff)
pvtm_div = 0xfff;
@@ -660,12 +664,19 @@ static void pvtm_32k_config(int flag)
writel_relaxed(BITS_WITH_WMASK(0x2, 0x3, 0),
pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
sleep_clk_freq_khz = pvtm_freq_khz / (pvtm_div + 1);
pvtm_div_freq_hz = (u32)pvtm_freq_hz / (pvtm_div + 1);
ddr_data.sleep_clk_freq_hz = pvtm_div_freq_hz;
rkpm_printstr("pvtm real_freq (khz):");
rkpm_printhex(sleep_clk_freq_khz);
rkpm_printstr("pvtm freq (hz):");
rkpm_printdec(pvtm_freq_hz);
rkpm_printch('-');
rkpm_printdec(pvtm_div_freq_hz);
rkpm_printch('\n');
}
rkpm_printstr("sleep freq (hz):");
rkpm_printdec(ddr_data.sleep_clk_freq_hz);
rkpm_printch('\n');
}
static void pvtm_32k_config_restore(void)
@@ -674,7 +685,9 @@ static void pvtm_32k_config_restore(void)
pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
if (rk_hptimer_get_mode(hptimer_base) == RK_HPTIMER_SOFT_ADJUST_MODE)
rk_hptimer_do_soft_adjust_no_wait(hptimer_base);
rk_hptimer_do_soft_adjust_no_wait(hptimer_base,
24000000,
ddr_data.sleep_clk_freq_hz);
}
static void ddr_sleep_config(void)

View File

@@ -129,7 +129,8 @@
#define RV1106_PVTM_INTSTS 0x74
#define RV1106_PVTM_STATUS(i) (0x80 + (i) * 4)
#define RV1106_PVTM_CALC_CNT 0x200
#define RV1106_PVTM_CALC_CNT 24000
#define RV1106_PVTM_TARGET_FREQ 32768
/* gpio */
#define RV1106_GPIO_SWPORT_DR_L 0x0000