ARM: tegra: add sysfs support for tegra cpuquiet driver
[linux-2.6.git] / arch / arm / mach-tegra / cpuquiet.c
1 /*
2  * arch/arm/mach-tegra/cpuquiet.c
3  *
4  * Cpuquiet driver for Tegra3 CPUs
5  *
6  * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/types.h>
24 #include <linux/sched.h>
25 #include <linux/cpufreq.h>
26 #include <linux/delay.h>
27 #include <linux/err.h>
28 #include <linux/io.h>
29 #include <linux/cpu.h>
30 #include <linux/clk.h>
31 #include <linux/debugfs.h>
32 #include <linux/seq_file.h>
33 #include <linux/pm_qos_params.h>
34 #include <linux/cpuquiet.h>
35
36 #include "pm.h"
37 #include "cpu-tegra.h"
38 #include "clock.h"
39
40 #define INITIAL_STATE           TEGRA_CPQ_IDLE
41 #define UP_DELAY_MS             70
42 #define DOWN_DELAY_MS           2000
43
44 static struct mutex *tegra3_cpu_lock;
45 static struct workqueue_struct *cpuquiet_wq;
46 static struct delayed_work cpuquiet_work;
47 static struct work_struct minmax_work;
48
49 static struct kobject *tegra_auto_sysfs_kobject;
50
51 static bool no_lp;
52 static bool enable;
53 static unsigned long up_delay;
54 static unsigned long down_delay;
55 static int mp_overhead = 10;
56 static unsigned int idle_top_freq;
57 static unsigned int idle_bottom_freq;
58
59 static struct clk *cpu_clk;
60 static struct clk *cpu_g_clk;
61 static struct clk *cpu_lp_clk;
62
63 static struct cpumask cr_online_requests;
64
65 enum {
66         TEGRA_CPQ_DISABLED = 0,
67         TEGRA_CPQ_IDLE,
68         TEGRA_CPQ_SWITCH_TO_LP,
69         TEGRA_CPQ_SWITCH_TO_G,
70 };
71
72 static int cpq_state;
73
74 static int update_core_config(unsigned int cpunumber, bool up)
75 {
76         int ret = -EINVAL;
77         unsigned int nr_cpus = num_online_cpus();
78         int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4;
79         int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS);
80
81         if (cpq_state == TEGRA_CPQ_DISABLED || cpunumber >= nr_cpu_ids)
82                 return ret;
83
84         if (up) {
85                 if(is_lp_cluster()) {
86                         cpumask_set_cpu(cpunumber, &cr_online_requests);
87                         ret = -EBUSY;
88                 } else {
89                         if (tegra_cpu_edp_favor_up(nr_cpus, mp_overhead) &&
90                             nr_cpus < max_cpus)
91                                 ret = cpu_up(cpunumber);
92                 }
93         } else {
94                 if (is_lp_cluster()) {
95                         ret = -EBUSY;
96                 } else {
97                         if (nr_cpus > min_cpus)
98                                 ret = cpu_down(cpunumber);
99                 }
100         }
101
102         return ret;
103 }
104
105 static int tegra_quiesence_cpu(unsigned int cpunumber)
106 {
107         return update_core_config(cpunumber, false);
108 }
109
110 static int tegra_wake_cpu(unsigned int cpunumber)
111 {
112         return update_core_config(cpunumber, true);
113 }
114
115 static struct cpuquiet_driver tegra_cpuquiet_driver = {
116         .name                   = "tegra",
117         .quiesence_cpu          = tegra_quiesence_cpu,
118         .wake_cpu               = tegra_wake_cpu,
119 };
120
121 static void apply_core_config(void)
122 {
123         unsigned int cpu;
124
125         if (is_lp_cluster() || cpq_state == TEGRA_CPQ_DISABLED)
126                 return;
127
128         for_each_cpu_mask(cpu, cr_online_requests) {
129                 if (cpu < nr_cpu_ids && !cpu_online(cpu))
130                         if (!tegra_wake_cpu(cpu))
131                                 cpumask_clear_cpu(cpu, &cr_online_requests);
132         }
133 }
134
135 static void tegra_cpuquiet_work_func(struct work_struct *work)
136 {
137         bool update_cr_config = false;
138
139         mutex_lock(tegra3_cpu_lock);
140
141         switch(cpq_state) {
142                 case TEGRA_CPQ_DISABLED:
143                 case TEGRA_CPQ_IDLE:
144                         break;
145                 case TEGRA_CPQ_SWITCH_TO_G:
146                         if (is_lp_cluster()) {
147                                 if(!clk_set_parent(cpu_clk, cpu_g_clk)) {
148                                         /*catch-up with governor target speed */
149                                         tegra_cpu_set_speed_cap(NULL);
150                                         /* process pending core requests*/
151                                         update_cr_config = true;
152                                 }
153                         }
154                         break;
155                 case TEGRA_CPQ_SWITCH_TO_LP:
156                         if (!is_lp_cluster() && !no_lp &&
157                                 !pm_qos_request(PM_QOS_MIN_ONLINE_CPUS)
158                                 && num_online_cpus() == 1) {
159                                 if (!clk_set_parent(cpu_clk, cpu_lp_clk)) {
160                                         /*catch-up with governor target speed*/
161                                         tegra_cpu_set_speed_cap(NULL);
162                                 }
163                         }
164                         break;
165                 default:
166                         pr_err("%s: invalid tegra hotplug state %d\n",
167                        __func__, cpq_state);
168         }
169
170         mutex_unlock(tegra3_cpu_lock);
171
172         if (update_cr_config)
173                 apply_core_config();
174 }
175
176 static void min_max_constraints_workfunc(struct work_struct *work)
177 {
178         int count = -1;
179         bool up = false;
180         unsigned int cpu;
181
182         int nr_cpus = num_online_cpus();
183         int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4;
184         int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS);
185
186         if (is_lp_cluster())
187                 return;
188
189         if (nr_cpus < min_cpus) {
190                 up = true;
191                 count = min_cpus - nr_cpus;
192         } else if (nr_cpus > max_cpus && max_cpus >= min_cpus) {
193                 count = nr_cpus - max_cpus;
194         }
195
196         for (;count > 0; count--) {
197                 if (up) {
198                         cpu = cpumask_next_zero(0, cpu_online_mask);
199                         if (cpu < nr_cpu_ids)
200                                 cpu_up(cpu);
201                         else
202                                 break;
203                 } else {
204                         cpu = cpumask_next(0, cpu_online_mask);
205                         if (cpu < nr_cpu_ids)
206                                 cpu_down(cpu);
207                         else
208                                 break;
209                 }
210         }
211 }
212
213 static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
214 {
215         mutex_lock(tegra3_cpu_lock);
216
217         if ((n >= 1) && is_lp_cluster()) {
218                 /* make sure cpu rate is within g-mode range before switching */
219                 unsigned long speed = max((unsigned long)tegra_getspeed(0),
220                                         clk_get_min_rate(cpu_g_clk) / 1000);
221                 tegra_update_cpu_speed(speed);
222
223                 clk_set_parent(cpu_clk, cpu_g_clk);
224         }
225
226         tegra_cpu_set_speed_cap(NULL);
227         mutex_unlock(tegra3_cpu_lock);
228
229         schedule_work(&minmax_work);
230
231         return NOTIFY_OK;
232 }
233
234 static int max_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
235 {
236         if (n < num_online_cpus())
237                 schedule_work(&minmax_work);
238
239         return NOTIFY_OK;
240 }
241
242 void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
243 {
244         if (!is_g_cluster_present())
245                 return;
246
247         if (cpq_state == TEGRA_CPQ_DISABLED)
248                 return;
249
250         if (suspend) {
251                 cpq_state = TEGRA_CPQ_IDLE;
252
253                 /* Switch to G-mode if suspend rate is high enough */
254                 if (is_lp_cluster() && (cpu_freq >= idle_bottom_freq)) {
255                         clk_set_parent(cpu_clk, cpu_g_clk);
256                 }
257                 return;
258         }
259
260         if (is_lp_cluster() && pm_qos_request(PM_QOS_MIN_ONLINE_CPUS) >= 2) {
261                 if (cpq_state != TEGRA_CPQ_SWITCH_TO_G) {
262                         /* Force switch */
263                         cpq_state = TEGRA_CPQ_SWITCH_TO_G;
264                         queue_delayed_work(
265                                 cpuquiet_wq, &cpuquiet_work, up_delay);
266                 }
267                 return;
268         }
269
270         if (is_lp_cluster() && (cpu_freq >= idle_top_freq || no_lp)) {
271                 cpq_state = TEGRA_CPQ_SWITCH_TO_G;
272                 queue_delayed_work(cpuquiet_wq, &cpuquiet_work, up_delay);
273         } else if (!is_lp_cluster() && !no_lp &&
274                    cpu_freq <= idle_bottom_freq) {
275                 cpq_state = TEGRA_CPQ_SWITCH_TO_LP;
276                 queue_delayed_work(cpuquiet_wq, &cpuquiet_work, down_delay);
277         } else {
278                 cpq_state = TEGRA_CPQ_IDLE;
279         }
280 }
281
282 static struct notifier_block min_cpus_notifier = {
283         .notifier_call = min_cpus_notify,
284 };
285
286 static struct notifier_block max_cpus_notifier = {
287         .notifier_call = max_cpus_notify,
288 };
289
290 static void delay_callback(struct cpuquiet_attribute *attr)
291 {
292         unsigned long val;
293
294         if (attr) {
295                 val = (*((unsigned long *)(attr->param)));
296                 (*((unsigned long *)(attr->param))) = msecs_to_jiffies(val);
297         }
298 }
299
300 static void enable_callback(struct cpuquiet_attribute *attr)
301 {
302         mutex_lock(tegra3_cpu_lock);
303
304         if (!enable && cpq_state != TEGRA_CPQ_DISABLED) {
305                 cpq_state = TEGRA_CPQ_DISABLED;
306                 mutex_unlock(tegra3_cpu_lock);
307                 cancel_delayed_work_sync(&cpuquiet_work);
308                 pr_info("Tegra cpuquiet clusterswitch disabled\n");
309                 mutex_lock(tegra3_cpu_lock);
310         } else if (enable && cpq_state == TEGRA_CPQ_DISABLED) {
311                 cpq_state = TEGRA_CPQ_IDLE;
312                 pr_info("Tegra cpuquiet clusterswitch enabled\n");
313                 tegra_cpu_set_speed_cap(NULL);
314         }
315
316         mutex_unlock(tegra3_cpu_lock);
317 }
318
319 CPQ_BASIC_ATTRIBUTE(no_lp, 0644, bool);
320 CPQ_BASIC_ATTRIBUTE(idle_top_freq, 0644, uint);
321 CPQ_BASIC_ATTRIBUTE(idle_bottom_freq, 0644, uint);
322 CPQ_BASIC_ATTRIBUTE(mp_overhead, 0644, int);
323 CPQ_ATTRIBUTE(up_delay, 0644, ulong, delay_callback);
324 CPQ_ATTRIBUTE(down_delay, 0644, ulong, delay_callback);
325 CPQ_ATTRIBUTE(enable, 0644, bool, enable_callback);
326
327 static struct attribute *tegra_auto_attributes[] = {
328         &no_lp_attr.attr,
329         &up_delay_attr.attr,
330         &down_delay_attr.attr,
331         &idle_top_freq_attr.attr,
332         &idle_bottom_freq_attr.attr,
333         &mp_overhead_attr.attr,
334         &enable_attr.attr,
335         NULL,
336 };
337
338 static const struct sysfs_ops tegra_auto_sysfs_ops = {
339         .show = cpuquiet_auto_sysfs_show,
340         .store = cpuquiet_auto_sysfs_store,
341 };
342
343 static struct kobj_type ktype_sysfs = {
344         .sysfs_ops = &tegra_auto_sysfs_ops,
345         .default_attrs = tegra_auto_attributes,
346 };
347
348 static int tegra_auto_sysfs(void)
349 {
350         int err;
351
352         tegra_auto_sysfs_kobject = kzalloc(sizeof(*tegra_auto_sysfs_kobject),
353                                         GFP_KERNEL);
354
355         if (!tegra_auto_sysfs_kobject)
356                 return -ENOMEM;
357
358         err = cpuquiet_kobject_init(tegra_auto_sysfs_kobject, &ktype_sysfs,
359                                 "tegra_cpuquiet");
360
361         if (err)
362                 kfree(tegra_auto_sysfs_kobject);
363
364         return err;
365 }
366
367 int tegra_auto_hotplug_init(struct mutex *cpu_lock)
368 {
369         int err;
370
371         cpu_clk = clk_get_sys(NULL, "cpu");
372         cpu_g_clk = clk_get_sys(NULL, "cpu_g");
373         cpu_lp_clk = clk_get_sys(NULL, "cpu_lp");
374
375         if (IS_ERR(cpu_clk) || IS_ERR(cpu_g_clk) || IS_ERR(cpu_lp_clk))
376                 return -ENOENT;
377
378         /*
379          * Not bound to the issuer CPU (=> high-priority), has rescue worker
380          * task, single-threaded, freezable.
381          */
382         cpuquiet_wq = alloc_workqueue(
383                 "cpuquiet", WQ_UNBOUND | WQ_RESCUER | WQ_FREEZABLE, 1);
384
385         if (!cpuquiet_wq)
386                 return -ENOMEM;
387
388         INIT_DELAYED_WORK(&cpuquiet_work, tegra_cpuquiet_work_func);
389         INIT_WORK(&minmax_work, min_max_constraints_workfunc);
390
391         cpu_clk = clk_get_sys(NULL, "cpu");
392         cpu_g_clk = clk_get_sys(NULL, "cpu_g");
393         cpu_lp_clk = clk_get_sys(NULL, "cpu_lp");
394
395         if (IS_ERR(cpu_clk) || IS_ERR(cpu_g_clk) || IS_ERR(cpu_lp_clk))
396                 return -ENOENT;
397
398         idle_top_freq = clk_get_max_rate(cpu_lp_clk) / 1000;
399         idle_bottom_freq = clk_get_min_rate(cpu_g_clk) / 1000;
400
401         up_delay = msecs_to_jiffies(UP_DELAY_MS);
402         down_delay = msecs_to_jiffies(DOWN_DELAY_MS);
403         cpumask_clear(&cr_online_requests);
404         tegra3_cpu_lock = cpu_lock;
405
406         cpq_state = INITIAL_STATE;
407         enable = cpq_state == TEGRA_CPQ_DISABLED ? false : true;
408
409
410         pr_info("Tegra cpuquiet initialized: %s\n",
411                 (cpq_state == TEGRA_CPQ_DISABLED) ? "disabled" : "enabled");
412
413         if (pm_qos_add_notifier(PM_QOS_MIN_ONLINE_CPUS, &min_cpus_notifier))
414                 pr_err("%s: Failed to register min cpus PM QoS notifier\n",
415                         __func__);
416         if (pm_qos_add_notifier(PM_QOS_MAX_ONLINE_CPUS, &max_cpus_notifier))
417                 pr_err("%s: Failed to register max cpus PM QoS notifier\n",
418                         __func__);
419
420         err = cpuquiet_register_driver(&tegra_cpuquiet_driver);
421         if (err) {
422                 destroy_workqueue(cpuquiet_wq);
423                 return err;
424         }
425
426         err = tegra_auto_sysfs();
427         if (err) {
428                 cpuquiet_unregister_driver(&tegra_cpuquiet_driver);
429                 destroy_workqueue(cpuquiet_wq);
430         }
431
432         return err;
433 }
434
435 void tegra_auto_hotplug_exit(void)
436 {
437         destroy_workqueue(cpuquiet_wq);
438         cpuquiet_unregister_driver(&tegra_cpuquiet_driver);
439         kobject_put(tegra_auto_sysfs_kobject);
440 }