Loading drivers/cpuidle/lpm-levels.c +64 −50 Original line number Original line Diff line number Diff line Loading @@ -39,8 +39,8 @@ #include <linux/sched/stat.h> #include <linux/sched/stat.h> #include <soc/qcom/pm.h> #include <soc/qcom/pm.h> #include <soc/qcom/event_timer.h> #include <soc/qcom/event_timer.h> #include <soc/qcom/lpm_levels.h> #include <soc/qcom/lpm-stats.h> #include <soc/qcom/lpm-stats.h> #include <soc/qcom/system_pm.h> #include <soc/qcom/minidump.h> #include <soc/qcom/minidump.h> #include <asm/arch_timer.h> #include <asm/arch_timer.h> #include <asm/suspend.h> #include <asm/suspend.h> Loading Loading @@ -79,6 +79,9 @@ struct lpm_debug { uint32_t arg4; uint32_t arg4; }; }; static struct system_pm_ops *sys_pm_ops; struct lpm_cluster *lpm_root_node; struct lpm_cluster *lpm_root_node; #define MAXSAMPLES 5 #define MAXSAMPLES 5 Loading @@ -93,6 +96,8 @@ static uint32_t tmr_add = 1000; module_param_named(tmr_add, tmr_add, uint, 0664); module_param_named(tmr_add, tmr_add, uint, 0664); static uint32_t ref_premature_cnt = 1; static uint32_t ref_premature_cnt = 1; module_param_named(ref_premature_cnt, ref_premature_cnt, uint, 0664); static uint32_t bias_hyst; static uint32_t bias_hyst; module_param_named(bias_hyst, bias_hyst, uint, 0664); module_param_named(bias_hyst, bias_hyst, uint, 0664); Loading Loading @@ -123,11 +128,6 @@ static void cluster_prepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle, const struct cpumask *cpu, int child_idx, bool from_idle, int64_t time); int64_t time); static int msm_pm_sleep_time_override; module_param_named(sleep_time_override, msm_pm_sleep_time_override, int, 0664); static uint64_t suspend_wake_time; static bool print_parsed_dt; static bool print_parsed_dt; module_param_named(print_parsed_dt, print_parsed_dt, bool, 0664); module_param_named(print_parsed_dt, print_parsed_dt, bool, 0664); Loading @@ -145,20 +145,15 @@ s32 msm_cpuidle_get_deep_idle_latency(void) } } EXPORT_SYMBOL(msm_cpuidle_get_deep_idle_latency); EXPORT_SYMBOL(msm_cpuidle_get_deep_idle_latency); void lpm_suspend_wake_time(uint64_t wakeup_time) uint32_t register_system_pm_ops(struct system_pm_ops *pm_ops) { { if (wakeup_time <= 0) { if (sys_pm_ops) suspend_wake_time = msm_pm_sleep_time_override; return -EUSERS; return; } if (msm_pm_sleep_time_override && sys_pm_ops = pm_ops; (msm_pm_sleep_time_override < wakeup_time)) suspend_wake_time = msm_pm_sleep_time_override; return 0; else suspend_wake_time = wakeup_time; } } EXPORT_SYMBOL(lpm_suspend_wake_time); static uint32_t least_cluster_latency(struct lpm_cluster *cluster, static uint32_t least_cluster_latency(struct lpm_cluster *cluster, struct latency_level *lat_level) struct latency_level *lat_level) Loading Loading @@ -703,28 +698,40 @@ static int cpu_power_select(struct cpuidle_device *dev, return best_level; return best_level; } } static unsigned int get_next_online_cpu(bool from_idle) { unsigned int cpu; ktime_t next_event; unsigned int next_cpu = raw_smp_processor_id(); if (!from_idle) return next_cpu; next_event = KTIME_MAX; for_each_online_cpu(cpu) { ktime_t *next_event_c; next_event_c = get_next_event_cpu(cpu); if (*next_event_c < next_event) { next_event = *next_event_c; next_cpu = cpu; } } return next_cpu; } static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, struct cpumask *mask, bool from_idle, uint32_t *pred_time) bool from_idle, uint32_t *pred_time) { { int cpu; int cpu; int next_cpu = raw_smp_processor_id(); ktime_t next_event; ktime_t next_event; struct cpumask online_cpus_in_cluster; struct cpumask online_cpus_in_cluster; struct lpm_history *history; struct lpm_history *history; int64_t prediction = LONG_MAX; int64_t prediction = LONG_MAX; next_event = KTIME_MAX; if (!from_idle) if (!suspend_wake_time) suspend_wake_time = msm_pm_sleep_time_override; if (!from_idle) { if (mask) cpumask_copy(mask, cpumask_of(raw_smp_processor_id())); if (!suspend_wake_time) return ~0ULL; return ~0ULL; else return USEC_PER_SEC * suspend_wake_time; } next_event = KTIME_MAX; cpumask_and(&online_cpus_in_cluster, cpumask_and(&online_cpus_in_cluster, &cluster->num_children_in_sync, cpu_online_mask); &cluster->num_children_in_sync, cpu_online_mask); Loading @@ -732,10 +739,8 @@ static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, ktime_t *next_event_c; ktime_t *next_event_c; next_event_c = get_next_event_cpu(cpu); next_event_c = get_next_event_cpu(cpu); if (*next_event_c < next_event) { if (*next_event_c < next_event) next_event = *next_event_c; next_event = *next_event_c; next_cpu = cpu; } if (from_idle && lpm_prediction) { if (from_idle && lpm_prediction) { history = &per_cpu(hist, cpu); history = &per_cpu(hist, cpu); Loading @@ -744,9 +749,6 @@ static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, } } } } if (mask) cpumask_copy(mask, cpumask_of(next_cpu)); if (from_idle && lpm_prediction) { if (from_idle && lpm_prediction) { if (prediction > ktime_to_us(ktime_get())) if (prediction > ktime_to_us(ktime_get())) *pred_time = prediction - ktime_to_us(ktime_get()); *pred_time = prediction - ktime_to_us(ktime_get()); Loading Loading @@ -929,7 +931,7 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle, if (!cluster) if (!cluster) return -EINVAL; return -EINVAL; sleep_us = (uint32_t)get_cluster_sleep_time(cluster, NULL, sleep_us = (uint32_t)get_cluster_sleep_time(cluster, from_idle, &cpupred_us); from_idle, &cpupred_us); if (from_idle) { if (from_idle) { Loading Loading @@ -980,8 +982,12 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle, if (suspend_in_progress && from_idle && level->notify_rpm) if (suspend_in_progress && from_idle && level->notify_rpm) continue; continue; if (level->notify_rpm && !system_sleep_allowed()) if (level->notify_rpm) { if (!(sys_pm_ops && sys_pm_ops->sleep_allowed)) continue; continue; if (!sys_pm_ops->sleep_allowed()) continue; } best_level = i; best_level = i; Loading Loading @@ -1015,6 +1021,11 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, bool from_idle, int predicted) bool from_idle, int predicted) { { struct lpm_cluster_level *level = &cluster->levels[idx]; struct lpm_cluster_level *level = &cluster->levels[idx]; struct cpumask online_cpus, cpumask; unsigned int cpu; cpumask_and(&online_cpus, &cluster->num_children_in_sync, cpu_online_mask); if (!cpumask_equal(&cluster->num_children_in_sync, &cluster->child_cpus) if (!cpumask_equal(&cluster->num_children_in_sync, &cluster->child_cpus) || is_IPI_pending(&cluster->num_children_in_sync)) { || is_IPI_pending(&cluster->num_children_in_sync)) { Loading @@ -1036,9 +1047,12 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, } } if (level->notify_rpm) { if (level->notify_rpm) { cpu = get_next_online_cpu(from_idle); cpumask_copy(&cpumask, cpumask_of(cpu)); clear_predict_history(); clear_predict_history(); clear_cl_predict_history(); clear_cl_predict_history(); if (system_sleep_enter()) if (sys_pm_ops && sys_pm_ops->enter) if ((sys_pm_ops->enter(&cpumask))) return -EBUSY; return -EBUSY; } } /* Notify cluster enter event after successfully config completion */ /* Notify cluster enter event after successfully config completion */ Loading Loading @@ -1170,7 +1184,8 @@ static void cluster_unprepare(struct lpm_cluster *cluster, level = &cluster->levels[cluster->last_level]; level = &cluster->levels[cluster->last_level]; if (level->notify_rpm) if (level->notify_rpm) system_sleep_exit(); if (sys_pm_ops && sys_pm_ops->exit) sys_pm_ops->exit(); update_debug_pc_event(CLUSTER_EXIT, cluster->last_level, update_debug_pc_event(CLUSTER_EXIT, cluster->last_level, cluster->num_children_in_sync.bits[0], cluster->num_children_in_sync.bits[0], Loading Loading @@ -1223,7 +1238,8 @@ static inline void cpu_unprepare(struct lpm_cpu *cpu, int cpu_index, cpu_pm_exit(); cpu_pm_exit(); } } int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) static int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl, bool from_idle) { { int state_id = 0; int state_id = 0; Loading @@ -1236,7 +1252,7 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) &cluster->child_cpus)) &cluster->child_cpus)) goto unlock_and_return; goto unlock_and_return; state_id |= get_cluster_id(cluster->parent, aff_lvl); state_id |= get_cluster_id(cluster->parent, aff_lvl, from_idle); if (cluster->last_level != cluster->default_level) { if (cluster->last_level != cluster->default_level) { struct lpm_cluster_level *level struct lpm_cluster_level *level Loading @@ -1250,7 +1266,8 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) * the wakeup value by reading the bc timer directly. * the wakeup value by reading the bc timer directly. */ */ if (level->notify_rpm) if (level->notify_rpm) system_sleep_update_wakeup(); if (sys_pm_ops && sys_pm_ops->update_wakeup) sys_pm_ops->update_wakeup(from_idle); if (level->psci_id) if (level->psci_id) (*aff_lvl)++; (*aff_lvl)++; } } Loading Loading @@ -1279,7 +1296,7 @@ static bool psci_enter_sleep(struct lpm_cpu *cpu, int idx, bool from_idle) return success; return success; } } state_id = get_cluster_id(cpu->parent, &affinity_level); state_id = get_cluster_id(cpu->parent, &affinity_level, from_idle); power_state = PSCI_POWER_STATE(cpu->levels[idx].is_reset); power_state = PSCI_POWER_STATE(cpu->levels[idx].is_reset); affinity_level = PSCI_AFFINITY_LEVEL(affinity_level); affinity_level = PSCI_AFFINITY_LEVEL(affinity_level); state_id |= power_state | affinity_level | cpu->levels[idx].psci_id; state_id |= power_state | affinity_level | cpu->levels[idx].psci_id; Loading Loading @@ -1352,9 +1369,6 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, const struct cpumask *cpumask = get_cpu_mask(dev->cpu); const struct cpumask *cpumask = get_cpu_mask(dev->cpu); ktime_t start = ktime_get(); ktime_t start = ktime_get(); uint64_t start_time = ktime_to_ns(start), end_time; uint64_t start_time = ktime_to_ns(start), end_time; struct power_params *pwr_params; pwr_params = &cpu->levels[idx].pwr; cpu_prepare(cpu, idx, true); cpu_prepare(cpu, idx, true); cluster_prepare(cpu->parent, cpumask, idx, true, start_time); cluster_prepare(cpu->parent, cpumask, idx, true, start_time); Loading Loading @@ -1724,7 +1738,7 @@ static int __init lpm_levels_module_init(void) int cpu; int cpu; for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) { rc = arm_cpuidle_init(smp_processor_id()); rc = arm_cpuidle_init(cpu); if (rc) { if (rc) { pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc); pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc); return rc; return rc; Loading drivers/cpuidle/lpm-levels.h +0 −2 Original line number Original line Diff line number Diff line Loading @@ -108,8 +108,6 @@ struct lpm_cluster { struct hrtimer histtimer; struct hrtimer histtimer; }; }; void lpm_suspend_wake_time(uint64_t wakeup_time); struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev); struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev); void free_cluster_node(struct lpm_cluster *cluster); void free_cluster_node(struct lpm_cluster *cluster); void cluster_dt_walkthrough(struct lpm_cluster *cluster); void cluster_dt_walkthrough(struct lpm_cluster *cluster); Loading drivers/soc/qcom/system_pm.c +13 −15 Original line number Original line Diff line number Diff line Loading @@ -13,11 +13,9 @@ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/platform_device.h> #include <soc/qcom/rpmh.h> #include <soc/qcom/rpmh.h> #include <soc/qcom/system_pm.h> #include <clocksource/arm_arch_timer.h> #include <clocksource/arm_arch_timer.h> #include <soc/qcom/lpm_levels.h> #define PDC_TIME_VALID_SHIFT 31 #define PDC_TIME_VALID_SHIFT 31 #define PDC_TIME_UPPER_MASK 0xFFFFFF #define PDC_TIME_UPPER_MASK 0xFFFFFF Loading @@ -35,7 +33,7 @@ static int setup_wakeup(uint32_t lo, uint32_t hi) return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd)); return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd)); } } int system_sleep_update_wakeup(void) static int system_sleep_update_wakeup(bool from_idle) { { uint32_t lo = ~0U, hi = ~0U; uint32_t lo = ~0U, hi = ~0U; Loading @@ -44,16 +42,14 @@ int system_sleep_update_wakeup(void) return setup_wakeup(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 * system_sleep_allowed() - Returns if its okay to enter system low power modes */ */ bool system_sleep_allowed(void) static bool system_sleep_allowed(void) { { return (rpmh_ctrlr_idle(rpmh_client) == 0); return (rpmh_ctrlr_idle(rpmh_client) == 0); } } EXPORT_SYMBOL(system_sleep_allowed); /** /** * system_sleep_enter() - Activties done when entering system low power modes * system_sleep_enter() - Activties done when entering system low power modes Loading @@ -61,22 +57,24 @@ EXPORT_SYMBOL(system_sleep_allowed); * Returns 0 for success or error values from writing the sleep/wake values to * Returns 0 for success or error values from writing the sleep/wake values to * the hardware block. * the hardware block. */ */ int system_sleep_enter(void) static int system_sleep_enter(struct cpumask *mask) { { if (IS_ERR_OR_NULL(rpmh_client)) return -EFAULT; return rpmh_flush(rpmh_client); return rpmh_flush(rpmh_client); } } EXPORT_SYMBOL(system_sleep_enter); /** /** * system_sleep_exit() - Activities done when exiting system low power modes * system_sleep_exit() - Activities done when exiting system low power modes */ */ void system_sleep_exit(void) static void system_sleep_exit(void) { { } } EXPORT_SYMBOL(system_sleep_exit); static struct system_pm_ops pm_ops = { .enter = system_sleep_enter, .exit = system_sleep_exit, .update_wakeup = system_sleep_update_wakeup, .sleep_allowed = system_sleep_allowed, }; static int sys_pm_probe(struct platform_device *pdev) static int sys_pm_probe(struct platform_device *pdev) { { Loading @@ -84,7 +82,7 @@ static int sys_pm_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(rpmh_client)) if (IS_ERR_OR_NULL(rpmh_client)) return PTR_ERR(rpmh_client); return PTR_ERR(rpmh_client); return 0; return register_system_pm_ops(&pm_ops); } } static const struct of_device_id sys_pm_drv_match[] = { static const struct of_device_id sys_pm_drv_match[] = { Loading include/soc/qcom/system_pm.h→include/soc/qcom/lpm_levels.h +30 −0 Original line number Original line Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading @@ -10,30 +10,21 @@ * GNU General Public License for more details. * GNU General Public License for more details. * * */ */ #ifndef __SOC_QCOM_SYS_PM_H__ #ifndef __SOC_QCOM_LPM_LEVEL_H__ #define __SOC_QCOM_SYS_PM_H__ #define __SOC_QCOM_LPM_LEVEL_H__ #ifdef CONFIG_QTI_SYSTEM_PM struct system_pm_ops { int system_sleep_enter(void); int (*enter)(struct cpumask *mask); void (*exit)(void); void system_sleep_exit(void); int (*update_wakeup)(bool); bool (*sleep_allowed)(void); bool system_sleep_allowed(void); }; int system_sleep_update_wakeup(void); #ifdef CONFIG_MSM_PM uint32_t register_system_pm_ops(struct system_pm_ops *pm_ops); #else #else static inline int system_sleep_enter(void) static inline uint32_t register_system_pm_ops(struct system_pm_ops *pm_ops) { return -ENODEV; } { return -ENODEV; } #endif static inline void system_sleep_exit(void) #endif { } 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/cpuidle/lpm-levels.c +64 −50 Original line number Original line Diff line number Diff line Loading @@ -39,8 +39,8 @@ #include <linux/sched/stat.h> #include <linux/sched/stat.h> #include <soc/qcom/pm.h> #include <soc/qcom/pm.h> #include <soc/qcom/event_timer.h> #include <soc/qcom/event_timer.h> #include <soc/qcom/lpm_levels.h> #include <soc/qcom/lpm-stats.h> #include <soc/qcom/lpm-stats.h> #include <soc/qcom/system_pm.h> #include <soc/qcom/minidump.h> #include <soc/qcom/minidump.h> #include <asm/arch_timer.h> #include <asm/arch_timer.h> #include <asm/suspend.h> #include <asm/suspend.h> Loading Loading @@ -79,6 +79,9 @@ struct lpm_debug { uint32_t arg4; uint32_t arg4; }; }; static struct system_pm_ops *sys_pm_ops; struct lpm_cluster *lpm_root_node; struct lpm_cluster *lpm_root_node; #define MAXSAMPLES 5 #define MAXSAMPLES 5 Loading @@ -93,6 +96,8 @@ static uint32_t tmr_add = 1000; module_param_named(tmr_add, tmr_add, uint, 0664); module_param_named(tmr_add, tmr_add, uint, 0664); static uint32_t ref_premature_cnt = 1; static uint32_t ref_premature_cnt = 1; module_param_named(ref_premature_cnt, ref_premature_cnt, uint, 0664); static uint32_t bias_hyst; static uint32_t bias_hyst; module_param_named(bias_hyst, bias_hyst, uint, 0664); module_param_named(bias_hyst, bias_hyst, uint, 0664); Loading Loading @@ -123,11 +128,6 @@ static void cluster_prepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle, const struct cpumask *cpu, int child_idx, bool from_idle, int64_t time); int64_t time); static int msm_pm_sleep_time_override; module_param_named(sleep_time_override, msm_pm_sleep_time_override, int, 0664); static uint64_t suspend_wake_time; static bool print_parsed_dt; static bool print_parsed_dt; module_param_named(print_parsed_dt, print_parsed_dt, bool, 0664); module_param_named(print_parsed_dt, print_parsed_dt, bool, 0664); Loading @@ -145,20 +145,15 @@ s32 msm_cpuidle_get_deep_idle_latency(void) } } EXPORT_SYMBOL(msm_cpuidle_get_deep_idle_latency); EXPORT_SYMBOL(msm_cpuidle_get_deep_idle_latency); void lpm_suspend_wake_time(uint64_t wakeup_time) uint32_t register_system_pm_ops(struct system_pm_ops *pm_ops) { { if (wakeup_time <= 0) { if (sys_pm_ops) suspend_wake_time = msm_pm_sleep_time_override; return -EUSERS; return; } if (msm_pm_sleep_time_override && sys_pm_ops = pm_ops; (msm_pm_sleep_time_override < wakeup_time)) suspend_wake_time = msm_pm_sleep_time_override; return 0; else suspend_wake_time = wakeup_time; } } EXPORT_SYMBOL(lpm_suspend_wake_time); static uint32_t least_cluster_latency(struct lpm_cluster *cluster, static uint32_t least_cluster_latency(struct lpm_cluster *cluster, struct latency_level *lat_level) struct latency_level *lat_level) Loading Loading @@ -703,28 +698,40 @@ static int cpu_power_select(struct cpuidle_device *dev, return best_level; return best_level; } } static unsigned int get_next_online_cpu(bool from_idle) { unsigned int cpu; ktime_t next_event; unsigned int next_cpu = raw_smp_processor_id(); if (!from_idle) return next_cpu; next_event = KTIME_MAX; for_each_online_cpu(cpu) { ktime_t *next_event_c; next_event_c = get_next_event_cpu(cpu); if (*next_event_c < next_event) { next_event = *next_event_c; next_cpu = cpu; } } return next_cpu; } static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, struct cpumask *mask, bool from_idle, uint32_t *pred_time) bool from_idle, uint32_t *pred_time) { { int cpu; int cpu; int next_cpu = raw_smp_processor_id(); ktime_t next_event; ktime_t next_event; struct cpumask online_cpus_in_cluster; struct cpumask online_cpus_in_cluster; struct lpm_history *history; struct lpm_history *history; int64_t prediction = LONG_MAX; int64_t prediction = LONG_MAX; next_event = KTIME_MAX; if (!from_idle) if (!suspend_wake_time) suspend_wake_time = msm_pm_sleep_time_override; if (!from_idle) { if (mask) cpumask_copy(mask, cpumask_of(raw_smp_processor_id())); if (!suspend_wake_time) return ~0ULL; return ~0ULL; else return USEC_PER_SEC * suspend_wake_time; } next_event = KTIME_MAX; cpumask_and(&online_cpus_in_cluster, cpumask_and(&online_cpus_in_cluster, &cluster->num_children_in_sync, cpu_online_mask); &cluster->num_children_in_sync, cpu_online_mask); Loading @@ -732,10 +739,8 @@ static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, ktime_t *next_event_c; ktime_t *next_event_c; next_event_c = get_next_event_cpu(cpu); next_event_c = get_next_event_cpu(cpu); if (*next_event_c < next_event) { if (*next_event_c < next_event) next_event = *next_event_c; next_event = *next_event_c; next_cpu = cpu; } if (from_idle && lpm_prediction) { if (from_idle && lpm_prediction) { history = &per_cpu(hist, cpu); history = &per_cpu(hist, cpu); Loading @@ -744,9 +749,6 @@ static uint64_t get_cluster_sleep_time(struct lpm_cluster *cluster, } } } } if (mask) cpumask_copy(mask, cpumask_of(next_cpu)); if (from_idle && lpm_prediction) { if (from_idle && lpm_prediction) { if (prediction > ktime_to_us(ktime_get())) if (prediction > ktime_to_us(ktime_get())) *pred_time = prediction - ktime_to_us(ktime_get()); *pred_time = prediction - ktime_to_us(ktime_get()); Loading Loading @@ -929,7 +931,7 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle, if (!cluster) if (!cluster) return -EINVAL; return -EINVAL; sleep_us = (uint32_t)get_cluster_sleep_time(cluster, NULL, sleep_us = (uint32_t)get_cluster_sleep_time(cluster, from_idle, &cpupred_us); from_idle, &cpupred_us); if (from_idle) { if (from_idle) { Loading Loading @@ -980,8 +982,12 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle, if (suspend_in_progress && from_idle && level->notify_rpm) if (suspend_in_progress && from_idle && level->notify_rpm) continue; continue; if (level->notify_rpm && !system_sleep_allowed()) if (level->notify_rpm) { if (!(sys_pm_ops && sys_pm_ops->sleep_allowed)) continue; continue; if (!sys_pm_ops->sleep_allowed()) continue; } best_level = i; best_level = i; Loading Loading @@ -1015,6 +1021,11 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, bool from_idle, int predicted) bool from_idle, int predicted) { { struct lpm_cluster_level *level = &cluster->levels[idx]; struct lpm_cluster_level *level = &cluster->levels[idx]; struct cpumask online_cpus, cpumask; unsigned int cpu; cpumask_and(&online_cpus, &cluster->num_children_in_sync, cpu_online_mask); if (!cpumask_equal(&cluster->num_children_in_sync, &cluster->child_cpus) if (!cpumask_equal(&cluster->num_children_in_sync, &cluster->child_cpus) || is_IPI_pending(&cluster->num_children_in_sync)) { || is_IPI_pending(&cluster->num_children_in_sync)) { Loading @@ -1036,9 +1047,12 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, } } if (level->notify_rpm) { if (level->notify_rpm) { cpu = get_next_online_cpu(from_idle); cpumask_copy(&cpumask, cpumask_of(cpu)); clear_predict_history(); clear_predict_history(); clear_cl_predict_history(); clear_cl_predict_history(); if (system_sleep_enter()) if (sys_pm_ops && sys_pm_ops->enter) if ((sys_pm_ops->enter(&cpumask))) return -EBUSY; return -EBUSY; } } /* Notify cluster enter event after successfully config completion */ /* Notify cluster enter event after successfully config completion */ Loading Loading @@ -1170,7 +1184,8 @@ static void cluster_unprepare(struct lpm_cluster *cluster, level = &cluster->levels[cluster->last_level]; level = &cluster->levels[cluster->last_level]; if (level->notify_rpm) if (level->notify_rpm) system_sleep_exit(); if (sys_pm_ops && sys_pm_ops->exit) sys_pm_ops->exit(); update_debug_pc_event(CLUSTER_EXIT, cluster->last_level, update_debug_pc_event(CLUSTER_EXIT, cluster->last_level, cluster->num_children_in_sync.bits[0], cluster->num_children_in_sync.bits[0], Loading Loading @@ -1223,7 +1238,8 @@ static inline void cpu_unprepare(struct lpm_cpu *cpu, int cpu_index, cpu_pm_exit(); cpu_pm_exit(); } } int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) static int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl, bool from_idle) { { int state_id = 0; int state_id = 0; Loading @@ -1236,7 +1252,7 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) &cluster->child_cpus)) &cluster->child_cpus)) goto unlock_and_return; goto unlock_and_return; state_id |= get_cluster_id(cluster->parent, aff_lvl); state_id |= get_cluster_id(cluster->parent, aff_lvl, from_idle); if (cluster->last_level != cluster->default_level) { if (cluster->last_level != cluster->default_level) { struct lpm_cluster_level *level struct lpm_cluster_level *level Loading @@ -1250,7 +1266,8 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl) * the wakeup value by reading the bc timer directly. * the wakeup value by reading the bc timer directly. */ */ if (level->notify_rpm) if (level->notify_rpm) system_sleep_update_wakeup(); if (sys_pm_ops && sys_pm_ops->update_wakeup) sys_pm_ops->update_wakeup(from_idle); if (level->psci_id) if (level->psci_id) (*aff_lvl)++; (*aff_lvl)++; } } Loading Loading @@ -1279,7 +1296,7 @@ static bool psci_enter_sleep(struct lpm_cpu *cpu, int idx, bool from_idle) return success; return success; } } state_id = get_cluster_id(cpu->parent, &affinity_level); state_id = get_cluster_id(cpu->parent, &affinity_level, from_idle); power_state = PSCI_POWER_STATE(cpu->levels[idx].is_reset); power_state = PSCI_POWER_STATE(cpu->levels[idx].is_reset); affinity_level = PSCI_AFFINITY_LEVEL(affinity_level); affinity_level = PSCI_AFFINITY_LEVEL(affinity_level); state_id |= power_state | affinity_level | cpu->levels[idx].psci_id; state_id |= power_state | affinity_level | cpu->levels[idx].psci_id; Loading Loading @@ -1352,9 +1369,6 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, const struct cpumask *cpumask = get_cpu_mask(dev->cpu); const struct cpumask *cpumask = get_cpu_mask(dev->cpu); ktime_t start = ktime_get(); ktime_t start = ktime_get(); uint64_t start_time = ktime_to_ns(start), end_time; uint64_t start_time = ktime_to_ns(start), end_time; struct power_params *pwr_params; pwr_params = &cpu->levels[idx].pwr; cpu_prepare(cpu, idx, true); cpu_prepare(cpu, idx, true); cluster_prepare(cpu->parent, cpumask, idx, true, start_time); cluster_prepare(cpu->parent, cpumask, idx, true, start_time); Loading Loading @@ -1724,7 +1738,7 @@ static int __init lpm_levels_module_init(void) int cpu; int cpu; for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) { rc = arm_cpuidle_init(smp_processor_id()); rc = arm_cpuidle_init(cpu); if (rc) { if (rc) { pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc); pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc); return rc; return rc; Loading
drivers/cpuidle/lpm-levels.h +0 −2 Original line number Original line Diff line number Diff line Loading @@ -108,8 +108,6 @@ struct lpm_cluster { struct hrtimer histtimer; struct hrtimer histtimer; }; }; void lpm_suspend_wake_time(uint64_t wakeup_time); struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev); struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev); void free_cluster_node(struct lpm_cluster *cluster); void free_cluster_node(struct lpm_cluster *cluster); void cluster_dt_walkthrough(struct lpm_cluster *cluster); void cluster_dt_walkthrough(struct lpm_cluster *cluster); Loading
drivers/soc/qcom/system_pm.c +13 −15 Original line number Original line Diff line number Diff line Loading @@ -13,11 +13,9 @@ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/platform_device.h> #include <soc/qcom/rpmh.h> #include <soc/qcom/rpmh.h> #include <soc/qcom/system_pm.h> #include <clocksource/arm_arch_timer.h> #include <clocksource/arm_arch_timer.h> #include <soc/qcom/lpm_levels.h> #define PDC_TIME_VALID_SHIFT 31 #define PDC_TIME_VALID_SHIFT 31 #define PDC_TIME_UPPER_MASK 0xFFFFFF #define PDC_TIME_UPPER_MASK 0xFFFFFF Loading @@ -35,7 +33,7 @@ static int setup_wakeup(uint32_t lo, uint32_t hi) return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd)); return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd)); } } int system_sleep_update_wakeup(void) static int system_sleep_update_wakeup(bool from_idle) { { uint32_t lo = ~0U, hi = ~0U; uint32_t lo = ~0U, hi = ~0U; Loading @@ -44,16 +42,14 @@ int system_sleep_update_wakeup(void) return setup_wakeup(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 * system_sleep_allowed() - Returns if its okay to enter system low power modes */ */ bool system_sleep_allowed(void) static bool system_sleep_allowed(void) { { return (rpmh_ctrlr_idle(rpmh_client) == 0); return (rpmh_ctrlr_idle(rpmh_client) == 0); } } EXPORT_SYMBOL(system_sleep_allowed); /** /** * system_sleep_enter() - Activties done when entering system low power modes * system_sleep_enter() - Activties done when entering system low power modes Loading @@ -61,22 +57,24 @@ EXPORT_SYMBOL(system_sleep_allowed); * Returns 0 for success or error values from writing the sleep/wake values to * Returns 0 for success or error values from writing the sleep/wake values to * the hardware block. * the hardware block. */ */ int system_sleep_enter(void) static int system_sleep_enter(struct cpumask *mask) { { if (IS_ERR_OR_NULL(rpmh_client)) return -EFAULT; return rpmh_flush(rpmh_client); return rpmh_flush(rpmh_client); } } EXPORT_SYMBOL(system_sleep_enter); /** /** * system_sleep_exit() - Activities done when exiting system low power modes * system_sleep_exit() - Activities done when exiting system low power modes */ */ void system_sleep_exit(void) static void system_sleep_exit(void) { { } } EXPORT_SYMBOL(system_sleep_exit); static struct system_pm_ops pm_ops = { .enter = system_sleep_enter, .exit = system_sleep_exit, .update_wakeup = system_sleep_update_wakeup, .sleep_allowed = system_sleep_allowed, }; static int sys_pm_probe(struct platform_device *pdev) static int sys_pm_probe(struct platform_device *pdev) { { Loading @@ -84,7 +82,7 @@ static int sys_pm_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(rpmh_client)) if (IS_ERR_OR_NULL(rpmh_client)) return PTR_ERR(rpmh_client); return PTR_ERR(rpmh_client); return 0; return register_system_pm_ops(&pm_ops); } } static const struct of_device_id sys_pm_drv_match[] = { static const struct of_device_id sys_pm_drv_match[] = { Loading
include/soc/qcom/system_pm.h→include/soc/qcom/lpm_levels.h +30 −0 Original line number Original line Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading @@ -10,30 +10,21 @@ * GNU General Public License for more details. * GNU General Public License for more details. * * */ */ #ifndef __SOC_QCOM_SYS_PM_H__ #ifndef __SOC_QCOM_LPM_LEVEL_H__ #define __SOC_QCOM_SYS_PM_H__ #define __SOC_QCOM_LPM_LEVEL_H__ #ifdef CONFIG_QTI_SYSTEM_PM struct system_pm_ops { int system_sleep_enter(void); int (*enter)(struct cpumask *mask); void (*exit)(void); void system_sleep_exit(void); int (*update_wakeup)(bool); bool (*sleep_allowed)(void); bool system_sleep_allowed(void); }; int system_sleep_update_wakeup(void); #ifdef CONFIG_MSM_PM uint32_t register_system_pm_ops(struct system_pm_ops *pm_ops); #else #else static inline int system_sleep_enter(void) static inline uint32_t register_system_pm_ops(struct system_pm_ops *pm_ops) { return -ENODEV; } { return -ENODEV; } #endif static inline void system_sleep_exit(void) #endif { } 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__ */