Loading drivers/clocksource/arm_arch_timer.c +20 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ #define CNTFRQ 0x10 #define CNTP_TVAL 0x28 #define CNTP_CTL 0x2c #define CNTCVAL_LO 0x30 #define CNTCVAL_HI 0x34 #define CNTV_TVAL 0x38 #define CNTV_CTL 0x3c Loading Loading @@ -541,6 +543,23 @@ u32 arch_timer_get_rate(void) return arch_timer_rate; } void arch_timer_mem_get_cval(u32 *lo, u32 *hi) { u32 ctrl; *lo = *hi = ~0U; if (!arch_counter_base) return; ctrl = readl_relaxed_no_log(arch_counter_base + CNTV_CTL); if (ctrl & ARCH_TIMER_CTRL_ENABLE) { *lo = readl_relaxed_no_log(arch_counter_base + CNTCVAL_LO); *hi = readl_relaxed_no_log(arch_counter_base + CNTCVAL_HI); } } static u64 arch_counter_get_cntvct_mem(void) { u32 vct_lo, vct_hi, tmp_hi; Loading drivers/cpuidle/lpm-levels.c +8 −10 Original line number Diff line number Diff line Loading @@ -1043,18 +1043,9 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, } if (level->notify_rpm) { uint64_t us; uint32_t pred_us; us = get_cluster_sleep_time(cluster, NULL, from_idle, &pred_us); us = us + 1; clear_predict_history(); clear_cl_predict_history(); if (system_sleep_enter(us)) if (system_sleep_enter()) return -EBUSY; } /* Notify cluster enter event after successfully config completion */ Loading Loading @@ -1261,6 +1252,13 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) state_id |= (level->psci_id & cluster->psci_mode_mask) << cluster->psci_mode_shift; (*aff_lvl)++; /* * We may have updated the broadcast timers, update * the wakeup value by reading the bc timer directly. */ if (level->notify_rpm) system_sleep_update_wakeup(); } unlock_and_return: spin_unlock(&cluster->sync_lock); Loading drivers/soc/qcom/system_pm.c +20 −28 Original line number Diff line number Diff line Loading @@ -18,23 +18,35 @@ #include <soc/qcom/rpmh.h> #include <soc/qcom/system_pm.h> #define ARCH_TIMER_HZ (19200000UL) #include <clocksource/arm_arch_timer.h> #define PDC_TIME_VALID_SHIFT 31 #define PDC_TIME_UPPER_MASK 0xFFFFFF static struct rpmh_client *rpmh_client; static int setup_wakeup(uint64_t sleep_val) static int setup_wakeup(uint32_t lo, uint32_t hi) { struct tcs_cmd cmd[2] = { { 0 } }; cmd[0].data = (sleep_val >> 32) & PDC_TIME_UPPER_MASK; cmd[0].data = hi & PDC_TIME_UPPER_MASK; cmd[0].data |= 1 << PDC_TIME_VALID_SHIFT; cmd[1].data = sleep_val & 0xFFFFFFFF; cmd[1].data = lo; return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd)); } int system_sleep_update_wakeup(void) { uint32_t lo = ~0U, hi = ~0U; /* Read the hardware to get the most accurate value */ arch_timer_mem_get_cval(&lo, &hi); return setup_wakeup(lo, hi); } EXPORT_SYMBOL(system_sleep_update_wakeup); /** * system_sleep_allowed() - Returns if its okay to enter system low power modes */ Loading @@ -47,35 +59,15 @@ EXPORT_SYMBOL(system_sleep_allowed); /** * system_sleep_enter() - Activties done when entering system low power modes * * @sleep_val: The sleep duration in us. * * Returns 0 for success or error values from writing the timer value in the * hardware block. * Returns 0 for success or error values from writing the sleep/wake values to * the hardware block. */ int system_sleep_enter(uint64_t sleep_val) int system_sleep_enter(void) { int ret; if (IS_ERR_OR_NULL(rpmh_client)) return -EFAULT; ret = rpmh_flush(rpmh_client); if (ret) return ret; /* * Set up the wake up value offset from the current time. * Convert us to ns to allow div by 19.2 Mhz tick timer. */ if (sleep_val) { sleep_val *= NSEC_PER_USEC; do_div(sleep_val, NSEC_PER_SEC/ARCH_TIMER_HZ); sleep_val += arch_counter_get_cntvct(); } else { sleep_val = ~0ULL; } return setup_wakeup(sleep_val); return rpmh_flush(rpmh_client); } EXPORT_SYMBOL(system_sleep_enter); Loading include/clocksource/arm_arch_timer.h +5 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ struct arch_timer_kvm_info { extern u32 arch_timer_get_rate(void); extern u64 (*arch_timer_read_counter)(void); extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void); extern void arch_timer_mem_get_cval(u32 *lo, u32 *hi); #else static inline u32 arch_timer_get_rate(void) Loading @@ -72,6 +72,10 @@ static inline u64 arch_timer_read_counter(void) return 0; } static void arch_timer_mem_get_cval(u32 *lo, u32 *hi) { *lo = *hi = ~0U; } #endif #endif include/soc/qcom/system_pm.h +7 −2 Original line number Diff line number Diff line Loading @@ -14,13 +14,15 @@ #define __SOC_QCOM_SYS_PM_H__ #ifdef CONFIG_QTI_SYSTEM_PM int system_sleep_enter(uint64_t sleep_val); int system_sleep_enter(void); void system_sleep_exit(void); bool system_sleep_allowed(void); int system_sleep_update_wakeup(void); #else static inline int system_sleep_enter(uint64_t sleep_val) static inline int system_sleep_enter(void) { return -ENODEV; } static inline void system_sleep_exit(void) Loading @@ -29,6 +31,9 @@ static inline void system_sleep_exit(void) static inline bool system_sleep_allowed(void) { return false; } static inline int system_sleep_update_wakeup(void) { return -ENODEV; } #endif /* CONFIG_QTI_SYSTEM_PM */ #endif /* __SOC_QCOM_SYS_PM_H__ */ Loading
drivers/clocksource/arm_arch_timer.c +20 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ #define CNTFRQ 0x10 #define CNTP_TVAL 0x28 #define CNTP_CTL 0x2c #define CNTCVAL_LO 0x30 #define CNTCVAL_HI 0x34 #define CNTV_TVAL 0x38 #define CNTV_CTL 0x3c Loading Loading @@ -541,6 +543,23 @@ u32 arch_timer_get_rate(void) return arch_timer_rate; } void arch_timer_mem_get_cval(u32 *lo, u32 *hi) { u32 ctrl; *lo = *hi = ~0U; if (!arch_counter_base) return; ctrl = readl_relaxed_no_log(arch_counter_base + CNTV_CTL); if (ctrl & ARCH_TIMER_CTRL_ENABLE) { *lo = readl_relaxed_no_log(arch_counter_base + CNTCVAL_LO); *hi = readl_relaxed_no_log(arch_counter_base + CNTCVAL_HI); } } static u64 arch_counter_get_cntvct_mem(void) { u32 vct_lo, vct_hi, tmp_hi; Loading
drivers/cpuidle/lpm-levels.c +8 −10 Original line number Diff line number Diff line Loading @@ -1043,18 +1043,9 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, } if (level->notify_rpm) { uint64_t us; uint32_t pred_us; us = get_cluster_sleep_time(cluster, NULL, from_idle, &pred_us); us = us + 1; clear_predict_history(); clear_cl_predict_history(); if (system_sleep_enter(us)) if (system_sleep_enter()) return -EBUSY; } /* Notify cluster enter event after successfully config completion */ Loading Loading @@ -1261,6 +1252,13 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) state_id |= (level->psci_id & cluster->psci_mode_mask) << cluster->psci_mode_shift; (*aff_lvl)++; /* * We may have updated the broadcast timers, update * the wakeup value by reading the bc timer directly. */ if (level->notify_rpm) system_sleep_update_wakeup(); } unlock_and_return: spin_unlock(&cluster->sync_lock); Loading
drivers/soc/qcom/system_pm.c +20 −28 Original line number Diff line number Diff line Loading @@ -18,23 +18,35 @@ #include <soc/qcom/rpmh.h> #include <soc/qcom/system_pm.h> #define ARCH_TIMER_HZ (19200000UL) #include <clocksource/arm_arch_timer.h> #define PDC_TIME_VALID_SHIFT 31 #define PDC_TIME_UPPER_MASK 0xFFFFFF static struct rpmh_client *rpmh_client; static int setup_wakeup(uint64_t sleep_val) static int setup_wakeup(uint32_t lo, uint32_t hi) { struct tcs_cmd cmd[2] = { { 0 } }; cmd[0].data = (sleep_val >> 32) & PDC_TIME_UPPER_MASK; cmd[0].data = hi & PDC_TIME_UPPER_MASK; cmd[0].data |= 1 << PDC_TIME_VALID_SHIFT; cmd[1].data = sleep_val & 0xFFFFFFFF; cmd[1].data = lo; return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd)); } int system_sleep_update_wakeup(void) { uint32_t lo = ~0U, hi = ~0U; /* Read the hardware to get the most accurate value */ arch_timer_mem_get_cval(&lo, &hi); return setup_wakeup(lo, hi); } EXPORT_SYMBOL(system_sleep_update_wakeup); /** * system_sleep_allowed() - Returns if its okay to enter system low power modes */ Loading @@ -47,35 +59,15 @@ EXPORT_SYMBOL(system_sleep_allowed); /** * system_sleep_enter() - Activties done when entering system low power modes * * @sleep_val: The sleep duration in us. * * Returns 0 for success or error values from writing the timer value in the * hardware block. * Returns 0 for success or error values from writing the sleep/wake values to * the hardware block. */ int system_sleep_enter(uint64_t sleep_val) int system_sleep_enter(void) { int ret; if (IS_ERR_OR_NULL(rpmh_client)) return -EFAULT; ret = rpmh_flush(rpmh_client); if (ret) return ret; /* * Set up the wake up value offset from the current time. * Convert us to ns to allow div by 19.2 Mhz tick timer. */ if (sleep_val) { sleep_val *= NSEC_PER_USEC; do_div(sleep_val, NSEC_PER_SEC/ARCH_TIMER_HZ); sleep_val += arch_counter_get_cntvct(); } else { sleep_val = ~0ULL; } return setup_wakeup(sleep_val); return rpmh_flush(rpmh_client); } EXPORT_SYMBOL(system_sleep_enter); Loading
include/clocksource/arm_arch_timer.h +5 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ struct arch_timer_kvm_info { extern u32 arch_timer_get_rate(void); extern u64 (*arch_timer_read_counter)(void); extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void); extern void arch_timer_mem_get_cval(u32 *lo, u32 *hi); #else static inline u32 arch_timer_get_rate(void) Loading @@ -72,6 +72,10 @@ static inline u64 arch_timer_read_counter(void) return 0; } static void arch_timer_mem_get_cval(u32 *lo, u32 *hi) { *lo = *hi = ~0U; } #endif #endif
include/soc/qcom/system_pm.h +7 −2 Original line number Diff line number Diff line Loading @@ -14,13 +14,15 @@ #define __SOC_QCOM_SYS_PM_H__ #ifdef CONFIG_QTI_SYSTEM_PM int system_sleep_enter(uint64_t sleep_val); int system_sleep_enter(void); void system_sleep_exit(void); bool system_sleep_allowed(void); int system_sleep_update_wakeup(void); #else static inline int system_sleep_enter(uint64_t sleep_val) static inline int system_sleep_enter(void) { return -ENODEV; } static inline void system_sleep_exit(void) Loading @@ -29,6 +31,9 @@ static inline void system_sleep_exit(void) static inline bool system_sleep_allowed(void) { return false; } static inline int system_sleep_update_wakeup(void) { return -ENODEV; } #endif /* CONFIG_QTI_SYSTEM_PM */ #endif /* __SOC_QCOM_SYS_PM_H__ */