ARM: tegra: Add Tegra12x clock and dvfs files
[linux-3.10.git] / arch / arm / mach-tegra / dvfs.h
1 /*
2  *
3  * Copyright (C) 2010 Google, Inc.
4  *
5  * Author:
6  *      Colin Cross <ccross@google.com>
7  *
8  * Copyright (c) 2010-2013 NVIDIA CORPORATION. All rights reserved.
9  *
10  * This software is licensed under the terms of the GNU General Public
11  * License version 2, as published by the Free Software Foundation, and
12  * may be copied, distributed, and modified under those terms.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  */
20
21 #ifndef _TEGRA_DVFS_H_
22 #define _TEGRA_DVFS_H_
23
24 #include <linux/of.h>
25 #include <mach/thermal.h>
26
27 #define MAX_DVFS_FREQS  40
28 #define MAX_DVFS_TABLES 80
29 #define DVFS_RAIL_STATS_TOP_BIN 60
30 #define MAX_THERMAL_LIMITS      8
31
32 struct clk;
33 struct dvfs_rail;
34
35 /*
36  * dvfs_relationship between to rails, "from" and "to"
37  * when the rail changes, it will call dvfs_rail_update on the rails
38  * in the relationship_to list.
39  * when determining the voltage to set a rail to, it will consider each
40  * rail in the relationship_from list.
41  */
42 struct dvfs_relationship {
43         struct dvfs_rail *to;
44         struct dvfs_rail *from;
45         int (*solve)(struct dvfs_rail *, struct dvfs_rail *);
46
47         struct list_head to_node; /* node in relationship_to list */
48         struct list_head from_node; /* node in relationship_from list */
49         bool solved_at_nominal;
50 };
51
52 struct rail_stats {
53         ktime_t time_at_mv[DVFS_RAIL_STATS_TOP_BIN + 1];
54         ktime_t last_update;
55         int last_index;
56         bool off;
57         int bin_uV;
58 };
59
60 struct dvfs_rail {
61         const char *reg_id;
62         int min_millivolts;
63         int max_millivolts;
64         int reg_max_millivolts;
65         int nominal_millivolts;
66         int override_millivolts;
67         int min_override_millivolts;
68         const int *therm_mv_floors;
69         int therm_mv_floors_num;
70         const int *therm_mv_caps;
71         int therm_mv_caps_num;
72
73         int step;
74         bool jmp_to_zero;
75         bool disabled;
76         bool updating;
77         bool resolving_to;
78
79         struct list_head node;  /* node in dvfs_rail_list */
80         struct list_head dvfs;  /* list head of attached dvfs clocks */
81         struct list_head relationships_to;
82         struct list_head relationships_from;
83         struct regulator *reg;
84         int millivolts;
85         int new_millivolts;
86         int offs_millivolts;
87         bool suspended;
88         bool dfll_mode;
89         bool dfll_mode_updating;
90         int therm_floor_idx;
91         struct tegra_cooling_device *vmin_cdev;
92         struct tegra_cooling_device *vmax_cdev;
93         struct rail_stats stats;
94 };
95
96 enum dfll_range {
97         DFLL_RANGE_NONE = 0,
98         DFLL_RANGE_ALL_RATES,
99         DFLL_RANGE_HIGH_RATES,
100 };
101
102 struct dvfs_dfll_data {
103         u32             tune0;
104         u32             tune0_high_mv;
105         u32             tune1;
106         unsigned long   droop_rate_min;
107         unsigned long   use_dfll_rate_min;
108         unsigned long   out_rate_min;
109         unsigned long   max_rate_boost;
110         int tune_high_min_millivolts;
111         int min_millivolts;
112         enum dfll_range range;
113         void (*tune_trimmers)(bool trim_high);
114 };
115
116 struct dvfs {
117         /* Used only by tegra2_clock.c */
118         const char *clk_name;
119         int speedo_id;
120         int process_id;
121
122         /* Must be initialized before tegra_dvfs_init */
123         int freqs_mult;
124         unsigned long freqs[MAX_DVFS_FREQS];
125         unsigned long *alt_freqs;
126         const int *millivolts;
127         const int *dfll_millivolts;
128         struct dvfs_rail *dvfs_rail;
129         bool auto_dvfs;
130
131         /* Filled in by tegra_dvfs_init */
132         int max_millivolts;
133         int num_freqs;
134         struct dvfs_dfll_data dfll_data;
135
136         int cur_millivolts;
137         unsigned long cur_rate;
138         struct list_head node;
139         struct list_head debug_node;
140         struct list_head reg_node;
141 };
142
143 struct cvb_dvfs_parameters {
144         int     c0;
145         int     c1;
146         int     c2;
147 };
148
149 struct cvb_dvfs_table {
150         unsigned long freq;
151         struct cvb_dvfs_parameters cvb_dfll_param;
152         struct cvb_dvfs_parameters cvb_pll_param;
153 };
154
155 struct cpu_cvb_dvfs {
156         int speedo_id;
157         int process_id;
158
159         struct dvfs_dfll_data dfll_tune_data;
160         int max_mv;
161         int freqs_mult;
162         int speedo_scale;
163         int voltage_scale;
164         struct cvb_dvfs_table cvb_table[MAX_DVFS_FREQS];
165         int therm_trips_table[MAX_THERMAL_LIMITS];
166         int therm_floors_table[MAX_THERMAL_LIMITS];
167 };
168
169 struct core_cvb_dvfs {
170         int speedo_id;
171         int process_id;
172
173         int freqs_mult;
174         int speedo_scale;
175         int voltage_scale;
176         struct cvb_dvfs_table cvb_table[MAX_DVFS_FREQS];
177 };
178
179 extern struct dvfs_rail *tegra_cpu_rail;
180 extern struct dvfs_rail *tegra_core_rail;
181
182 struct dvfs_data {
183         struct dvfs_rail *rail;
184         struct dvfs *tables;
185         int *millivolts;
186         unsigned int num_tables;
187         unsigned int num_voltages;
188 };
189
190 struct core_dvfs_cap_table {
191         const char *cap_name;
192         struct clk *cap_clk;
193         unsigned long freqs[MAX_DVFS_FREQS];
194 };
195
196 struct core_bus_cap_table {
197         const char *cap_name;
198         struct clk *cap_clk;
199         struct kobj_attribute refcnt_attr;
200         struct kobj_attribute level_attr;
201         int refcnt;
202         int level;
203 };
204
205 #ifdef CONFIG_OF
206 typedef int (*of_tegra_dvfs_init_cb_t)(struct device_node *);
207 int of_tegra_dvfs_init(const struct of_device_id *matches);
208 #else
209 static inline int of_tegra_dvfs_init(const struct of_device_id *matches)
210 { return -ENODATA; }
211 #endif
212
213 void tegra11x_init_dvfs(void);
214 void tegra12x_init_dvfs(void);
215 void tegra14x_init_dvfs(void);
216 int tegra_enable_dvfs_on_clk(struct clk *c, struct dvfs *d);
217 int dvfs_debugfs_init(struct dentry *clk_debugfs_root);
218 int tegra_dvfs_late_init(void);
219 int tegra_dvfs_init_rails(struct dvfs_rail *dvfs_rails[], int n);
220 void tegra_dvfs_add_relationships(struct dvfs_relationship *rels, int n);
221 void tegra_dvfs_rail_enable(struct dvfs_rail *rail);
222 void tegra_dvfs_rail_disable(struct dvfs_rail *rail);
223 bool tegra_dvfs_rail_updating(struct clk *clk);
224 void tegra_dvfs_rail_off(struct dvfs_rail *rail, ktime_t now);
225 void tegra_dvfs_rail_on(struct dvfs_rail *rail, ktime_t now);
226 void tegra_dvfs_rail_pause(struct dvfs_rail *rail, ktime_t delta, bool on);
227 struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id);
228 int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
229 int tegra_dvfs_predict_millivolts_pll(struct clk *c, unsigned long rate);
230 int tegra_dvfs_predict_millivolts_dfll(struct clk *c, unsigned long rate);
231 int tegra_dvfs_core_cap_level_apply(int level);
232 int tegra_dvfs_alt_freqs_set(struct dvfs *d, unsigned long *alt_freqs);
233 int tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus,
234                          bool before_clk_update, int cpu_event);
235 int tegra_dvfs_dfll_mode_set(struct dvfs *d, unsigned long rate);
236 int tegra_dvfs_dfll_mode_clear(struct dvfs *d, unsigned long rate);
237 struct tegra_cooling_device *tegra_dvfs_get_cpu_vmax_cdev(void);
238 struct tegra_cooling_device *tegra_dvfs_get_cpu_vmin_cdev(void);
239 struct tegra_cooling_device *tegra_dvfs_get_core_vmin_cdev(void);
240 int tegra_dvfs_rail_dfll_mode_set_cold(struct dvfs_rail *rail);
241
242 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
243 int tegra_dvfs_rail_disable_prepare(struct dvfs_rail *rail);
244 int tegra_dvfs_rail_post_enable(struct dvfs_rail *rail);
245 #else
246 static inline int tegra_dvfs_rail_disable_prepare(struct dvfs_rail *rail)
247 { return 0; }
248 static inline int tegra_dvfs_rail_post_enable(struct dvfs_rail *rail)
249 { return 0; }
250 #endif
251
252 int tegra_init_core_cap(struct core_dvfs_cap_table *table, int table_size,
253         const int *millivolts, int millivolts_num, struct kobject *cap_kobj);
254 int tegra_init_shared_bus_cap(struct core_bus_cap_table *table, int table_size,
255         struct kobject *cap_kobj);
256
257 static inline bool tegra_dvfs_rail_is_dfll_mode(struct dvfs_rail *rail)
258 {
259         return rail ? rail->dfll_mode : false;
260 }
261 static inline bool tegra_dvfs_is_dfll_range_entry(struct dvfs *d,
262                                                   unsigned long rate)
263 {
264         /* make exception for cluster switch (cur_rate = 0) */
265         return  d->cur_rate && d->dvfs_rail && (!d->dvfs_rail->dfll_mode) &&
266                 (d->dfll_data.range == DFLL_RANGE_HIGH_RATES) &&
267                 (rate >= d->dfll_data.use_dfll_rate_min) &&
268                 (d->cur_rate < d->dfll_data.use_dfll_rate_min);
269 }
270
271 static inline bool tegra_dvfs_is_dfll_scale(struct dvfs *d, unsigned long rate)
272 {
273         return tegra_dvfs_rail_is_dfll_mode(d->dvfs_rail) ||
274                 tegra_dvfs_is_dfll_range_entry(d, rate);
275 }
276
277 static inline bool tegra_dvfs_is_dfll_range(struct dvfs *d, unsigned long rate)
278 {
279         return (d->dfll_data.range == DFLL_RANGE_ALL_RATES) ||
280                 ((d->dfll_data.range == DFLL_RANGE_HIGH_RATES) &&
281                 (rate >= d->dfll_data.use_dfll_rate_min));
282 }
283 static inline int tegra_dvfs_set_dfll_range(struct dvfs *d, int range)
284 {
285         if (!d->dfll_millivolts)
286                 return -ENOSYS;
287
288         if ((range < DFLL_RANGE_NONE) || (range > DFLL_RANGE_HIGH_RATES))
289                 return -EINVAL;
290
291         d->dfll_data.range = range;
292         return 0;
293 }
294 static inline void tegra_dvfs_rail_mode_updating(struct dvfs_rail *rail,
295                                                  bool updating)
296 {
297         if (rail)
298                 rail->dfll_mode_updating = updating;
299 }
300
301 static inline void tegra_dvfs_set_dfll_tune_trimmers(
302         struct dvfs *d, void (*tune_trimmers)(bool trim_high))
303 {
304         d->dfll_data.tune_trimmers = tune_trimmers;
305 }
306
307 static inline int tegra_dvfs_rail_get_nominal_millivolts(struct dvfs_rail *rail)
308 {
309         if (rail)
310                 return rail->nominal_millivolts;
311         return -ENOENT;
312 }
313
314 static inline int tegra_dvfs_rail_get_thermal_floor(struct dvfs_rail *rail)
315 {
316         if (rail && rail->therm_mv_floors &&
317             (rail->therm_floor_idx < rail->therm_mv_floors_num))
318                 return rail->therm_mv_floors[rail->therm_floor_idx];
319         return 0;
320 }
321
322 static inline int tegra_dvfs_rail_get_override_floor(struct dvfs_rail *rail)
323 {
324         if (rail)
325                 return rail->min_override_millivolts;
326         return -ENOENT;
327 }
328
329 #endif