diff --git a/arch/arm/mach-rockchip/rockchip_hptimer.c b/arch/arm/mach-rockchip/rockchip_hptimer.c index 7cf7e9e46d31..5ca137e5b7bd 100644 --- a/arch/arm/mach-rockchip/rockchip_hptimer.c +++ b/arch/arm/mach-rockchip/rockchip_hptimer.c @@ -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); } diff --git a/arch/arm/mach-rockchip/rockchip_hptimer.h b/arch/arm/mach-rockchip/rockchip_hptimer.h index 4cf6399ba093..eba644d80b2a 100644 --- a/arch/arm/mach-rockchip/rockchip_hptimer.h +++ b/arch/arm/mach-rockchip/rockchip_hptimer.h @@ -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 diff --git a/arch/arm/mach-rockchip/rv1106_pm.c b/arch/arm/mach-rockchip/rv1106_pm.c index fbf7eae02596..1b352ffa2a1a 100644 --- a/arch/arm/mach-rockchip/rv1106_pm.c +++ b/arch/arm/mach-rockchip/rv1106_pm.c @@ -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) diff --git a/arch/arm/mach-rockchip/rv1106_pm.h b/arch/arm/mach-rockchip/rv1106_pm.h index cd07adc1acc6..8144344a1819 100644 --- a/arch/arm/mach-rockchip/rv1106_pm.h +++ b/arch/arm/mach-rockchip/rv1106_pm.h @@ -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