blob: 0b598c08b0429f494313ebd2b5d6f350367c4693 [file] [log] [blame]
Raghavendra Kakarlafbcacdf2018-03-09 18:27:33 +05301/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <soc/qcom/pm.h>
14#include <soc/qcom/spm.h>
15
16#define NR_LPM_LEVELS 8
17#define MAXSAMPLES 5
18#define CLUST_SMPL_INVLD_TIME 40000
Raghavendra Kakarlafbcacdf2018-03-09 18:27:33 +053019#define DEFAULT_PREMATURE_CNT 3
20#define DEFAULT_STDDEV 100
21#define DEFAULT_TIMER_ADD 100
22#define TIMER_ADD_LOW 100
23#define TIMER_ADD_HIGH 1500
24#define STDDEV_LOW 100
25#define STDDEV_HIGH 1000
26#define PREMATURE_CNT_LOW 1
27#define PREMATURE_CNT_HIGH 5
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070028
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070029struct power_params {
30 uint32_t latency_us; /* Enter + Exit latency */
31 uint32_t ss_power; /* Steady state power */
32 uint32_t energy_overhead; /* Enter + exit over head */
33 uint32_t time_overhead_us; /* Enter + exit overhead */
34 uint32_t residencies[NR_LPM_LEVELS];
35 uint32_t min_residency;
36 uint32_t max_residency;
37};
38
39struct lpm_cpu_level {
40 const char *name;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070041 bool use_bc_timer;
42 struct power_params pwr;
43 unsigned int psci_id;
44 bool is_reset;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070045 int reset_level;
46};
47
48struct lpm_cpu {
Mahesh Sivasubramanian168922d2017-06-09 09:47:52 -060049 struct list_head list;
50 struct cpumask related_cpus;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070051 struct lpm_cpu_level levels[NR_LPM_LEVELS];
52 int nlevels;
53 unsigned int psci_mode_shift;
54 unsigned int psci_mode_mask;
Raghavendra Kakarlafbcacdf2018-03-09 18:27:33 +053055 uint32_t ref_stddev;
56 uint32_t ref_premature_cnt;
57 uint32_t tmr_add;
Mahesh Sivasubramanian73810922017-10-16 16:46:56 -060058 bool lpm_prediction;
Mahesh Sivasubramanian168922d2017-06-09 09:47:52 -060059 struct cpuidle_driver *drv;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070060 struct lpm_cluster *parent;
61};
62
63struct lpm_level_avail {
64 bool idle_enabled;
65 bool suspend_enabled;
Mahesh Sivasubramanian62b3a6b2017-05-19 15:33:11 -060066 uint32_t latency_us;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070067 struct kobject *kobj;
68 struct kobj_attribute idle_enabled_attr;
69 struct kobj_attribute suspend_enabled_attr;
Mahesh Sivasubramanian62b3a6b2017-05-19 15:33:11 -060070 struct kobj_attribute latency_attr;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070071 void *data;
72 int idx;
73 bool cpu_node;
74};
75
76struct lpm_cluster_level {
77 const char *level_name;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070078 int min_child_level;
79 struct cpumask num_cpu_votes;
80 struct power_params pwr;
81 bool notify_rpm;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070082 bool sync_level;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070083 struct lpm_level_avail available;
84 unsigned int psci_id;
85 bool is_reset;
86 int reset_level;
87};
88
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070089struct cluster_history {
90 uint32_t resi[MAXSAMPLES];
91 int mode[MAXSAMPLES];
92 int64_t stime[MAXSAMPLES];
93 uint32_t hptr;
94 uint32_t hinvalid;
95 uint32_t htmr_wkup;
96 uint64_t entry_time;
97 int entry_idx;
98 int nsamp;
99 int flag;
100};
101
102struct lpm_cluster {
103 struct list_head list;
104 struct list_head child;
105 const char *cluster_name;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700106 unsigned long aff_level; /* Affinity level of the node */
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700107 struct lpm_cluster_level levels[NR_LPM_LEVELS];
108 int nlevels;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700109 int min_child_level;
110 int default_level;
111 int last_level;
Raghavendra Kakarlafbcacdf2018-03-09 18:27:33 +0530112 uint32_t tmr_add;
113 bool lpm_prediction;
Mahesh Sivasubramanian168922d2017-06-09 09:47:52 -0600114 struct list_head cpu;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700115 spinlock_t sync_lock;
116 struct cpumask child_cpus;
117 struct cpumask num_children_in_sync;
118 struct lpm_cluster *parent;
119 struct lpm_stats *stats;
120 unsigned int psci_mode_shift;
121 unsigned int psci_mode_mask;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700122 struct cluster_history history;
123 struct hrtimer histtimer;
124};
125
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700126struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev);
127void free_cluster_node(struct lpm_cluster *cluster);
128void cluster_dt_walkthrough(struct lpm_cluster *cluster);
129
130int create_cluster_lvl_nodes(struct lpm_cluster *p, struct kobject *kobj);
131bool lpm_cpu_mode_allow(unsigned int cpu,
132 unsigned int mode, bool from_idle);
133bool lpm_cluster_mode_allow(struct lpm_cluster *cluster,
134 unsigned int mode, bool from_idle);
135uint32_t *get_per_cpu_max_residency(int cpu);
136uint32_t *get_per_cpu_min_residency(int cpu);
137extern struct lpm_cluster *lpm_root_node;
138
Lina Iyer461ad8f2017-11-09 00:57:38 +0000139#if defined(CONFIG_SMP)
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700140extern DEFINE_PER_CPU(bool, pending_ipi);
141static inline bool is_IPI_pending(const struct cpumask *mask)
142{
143 unsigned int cpu;
144
145 for_each_cpu(cpu, mask) {
146 if per_cpu(pending_ipi, cpu)
147 return true;
148 }
149 return false;
150}
151#else
152static inline bool is_IPI_pending(const struct cpumask *mask)
153{
154 return false;
155}
156#endif