blob: c9f272e4b45822e093d39d02828261c4ae21a991 [file] [log] [blame]
Mahesh Sivasubramanian62b3a6b2017-05-19 15:33:11 -06001/* Copyright (c) 2014-2017, 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
19
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070020struct lpm_lookup_table {
21 uint32_t modes;
22 const char *mode_name;
23};
24
25struct power_params {
26 uint32_t latency_us; /* Enter + Exit latency */
27 uint32_t ss_power; /* Steady state power */
28 uint32_t energy_overhead; /* Enter + exit over head */
29 uint32_t time_overhead_us; /* Enter + exit overhead */
30 uint32_t residencies[NR_LPM_LEVELS];
31 uint32_t min_residency;
32 uint32_t max_residency;
33};
34
35struct lpm_cpu_level {
36 const char *name;
37 enum msm_pm_sleep_mode mode;
38 bool use_bc_timer;
39 struct power_params pwr;
40 unsigned int psci_id;
41 bool is_reset;
42 bool jtag_save_restore;
43 bool hyp_psci;
44 int reset_level;
45};
46
47struct lpm_cpu {
Mahesh Sivasubramanian168922d2017-06-09 09:47:52 -060048 struct list_head list;
49 struct cpumask related_cpus;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070050 struct lpm_cpu_level levels[NR_LPM_LEVELS];
51 int nlevels;
52 unsigned int psci_mode_shift;
53 unsigned int psci_mode_mask;
Mahesh Sivasubramanian168922d2017-06-09 09:47:52 -060054 struct cpuidle_driver *drv;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070055 struct lpm_cluster *parent;
56};
57
58struct lpm_level_avail {
59 bool idle_enabled;
60 bool suspend_enabled;
Mahesh Sivasubramanian62b3a6b2017-05-19 15:33:11 -060061 uint32_t latency_us;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070062 struct kobject *kobj;
63 struct kobj_attribute idle_enabled_attr;
64 struct kobj_attribute suspend_enabled_attr;
Mahesh Sivasubramanian62b3a6b2017-05-19 15:33:11 -060065 struct kobj_attribute latency_attr;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070066 void *data;
67 int idx;
68 bool cpu_node;
69};
70
71struct lpm_cluster_level {
72 const char *level_name;
73 int *mode; /* SPM mode to enter */
74 int min_child_level;
75 struct cpumask num_cpu_votes;
76 struct power_params pwr;
77 bool notify_rpm;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070078 bool sync_level;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070079 struct lpm_level_avail available;
80 unsigned int psci_id;
81 bool is_reset;
82 int reset_level;
83};
84
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -070085struct cluster_history {
86 uint32_t resi[MAXSAMPLES];
87 int mode[MAXSAMPLES];
88 int64_t stime[MAXSAMPLES];
89 uint32_t hptr;
90 uint32_t hinvalid;
91 uint32_t htmr_wkup;
92 uint64_t entry_time;
93 int entry_idx;
94 int nsamp;
95 int flag;
96};
97
98struct lpm_cluster {
99 struct list_head list;
100 struct list_head child;
101 const char *cluster_name;
102 const char **name;
103 unsigned long aff_level; /* Affinity level of the node */
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700104 int ndevices;
105 struct lpm_cluster_level levels[NR_LPM_LEVELS];
106 int nlevels;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700107 int min_child_level;
108 int default_level;
109 int last_level;
Mahesh Sivasubramanian168922d2017-06-09 09:47:52 -0600110 struct list_head cpu;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700111 spinlock_t sync_lock;
112 struct cpumask child_cpus;
113 struct cpumask num_children_in_sync;
114 struct lpm_cluster *parent;
115 struct lpm_stats *stats;
116 unsigned int psci_mode_shift;
117 unsigned int psci_mode_mask;
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700118 struct cluster_history history;
119 struct hrtimer histtimer;
120};
121
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700122void lpm_suspend_wake_time(uint64_t wakeup_time);
123
124struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev);
125void free_cluster_node(struct lpm_cluster *cluster);
126void cluster_dt_walkthrough(struct lpm_cluster *cluster);
127
128int create_cluster_lvl_nodes(struct lpm_cluster *p, struct kobject *kobj);
129bool lpm_cpu_mode_allow(unsigned int cpu,
130 unsigned int mode, bool from_idle);
131bool lpm_cluster_mode_allow(struct lpm_cluster *cluster,
132 unsigned int mode, bool from_idle);
133uint32_t *get_per_cpu_max_residency(int cpu);
134uint32_t *get_per_cpu_min_residency(int cpu);
135extern struct lpm_cluster *lpm_root_node;
136
Mahesh Sivasubramanianb9da25f2016-11-04 14:35:03 -0600137#if CONFIG_SMP
Mahesh Sivasubramanianc2ea76f2016-02-01 10:40:26 -0700138extern DEFINE_PER_CPU(bool, pending_ipi);
139static inline bool is_IPI_pending(const struct cpumask *mask)
140{
141 unsigned int cpu;
142
143 for_each_cpu(cpu, mask) {
144 if per_cpu(pending_ipi, cpu)
145 return true;
146 }
147 return false;
148}
149#else
150static inline bool is_IPI_pending(const struct cpumask *mask)
151{
152 return false;
153}
154#endif