Loading Documentation/devicetree/bindings/arm/msm/lpm-levels.txt +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ Required properties: - compatible: "qcom,lpm-levels" Optional properties: - clocks: The clocks sources used by the cluster/cci mux. - clock-names: Name of the clocks for the above clocks. [Node bindings for qcom,pm-cluster] Required properties: - reg - The numeric cluster id Loading drivers/cpuidle/lpm-levels.c +41 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/clk.h> #include <linux/cpu.h> #include <linux/of.h> #include <linux/irqchip/msm-mpm-irq.h> Loading Loading @@ -87,6 +88,10 @@ static bool suspend_in_progress; static struct hrtimer lpm_hrtimer; static struct lpm_debug *lpm_debug; static phys_addr_t lpm_debug_phys; DEFINE_PER_CPU(struct clk *, cpu_clocks); static struct clk *l2_clk; static const int num_dbg_elements = 0x100; static int lpm_cpu_callback(struct notifier_block *cpu_nb, unsigned long action, void *hcpu); Loading Loading @@ -1002,6 +1007,7 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, const struct cpumask *cpumask = get_cpu_mask(dev->cpu); int64_t start_time = ktime_to_ns(ktime_get()), end_time; struct power_params *pwr_params; struct clk *cpu_clk = per_cpu(cpu_clocks, dev->cpu); if (idx < 0) return -EINVAL; Loading @@ -1016,6 +1022,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, trace_cpu_idle_enter(idx); lpm_stats_cpu_enter(idx, start_time); if (idx > 0 && cpu_clk && l2_clk) trace_cpu_idle_enter_cpu_freq(dev->cpu, clk_get_rate(cpu_clk), clk_get_rate(l2_clk)); if (need_resched()) goto exit; Loading @@ -1037,6 +1047,10 @@ exit: end_time = ktime_to_ns(ktime_get()); lpm_stats_cpu_exit(idx, end_time, success); if (idx > 0 && cpu_clk && l2_clk) trace_cpu_idle_exit_cpu_freq(dev->cpu, clk_get_rate(cpu_clk), clk_get_rate(l2_clk)); cluster_unprepare(cluster, cpumask, idx, true, end_time); cpu_unprepare(cluster, idx, true); Loading Loading @@ -1293,6 +1307,32 @@ static const struct platform_suspend_ops lpm_suspend_ops = { .wake = lpm_suspend_wake, }; static void lpm_clk_init(struct platform_device *pdev) { u32 cpu; char clk_name[] = "cpu??_clk"; for_each_possible_cpu(cpu) { struct clk *clk = NULL; snprintf(clk_name, sizeof(clk_name), "cpu%d_clk", cpu); clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(clk)) { pr_debug("%s: Could not get cpu_clk (-%ld)\n", __func__, PTR_ERR(clk)); clk = NULL; } per_cpu(cpu_clocks, cpu) = clk; } l2_clk = clk_get(&pdev->dev, "l2_clk"); if (IS_ERR(l2_clk)) { pr_debug("%s: Could not get l2_clk (-%ld)\n", __func__, PTR_ERR(l2_clk)); l2_clk = NULL; } } static int lpm_probe(struct platform_device *pdev) { int ret; Loading Loading @@ -1322,6 +1362,7 @@ static int lpm_probe(struct platform_device *pdev) put_cpu(); suspend_set_ops(&lpm_suspend_ops); hrtimer_init(&lpm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); lpm_clk_init(pdev); ret = remote_spin_lock_init(&scm_handoff_lock, SCM_HANDOFF_LOCK_ID); if (ret) { Loading include/trace/events/trace_msm_low_power.h +45 −1 Original line number Diff line number Diff line /* Copyright (c) 2012, 2014-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012, 2014-2016, The Linux Foundation. All rights reserved. * * 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 Loading Loading @@ -82,6 +82,50 @@ TRACE_EVENT(cpu_idle_exit, __entry->success) ); TRACE_EVENT(cpu_idle_enter_cpu_freq, TP_PROTO(int cpu, unsigned long cpu_clk, unsigned long l2_clk), TP_ARGS(cpu, cpu_clk, l2_clk), TP_STRUCT__entry( __field(int, cpu) __field(unsigned long, cpu_clk) __field(unsigned long, l2_clk) ), TP_fast_assign( __entry->cpu = cpu; __entry->cpu_clk = cpu_clk; __entry->l2_clk = l2_clk; ), TP_printk("cpu:%d cpu_clk:%luHZ l2_clk:%luHZ", __entry->cpu, __entry->cpu_clk, __entry->l2_clk) ); TRACE_EVENT(cpu_idle_exit_cpu_freq, TP_PROTO(int cpu, unsigned long cpu_clk, unsigned long l2_clk), TP_ARGS(cpu, cpu_clk, l2_clk), TP_STRUCT__entry( __field(int, cpu) __field(unsigned long, cpu_clk) __field(unsigned long, l2_clk) ), TP_fast_assign( __entry->cpu = cpu; __entry->cpu_clk = cpu_clk; __entry->l2_clk = l2_clk; ), TP_printk("cpu:%d cpu_clk:%luHZ l2_clk:%luHZ", __entry->cpu, __entry->cpu_clk, __entry->l2_clk) ); TRACE_EVENT(cluster_enter, TP_PROTO(const char *name, int index, unsigned long sync_cpus, Loading Loading
Documentation/devicetree/bindings/arm/msm/lpm-levels.txt +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ Required properties: - compatible: "qcom,lpm-levels" Optional properties: - clocks: The clocks sources used by the cluster/cci mux. - clock-names: Name of the clocks for the above clocks. [Node bindings for qcom,pm-cluster] Required properties: - reg - The numeric cluster id Loading
drivers/cpuidle/lpm-levels.c +41 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/clk.h> #include <linux/cpu.h> #include <linux/of.h> #include <linux/irqchip/msm-mpm-irq.h> Loading Loading @@ -87,6 +88,10 @@ static bool suspend_in_progress; static struct hrtimer lpm_hrtimer; static struct lpm_debug *lpm_debug; static phys_addr_t lpm_debug_phys; DEFINE_PER_CPU(struct clk *, cpu_clocks); static struct clk *l2_clk; static const int num_dbg_elements = 0x100; static int lpm_cpu_callback(struct notifier_block *cpu_nb, unsigned long action, void *hcpu); Loading Loading @@ -1002,6 +1007,7 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, const struct cpumask *cpumask = get_cpu_mask(dev->cpu); int64_t start_time = ktime_to_ns(ktime_get()), end_time; struct power_params *pwr_params; struct clk *cpu_clk = per_cpu(cpu_clocks, dev->cpu); if (idx < 0) return -EINVAL; Loading @@ -1016,6 +1022,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, trace_cpu_idle_enter(idx); lpm_stats_cpu_enter(idx, start_time); if (idx > 0 && cpu_clk && l2_clk) trace_cpu_idle_enter_cpu_freq(dev->cpu, clk_get_rate(cpu_clk), clk_get_rate(l2_clk)); if (need_resched()) goto exit; Loading @@ -1037,6 +1047,10 @@ exit: end_time = ktime_to_ns(ktime_get()); lpm_stats_cpu_exit(idx, end_time, success); if (idx > 0 && cpu_clk && l2_clk) trace_cpu_idle_exit_cpu_freq(dev->cpu, clk_get_rate(cpu_clk), clk_get_rate(l2_clk)); cluster_unprepare(cluster, cpumask, idx, true, end_time); cpu_unprepare(cluster, idx, true); Loading Loading @@ -1293,6 +1307,32 @@ static const struct platform_suspend_ops lpm_suspend_ops = { .wake = lpm_suspend_wake, }; static void lpm_clk_init(struct platform_device *pdev) { u32 cpu; char clk_name[] = "cpu??_clk"; for_each_possible_cpu(cpu) { struct clk *clk = NULL; snprintf(clk_name, sizeof(clk_name), "cpu%d_clk", cpu); clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(clk)) { pr_debug("%s: Could not get cpu_clk (-%ld)\n", __func__, PTR_ERR(clk)); clk = NULL; } per_cpu(cpu_clocks, cpu) = clk; } l2_clk = clk_get(&pdev->dev, "l2_clk"); if (IS_ERR(l2_clk)) { pr_debug("%s: Could not get l2_clk (-%ld)\n", __func__, PTR_ERR(l2_clk)); l2_clk = NULL; } } static int lpm_probe(struct platform_device *pdev) { int ret; Loading Loading @@ -1322,6 +1362,7 @@ static int lpm_probe(struct platform_device *pdev) put_cpu(); suspend_set_ops(&lpm_suspend_ops); hrtimer_init(&lpm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); lpm_clk_init(pdev); ret = remote_spin_lock_init(&scm_handoff_lock, SCM_HANDOFF_LOCK_ID); if (ret) { Loading
include/trace/events/trace_msm_low_power.h +45 −1 Original line number Diff line number Diff line /* Copyright (c) 2012, 2014-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012, 2014-2016, The Linux Foundation. All rights reserved. * * 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 Loading Loading @@ -82,6 +82,50 @@ TRACE_EVENT(cpu_idle_exit, __entry->success) ); TRACE_EVENT(cpu_idle_enter_cpu_freq, TP_PROTO(int cpu, unsigned long cpu_clk, unsigned long l2_clk), TP_ARGS(cpu, cpu_clk, l2_clk), TP_STRUCT__entry( __field(int, cpu) __field(unsigned long, cpu_clk) __field(unsigned long, l2_clk) ), TP_fast_assign( __entry->cpu = cpu; __entry->cpu_clk = cpu_clk; __entry->l2_clk = l2_clk; ), TP_printk("cpu:%d cpu_clk:%luHZ l2_clk:%luHZ", __entry->cpu, __entry->cpu_clk, __entry->l2_clk) ); TRACE_EVENT(cpu_idle_exit_cpu_freq, TP_PROTO(int cpu, unsigned long cpu_clk, unsigned long l2_clk), TP_ARGS(cpu, cpu_clk, l2_clk), TP_STRUCT__entry( __field(int, cpu) __field(unsigned long, cpu_clk) __field(unsigned long, l2_clk) ), TP_fast_assign( __entry->cpu = cpu; __entry->cpu_clk = cpu_clk; __entry->l2_clk = l2_clk; ), TP_printk("cpu:%d cpu_clk:%luHZ l2_clk:%luHZ", __entry->cpu, __entry->cpu_clk, __entry->l2_clk) ); TRACE_EVENT(cluster_enter, TP_PROTO(const char *name, int index, unsigned long sync_cpus, Loading