2 * linux/drivers/thermal/sprd_cpu_cooling.c
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.
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.
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.
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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>
30 #include <linux/of_device.h>
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;
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)
45 #ifdef CONFIG_HOTPLUG_CPU
47 int first_cpu, last_cpu;
50 first_cpu = NR_CPUS / 2;
51 last_cpu = NR_CPUS - 1;
54 #ifdef CONFIG_SCHED_HMP
55 last_cpu = NR_CPUS / 2 -1;
57 last_cpu = NR_CPUS - 1;
60 for (cpus = 0, cpuid = first_cpu; cpuid <= last_cpu; ++cpuid){
61 if (cpu_online(cpuid)){
65 if (max_core == cpus){
70 for (cpuid = first_cpu; cpuid <= last_cpu; ++cpuid){
71 if (cpu_online(cpuid)){
74 pr_info("cpu-cooling: we gonna plugin cpu%d !!\n", cpuid);
76 pr_info("plug cpu%d failed!\n", cpuid);
78 if (++cpus >= max_core){
84 for (cpuid = last_cpu; cpuid >= first_cpu; --cpuid){
85 if (!cpu_online(cpuid)){
88 pr_info("cpu-cooling: we gonna unplug cpu%d !!\n", cpuid);
90 pr_info("unplug cpu%d failed!\n", cpuid);
92 if (--cpus <= max_core){
103 static int get_max_state(struct thermal_cooling_device *cdev,
104 unsigned long *state)
106 struct thermal_cooling_info_t *info = cdev->devdata;
109 *state = info->max_state;
114 static int get_cur_state(struct thermal_cooling_device *cdev,
115 unsigned long *state)
117 struct thermal_cooling_info_t *info = cdev->devdata;
120 *state = info->cooling_state;
125 static int thermal_set_vddarm(struct thermal_cooling_info_t *c_info,
129 struct vddarm_update *pvddarm = c_info->pdata->vddarm_update;
130 struct freq_vddarm *pfreq_vddarm;
132 if (pvddarm == NULL){
133 printk("%s vddarm_update isn't configed.\n", __func__);
136 for (i = 0; pvddarm[i].freq_vddarm; ++i){
137 if (state != pvddarm[i].state){
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);
150 static int set_cur_state(struct thermal_cooling_device *cdev,
153 struct thermal_cooling_info_t *c_info = cdev->devdata;
157 thermal_set_vddarm(c_info, state);
159 if (c_info->enable && c_info->cooling_state == state){
162 c_info->cooling_state = state;
165 limit_freq = c_info->pdata->cpu_state[state].max_freq;
166 max_core = c_info->pdata->cpu_state[state].max_core;
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);
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,
183 static int get_vddarm_updata_dt_data(struct device_node *np,
184 struct sprd_cpu_cooling_platform_data *pdata)
186 struct vddarm_update *pvddarm;
187 int vddarm_nr[MAX_CPU_STATE];
193 ret = of_property_read_u32_array(np, "vddarm_nr", vddarm_nr, 1);
195 printk(KERN_ERR "fail to get vddarm_nr\n");
199 ret = of_property_read_u32_array(np, "vddarm_nr", vddarm_nr, vddarm_nr[0] + 1);
201 printk(KERN_ERR "fail to get all vddarm_nr data.\n");
204 printk("%s vddarm_nr:<", __func__);
205 for (i = 0; i < vddarm_nr[0]; ++i){
206 printk("%d ", vddarm_nr[i + 1]);
210 pvddarm = kzalloc(sizeof(*pvddarm) * (vddarm_nr[0] + 1), GFP_KERNEL);
211 if (pvddarm == NULL){
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]);
219 printk(KERN_ERR "fail to get %s len:%d\n", name, vddarm_nr[i + 1]);
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){
227 printk("%s state: <", __func__);
228 for (j = 0; j < vddarm_nr[i + 1]; ++j){
229 printk("%d ", data[j]);
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++];
237 pvddarm[i].freq_vddarm[j].freq = 0;
239 pvddarm[i].freq_vddarm = NULL;
240 pdata->vddarm_update = pvddarm;
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;
252 pdata->vddarm_update = NULL;
256 static struct sprd_cpu_cooling_platform_data *get_cpu_cooling_dt_data(
257 struct device *dev, struct thermal_cooling_info_t *info)
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];
266 dev_err(dev, "device node not found\n");
269 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
271 dev_err(dev, "could not allocate memory for platform data\n");
274 ret = of_property_read_u32(np, "cluster", &info->cluster);
278 dev_info(dev, "cluster: %s\n", info->cluster ? "big" : "little");
279 ret = of_property_read_u32(np, "state_num", &pdata->state_num);
281 dev_err(dev, "fail to get state_num\n");
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);
287 dev_err(dev, "fail to get max_freq\n");
290 ret = of_property_read_u32_array(np, "max_core", max_core, pdata->state_num);
292 dev_err(dev, "fail to get max_core\n");
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]);
300 info->max_state = pdata->state_num - 1;
301 get_vddarm_updata_dt_data(np, pdata);
312 static int sprd_cpu_cooling_probe(struct platform_device *pdev)
314 struct thermal_cooling_info_t *info = NULL;
315 struct sprd_cpu_cooling_platform_data *pdata = NULL;
319 info = kzalloc(sizeof(*info), GFP_KERNEL);
321 dev_err(&pdev->dev, "could not allocate memory for info data\n");
325 ret = of_property_read_u32(pdev->dev.of_node, "id", &pdev->id);
326 if(ret || pdev->id < 0){
329 pdata = get_cpu_cooling_dt_data(&pdev->dev, info);
334 pdev->dev.platform_data = pdata;
336 pdata = dev_get_platdata(&pdev->dev);
338 dev_err(&pdev->dev, "%s platform data is NULL!\n", __func__);
342 info->max_state = pdata->state_num - 1;
345 pdata->devdata = info;
347 info->cooling_state = 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);
363 static int sprd_cpu_cooling_remove(struct platform_device *pdev)
365 struct sprd_cpu_cooling_platform_data *pdata = dev_get_platdata(&pdev->dev);
366 struct thermal_cooling_info_t *info = pdata->devdata;
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;
376 kfree(pdata->vddarm_update);
381 thermal_cooling_device_unregister(info->cdev);
388 static const struct of_device_id cpu_cooling_of_match[] = {
389 { .compatible = "sprd,sprd-cpu-cooling", },
394 static struct platform_driver cpu_cooling_driver = {
395 .probe = sprd_cpu_cooling_probe,
396 .remove = sprd_cpu_cooling_remove,
398 .owner = THIS_MODULE,
399 .name = "sprd-cpu-cooling",
401 .of_match_table = of_match_ptr(cpu_cooling_of_match),
407 static int __init sprd_cpu_cooling_init(void)
409 return platform_driver_register(&cpu_cooling_driver);
412 static void __exit sprd_cpu_cooling_exit(void)
414 platform_driver_unregister(&cpu_cooling_driver);
417 late_initcall(sprd_cpu_cooling_init);
418 module_exit(sprd_cpu_cooling_exit);