thermal: sprd: remove build warnings
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / thermal / sprd_cpu_cooling.c
1 /*
2  *  linux/drivers/thermal/sprd_cpu_cooling.c
3  *
4  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful, but
10  *  WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/slab.h>
23 #include <linux/err.h>
24 #include <linux/types.h>
25 #include <linux/thermal.h>
26 #include <linux/sprd_cpu_cooling.h>
27 #include <linux/platform_device.h>
28 #include <linux/cpumask.h>
29 #ifdef CONFIG_OF
30 #include <linux/of_device.h>
31 #endif
32
33 struct thermal_cooling_info_t {
34         unsigned long cooling_state;
35         struct thermal_cooling_device *cdev;
36         struct sprd_cpu_cooling_platform_data *pdata;
37         int max_state;
38         int enable;
39         int cluster;
40 };
41
42 #if !defined(CONFIG_SPRD_CPU_DYNAMIC_HOTPLUG) && !defined(CONFIG_CPU_FREQ_GOV_SPRDEMAND)
43 int cpu_core_thermal_limit(int cluster, int max_core)
44 {
45 #ifdef CONFIG_HOTPLUG_CPU
46         int cpuid, cpus;
47         int first_cpu, last_cpu;
48
49         if (cluster){
50                 first_cpu = NR_CPUS / 2;
51                 last_cpu = NR_CPUS - 1;
52         }else{
53                 first_cpu = 0;
54 #ifdef CONFIG_SCHED_HMP
55                 last_cpu = NR_CPUS / 2 -1;
56 #else
57                 last_cpu = NR_CPUS - 1;
58 #endif
59         }
60         for (cpus = 0, cpuid = first_cpu; cpuid <= last_cpu; ++cpuid){
61                 if (cpu_online(cpuid)){
62                         cpus++;
63                 }
64         }
65         if (max_core == cpus){
66                 return 0;
67         }
68         if (cpus < max_core){
69                 /* plug cpu */
70                 for (cpuid = first_cpu; cpuid <= last_cpu; ++cpuid){
71                         if (cpu_online(cpuid)){
72                                 continue;
73                         }
74                         pr_info("cpu-cooling: we gonna plugin cpu%d  !!\n", cpuid);
75                         if (cpu_up(cpuid)){
76                                 pr_info("plug cpu%d failed!\n", cpuid);
77                         }
78                         if (++cpus >= max_core){
79                                 return 0;
80                         }
81                 }
82         }else{
83                 /* unplug cpu */
84                 for (cpuid = last_cpu; cpuid >= first_cpu; --cpuid){
85                         if (!cpu_online(cpuid)){
86                                 continue;
87                         }
88                         pr_info("cpu-cooling: we gonna unplug cpu%d  !!\n", cpuid);
89                         if (cpu_down(cpuid)){
90                                 pr_info("unplug cpu%d failed!\n", cpuid);
91                         }
92                         if (--cpus <= max_core){
93                                 return 0;
94                         }
95                 }
96         }
97 #endif
98
99         return 0;
100 }
101 #endif
102
103 static int get_max_state(struct thermal_cooling_device *cdev,
104                          unsigned long *state)
105 {
106         struct thermal_cooling_info_t *info = cdev->devdata;
107         int ret = 0;
108
109         *state = info->max_state;
110
111         return ret;
112 }
113
114 static int get_cur_state(struct thermal_cooling_device *cdev,
115                          unsigned long *state)
116 {
117         struct thermal_cooling_info_t *info = cdev->devdata;
118         int ret = 0;
119
120         *state = info->cooling_state;
121
122         return ret;
123 }
124
125 static int thermal_set_vddarm(struct thermal_cooling_info_t *c_info,
126                 unsigned long state)
127 {
128         int i, j;
129         struct vddarm_update *pvddarm = c_info->pdata->vddarm_update;
130         struct freq_vddarm *pfreq_vddarm;
131
132         if (pvddarm == NULL){
133                 printk("%s vddarm_update isn't configed.\n", __func__);
134                 return -1;
135         }
136         for (i = 0; pvddarm[i].freq_vddarm; ++i){
137                 if (state != pvddarm[i].state){
138                         continue;
139                 }
140                 pfreq_vddarm = pvddarm[i].freq_vddarm;
141                 for (j = 0; pfreq_vddarm[j].freq; ++j){
142                         cpufreq_table_thermal_update(pfreq_vddarm[j].freq,
143                                         pfreq_vddarm[j].vddarm_mv);
144                 }
145         }
146
147         return 0;
148 }
149
150 static int set_cur_state(struct thermal_cooling_device *cdev,
151                          unsigned long state)
152 {
153         struct thermal_cooling_info_t *c_info = cdev->devdata;
154         int max_core;
155         int limit_freq;
156
157         thermal_set_vddarm(c_info, state);
158
159         if (c_info->enable && c_info->cooling_state == state){
160                 return 0;
161         }else{
162                 c_info->cooling_state = state;
163         }
164
165         limit_freq = c_info->pdata->cpu_state[state].max_freq;
166         max_core = c_info->pdata->cpu_state[state].max_core;
167         c_info->enable = 1;
168         pr_info("%s %s: %lu limit_freq: %d kHz max_core: %d\n",
169                         cdev->type, __func__, state, limit_freq, max_core);
170         cpufreq_thermal_limit(c_info->cluster, limit_freq);
171         cpu_core_thermal_limit(c_info->cluster, max_core);
172
173         return 0;
174 }
175
176 static struct thermal_cooling_device_ops sprd_cpufreq_cooling_ops = {
177         .get_max_state = get_max_state,
178         .get_cur_state = get_cur_state,
179         .set_cur_state = set_cur_state,
180 };
181
182 #ifdef CONFIG_OF
183 static int get_vddarm_updata_dt_data(struct device_node *np,
184                 struct sprd_cpu_cooling_platform_data *pdata)
185 {
186         struct vddarm_update *pvddarm;
187         int vddarm_nr[MAX_CPU_STATE];
188         char name[32];
189         int data[32];
190         int freq_nr;
191         int i, j, k, ret;
192
193         ret = of_property_read_u32_array(np, "vddarm_nr", vddarm_nr, 1);
194         if(ret){
195                 printk(KERN_ERR "fail to get vddarm_nr\n");
196                 goto error;
197         }
198
199         ret = of_property_read_u32_array(np, "vddarm_nr", vddarm_nr, vddarm_nr[0] + 1);
200         if (ret){
201                 printk(KERN_ERR "fail to get all vddarm_nr data.\n");
202                 goto error;
203         }
204         printk("%s vddarm_nr:<", __func__);
205         for (i = 0; i < vddarm_nr[0]; ++i){
206                 printk("%d ", vddarm_nr[i + 1]);
207         }
208         printk(">\n");
209
210         pvddarm = kzalloc(sizeof(*pvddarm) * (vddarm_nr[0] + 1), GFP_KERNEL);
211         if (pvddarm == NULL){
212                 goto error;
213         }
214
215         for (i = 0; i < vddarm_nr[0]; ++i){
216                 sprintf(name, "vddarm_update%d", i);
217                 ret = of_property_read_u32_array(np, name, data, vddarm_nr[i + 1]);
218                 if(ret){
219                         printk(KERN_ERR "fail to get %s len:%d\n", name, vddarm_nr[i + 1]);
220                         goto vddarm_err;
221                 }
222                 freq_nr = (vddarm_nr[i + 1] - 1) / 2;
223                 pvddarm[i].freq_vddarm = kzalloc(sizeof(struct freq_vddarm) * (freq_nr + 1), GFP_KERNEL);
224                 if (pvddarm[i].freq_vddarm == NULL){
225                         goto vddarm_err;
226                 }
227                 printk("%s state: <", __func__);
228                 for (j = 0; j < vddarm_nr[i + 1]; ++j){
229                         printk("%d ", data[j]);
230                 }
231                 printk(">\n");
232                 pvddarm[i].state = data[0];
233                 for (j = 0, k = 1; j < freq_nr; ++j){
234                         pvddarm[i].freq_vddarm[j].freq = data[k++];
235                         pvddarm[i].freq_vddarm[j].vddarm_mv = data[k++];
236                 }
237                 pvddarm[i].freq_vddarm[j].freq = 0;
238         }
239         pvddarm[i].freq_vddarm = NULL;
240         pdata->vddarm_update = pvddarm;
241
242         return 0;
243 vddarm_err:
244         for (j = 0; j < i; ++j){
245                 if (pvddarm[j].freq_vddarm){
246                         kfree(pvddarm[j].freq_vddarm);
247                         pvddarm[j].freq_vddarm = NULL;
248                 }
249         }
250         kfree(pvddarm);
251 error:
252         pdata->vddarm_update = NULL;
253         return -1;
254 }
255
256 static struct sprd_cpu_cooling_platform_data *get_cpu_cooling_dt_data(
257                 struct device *dev, struct thermal_cooling_info_t *info)
258 {
259         struct sprd_cpu_cooling_platform_data *pdata = NULL;
260         struct device_node *np = dev->of_node;
261         int max_freq[MAX_CPU_STATE];
262         int max_core[MAX_CPU_STATE];
263         int ret, i;
264
265         if (!np) {
266                 dev_err(dev, "device node not found\n");
267                 return NULL;
268         }
269         pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
270         if (!pdata) {
271                 dev_err(dev, "could not allocate memory for platform data\n");
272                 return NULL;
273         }
274         ret = of_property_read_u32(np, "cluster", &info->cluster);
275         if(ret){
276                 info->cluster = 0;
277         }
278         dev_info(dev, "cluster: %s\n", info->cluster ? "big" : "little");
279         ret = of_property_read_u32(np, "state_num", &pdata->state_num);
280         if(ret){
281                 dev_err(dev, "fail to get state_num\n");
282                 goto error;
283         }
284         dev_info(dev, "state_num=%d\n", pdata->state_num);
285         ret = of_property_read_u32_array(np, "max_freq", max_freq, pdata->state_num);
286         if(ret){
287                 dev_err(dev, "fail to get max_freq\n");
288                 goto error;
289         }
290         ret = of_property_read_u32_array(np, "max_core", max_core, pdata->state_num);
291         if(ret){
292                 dev_err(dev, "fail to get max_core\n");
293                 goto error;
294         }
295         for (i = 0; i < pdata->state_num; ++i){
296                 pdata->cpu_state[i].max_freq = max_freq[i];
297                 pdata->cpu_state[i].max_core = max_core[i];
298                 dev_info(dev, "state:%d, max_freq:%d, max_core:%d\n", i, max_freq[i], max_core[i]);
299         }
300         info->max_state = pdata->state_num - 1;
301         get_vddarm_updata_dt_data(np, pdata);
302
303         return pdata;
304
305 error:
306         kfree(pdata);
307         pdata = NULL;
308         return pdata;
309 }
310 #endif
311
312 static int sprd_cpu_cooling_probe(struct platform_device *pdev)
313 {
314         struct thermal_cooling_info_t *info = NULL;
315         struct sprd_cpu_cooling_platform_data *pdata = NULL;
316         char cdev_name[32];
317         int ret = 0;
318
319         info = kzalloc(sizeof(*info), GFP_KERNEL);
320         if (!info) {
321                 dev_err(&pdev->dev, "could not allocate memory for info data\n");
322                 return -1;
323         }
324 #ifdef CONFIG_OF
325         ret = of_property_read_u32(pdev->dev.of_node, "id", &pdev->id);
326         if(ret || pdev->id < 0){
327                 pdev->id = 0;
328         }
329         pdata = get_cpu_cooling_dt_data(&pdev->dev, info);
330         if (!pdata){
331                 ret = -1;
332                 goto err;
333         }
334         pdev->dev.platform_data = pdata;
335 #else
336         pdata = dev_get_platdata(&pdev->dev);
337         if (NULL == pdata){
338                 dev_err(&pdev->dev, "%s platform data is NULL!\n", __func__);
339                 ret = -1;
340                 goto err;
341         }
342         info->max_state = pdata->state_num - 1;
343 #endif
344
345         pdata->devdata = info;
346         info->pdata = pdata;
347         info->cooling_state = 0,
348         info->enable = 0,
349         sprintf(cdev_name, "thermal-cpufreq-%d", pdev->id);
350         info->cdev = thermal_cooling_device_register(cdev_name, info,
351                                                 &sprd_cpufreq_cooling_ops);
352         if (IS_ERR(info->cdev)){
353                 ret = PTR_ERR(info->cdev);
354                 goto err;
355         }
356
357         return ret;
358 err:
359         kfree(info);
360         return ret;
361 }
362
363 static int sprd_cpu_cooling_remove(struct platform_device *pdev)
364 {
365         struct sprd_cpu_cooling_platform_data *pdata = dev_get_platdata(&pdev->dev);
366         struct thermal_cooling_info_t *info = pdata->devdata;
367
368 #ifdef CONFIG_OF
369         int i;
370
371         if (pdata->vddarm_update){
372                 for (i = 0; pdata->vddarm_update[i].freq_vddarm; ++i){
373                         kfree(pdata->vddarm_update[i].freq_vddarm);
374                         pdata->vddarm_update[i].freq_vddarm = NULL;
375                 }
376                 kfree(pdata->vddarm_update);
377         }
378         kfree(pdata);
379         pdata = NULL;
380 #endif
381         thermal_cooling_device_unregister(info->cdev);
382         kfree(info);
383
384         return 0;
385 }
386
387 #ifdef CONFIG_OF
388 static const struct of_device_id cpu_cooling_of_match[] = {
389        { .compatible = "sprd,sprd-cpu-cooling", },
390        { }
391 };
392 #endif
393
394 static struct platform_driver cpu_cooling_driver = {
395         .probe = sprd_cpu_cooling_probe,
396         .remove = sprd_cpu_cooling_remove,
397         .driver = {
398                 .owner = THIS_MODULE,
399                 .name = "sprd-cpu-cooling",
400 #ifdef CONFIG_OF
401                 .of_match_table = of_match_ptr(cpu_cooling_of_match),
402 #endif
403         },
404 };
405
406
407 static int __init sprd_cpu_cooling_init(void)
408 {
409         return platform_driver_register(&cpu_cooling_driver);
410 }
411
412 static void __exit sprd_cpu_cooling_exit(void)
413 {
414         platform_driver_unregister(&cpu_cooling_driver);
415 }
416
417 late_initcall(sprd_cpu_cooling_init);
418 module_exit(sprd_cpu_cooling_exit);