thermal: sprd: remove build warnings
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / thermal / sprd_thm.c
1 /*
2  * Copyright (C) 2013 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/interrupt.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18 #include <linux/err.h>
19 #include<linux/string.h>
20 #include <asm/io.h>
21 #include <linux/thermal.h>
22 #include <linux/sprd_thm.h>
23 #include "thm.h"
24 #include "linux/delay.h"
25 #ifdef CONFIG_OF
26 #include <linux/slab.h>
27 #include <linux/of_device.h>
28 //#include <linux/of_address.h>
29 #include <linux/of_irq.h>
30 #endif
31
32 struct thm_handle_ops *sprd_thm_handle_ops[SPRD_MAX_SENSOR] = {NULL};
33 char sprd_thm_name[SPRD_MAX_SENSOR][THERMAL_NAME_LENGTH] = {{0},{0}};
34 extern struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
35 extern int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp);
36 int  sprd_thermal_temp_get(enum sprd_thm_sensor_id thermal_id,unsigned long *temp)
37 {
38         char thermal_name[SPRD_MAX_SENSOR][THERMAL_NAME_LENGTH] = {
39                 "sprd_arm_thm",
40                 "sprd_gpu_thm",
41                 "sprd_pmic_thm"
42         };
43         struct thermal_zone_device * tz = thermal_zone_get_zone_by_name(thermal_name[thermal_id]);
44         if(IS_ERR(tz) )
45                 return -1;
46         return thermal_zone_get_temp(tz, temp);
47 }
48 EXPORT_SYMBOL(sprd_thermal_temp_get);
49
50 static int sprd_thm_ops_init(struct sprd_thermal_zone *pzone)
51 {
52         if((!sprd_thm_name[pzone->sensor_id]) ||(!sprd_thm_handle_ops[pzone->sensor_id])  )
53                 return  -1;
54         strcpy(pzone->thermal_zone_name,sprd_thm_name[pzone->sensor_id]);
55         pzone->ops = sprd_thm_handle_ops[pzone->sensor_id];
56         return 0;
57 }
58 int sprd_thm_add(struct thm_handle_ops* ops, char *p,int id)
59 {
60         if( (ops == NULL) ||( p == NULL) ||( id > SPRD_MAX_SENSOR - 1))
61                 return -1;
62         sprd_thm_handle_ops[id] = ops;
63         strcpy(sprd_thm_name[id],p);
64         return 0;
65 }
66 void sprd_thm_delete(int id)
67 {
68         sprd_thm_handle_ops[id] = NULL;
69         strcpy(sprd_thm_name[id],"");
70 }
71 static int sprd_thermal_match_cdev(struct thermal_cooling_device *cdev,
72                                    struct sprd_trip_point *trip_point)
73 {
74         int i;
75         if (!strlen(cdev->type))
76                 return -EINVAL;
77         for (i = 0; i < COOLING_DEV_MAX; i++) {
78                 if (!strcmp(trip_point->cdev_name[i], cdev->type))
79                         return 0;
80         }
81         return -ENODEV;
82 }
83
84 /* Callback to bind cooling device to thermal zone */
85 static int sprd_cdev_bind(struct thermal_zone_device *thermal,
86                           struct thermal_cooling_device *cdev)
87 {
88         struct sprd_thermal_zone *pzone = thermal->devdata;
89         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
90         int i, ret = -EINVAL;
91
92         printk(KERN_INFO "sprd_cdev_bind--%d \n", pzone->sensor_id);
93         for (i = 0; i < ptrips->num_trips; i++) {
94                 if (sprd_thermal_match_cdev(cdev, &ptrips->trip_points[i]))
95                         continue;
96                 ret = thermal_zone_bind_cooling_device(thermal, i, cdev, THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
97                 dev_info(&cdev->device, "%s bind to %d: %d-%s\n", cdev->type,
98                          i, ret, ret ? "fail" : "succeed");
99         }
100         return 0;
101 }
102
103 /* Callback to unbind cooling device from thermal zone */
104 static int sprd_cdev_unbind(struct thermal_zone_device *thermal,
105                             struct thermal_cooling_device *cdev)
106 {
107         struct sprd_thermal_zone *pzone = thermal->devdata;
108         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
109         int i, ret = -EINVAL;
110
111         for (i = 0; i < ptrips->num_trips; i++) {
112                 if (sprd_thermal_match_cdev(cdev, &ptrips->trip_points[i]))
113                         continue;
114                 ret = thermal_zone_unbind_cooling_device(thermal, i, cdev);
115                 dev_info(&cdev->device, "%s unbind from %d: %s\n",
116                          cdev->type, i, ret ? "fail" : "succeed");
117         }
118         return ret;
119 }
120
121 /* Callback to get current temperature */
122 static int sprd_sys_get_temp(struct thermal_zone_device *thermal,
123                              unsigned long *temp)
124 {
125         struct sprd_thermal_zone *pzone = thermal->devdata;
126         if(!pzone->ops->read_temp)
127                 return -1;
128         *temp = pzone->ops->read_temp(pzone);
129         return 0;
130 }
131
132 /* Callback to get thermal zone mode */
133 static int sprd_sys_get_mode(struct thermal_zone_device *thermal,
134                              enum thermal_device_mode *mode)
135 {
136         struct sprd_thermal_zone *pzone = thermal->devdata;
137         mutex_lock(&pzone->th_lock);
138         *mode = pzone->mode;
139         mutex_unlock(&pzone->th_lock);
140         return 0;
141 }
142
143 /* Callback to set thermal zone mode */
144 static int sprd_sys_set_mode(struct thermal_zone_device *thermal,
145                              enum thermal_device_mode mode)
146 {
147         struct sprd_thermal_zone *pzone = thermal->devdata;
148         mutex_lock(&pzone->th_lock);
149         pzone->mode = mode;
150         if (mode == THERMAL_DEVICE_ENABLED)
151                 schedule_work(&pzone->therm_work);
152         mutex_unlock(&pzone->th_lock);
153         return 0;
154 }
155 #ifdef THM_TEST
156 static int sprd_sys_get_regs(struct thermal_zone_device *thermal,
157                             unsigned  int* regs)
158 {
159         struct sprd_thermal_zone *pzone = thermal->devdata;
160         if(!pzone->ops->reg_debug_get)
161                 return -1;
162         return pzone->ops->reg_debug_get(pzone,regs);
163 }
164
165 static int sprd_sys_set_regs(struct thermal_zone_device *thermal,
166                              unsigned int *regs)
167 {
168         struct sprd_thermal_zone *pzone = thermal->devdata;
169         if(!pzone->ops->reg_debug_set)
170                 return -1;
171         return pzone->ops->reg_debug_set(pzone,regs);
172 }
173
174 /* Callback to get thermal zone logtime */
175 static int sprd_sys_get_logtime(struct thermal_zone_device *thermal,
176                              unsigned long *logtime)
177 {
178         struct sprd_thermal_zone *pzone = thermal->devdata;
179         mutex_lock(&pzone->th_lock);
180         *logtime = pzone->logtime;
181         mutex_unlock(&pzone->th_lock);
182         return 0;
183 }
184
185 /* Callback to set thermal zone logtime */
186 static int sprd_sys_set_logtime(struct thermal_zone_device *thermal,
187                              unsigned long logtime)
188 {
189         struct sprd_thermal_zone *pzone = thermal->devdata;
190         mutex_lock(&pzone->th_lock);
191         pzone->logtime = logtime;
192         mutex_unlock(&pzone->th_lock);
193         return 0;
194 }
195
196 /* Callback to get thermal log switch status*/
197 static int sprd_sys_get_logswitch(struct thermal_zone_device *thermal,
198                              enum thermal_log_switch *logswitch)
199 {
200         struct sprd_thermal_zone *pzone = thermal->devdata;
201         mutex_lock(&pzone->th_lock);
202         *logswitch = pzone->thmlog_switch;
203         mutex_unlock(&pzone->th_lock);
204         return 0;
205 }
206
207 /* Callback to set thermal log switch status */
208 static int sprd_sys_set_logswitch(struct thermal_zone_device *thermal,
209                              enum thermal_log_switch logswitch)
210 {
211         struct sprd_thermal_zone *pzone = thermal->devdata;
212         mutex_lock(&pzone->th_lock);
213         pzone->thmlog_switch = logswitch;
214         if (logswitch == THERMAL_LOG_ENABLED)
215                 schedule_delayed_work(&pzone->thm_logtime_work, (HZ * pzone->logtime));
216         mutex_unlock(&pzone->th_lock);
217         return 0;
218 }
219
220
221 static ssize_t
222 debug_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
223 {
224         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
225         u32 regs[4] = {0};
226         sprd_sys_get_regs(tz,regs);
227         return sprintf(buf, "DET_PERI=%08x,MON_CTL=%08x,MON_PERI=%08x,SENSOR_CTL=%08x\n",
228                 regs[0],regs[1],regs[2],regs[3]);
229 }
230
231 static ssize_t
232 debug_reg_store(struct device *dev, struct device_attribute *attr,
233            const char *buf, size_t count)
234 {
235         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
236         unsigned int regs[4]={0};
237         if (!sscanf(buf, "%x,%x,%x,%x", &regs[0],&regs[1],&regs[2],&regs[3]))
238                 return -EINVAL;
239
240         printk("%x,%x,%x,%x\n", regs[0],regs[1],regs[2],regs[3]);
241         sprd_sys_set_regs(tz,regs);
242         return count;
243 }
244 static DEVICE_ATTR(debug_reg, 0644,debug_reg_show, debug_reg_store);
245
246 static int sprd_debug_get_trip_temp(struct thermal_zone_device *thermal,
247                                   int trip, unsigned long *temp,unsigned long *low_off)
248 {
249         struct sprd_thermal_zone *pzone = thermal->devdata;
250         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
251         if (trip >= ptrips->num_trips)
252                 return -EINVAL;
253         *temp = ptrips->trip_points[trip].temp;
254         *low_off = ptrips->trip_points[trip].lowoff;
255         return 0;
256 }
257
258 static int sprd_debug_set_trip_temp(struct thermal_zone_device *thermal,
259                                   int trip, unsigned long temp,unsigned long low_off)
260 {
261         struct sprd_thermal_zone *pzone = thermal->devdata;
262         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
263         if(!pzone->ops->trip_debug_set)
264                 return 0;
265         ptrips->trip_points[trip].temp = temp;
266         ptrips->trip_points[trip].lowoff = low_off;
267         return pzone->ops->trip_debug_set(pzone,trip);
268 }
269 static ssize_t
270 trip_point_debug_temp_show(struct device *dev, struct device_attribute *attr,
271                      char *buf)
272 {
273         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
274         int trip, ret;
275         long temperature,low_off;
276         if (!sscanf(attr->attr.name, "trip_%d_temp", &trip))
277                 return -EINVAL;
278         ret = sprd_debug_get_trip_temp(tz, trip, &temperature,&low_off);
279
280         if (ret)
281                 return ret;
282         return sprintf(buf, "tem = %ld,low_off=%ld\n", temperature,low_off);
283 }
284 static ssize_t
285 trip_point_debug_temp_store(struct device *dev, struct device_attribute *attr,
286                      const char *buf, size_t count)
287 {
288         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
289         int trip, ret;
290         unsigned long temperature,low_off;
291         if (!sscanf(attr->attr.name, "trip_%d_temp", &trip))
292                 return -EINVAL;
293         if(!sscanf(buf,"%ld,%ld",&temperature,&low_off))
294                 return -EINVAL;
295         ret = sprd_debug_set_trip_temp(tz, trip, temperature, low_off);
296         return ret ? ret : count;
297 }
298
299 static ssize_t
300 logtime_show(struct device *dev, struct device_attribute *attr, char *buf)
301 {
302         //struct thermal_zone_device *tz = to_thermal_zone(dev);
303         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
304         unsigned long logtime;
305         int result;
306         result = sprd_sys_get_logtime(tz, &logtime);
307         if (result)
308                 return result;
309
310         return sprintf(buf, "%ld\n", logtime);
311
312 }
313 static ssize_t
314 logtime_store(struct device *dev, struct device_attribute *attr,
315            const char *buf, size_t count)
316 {
317         //struct thermal_zone_device *tz = to_thermal_zone(dev);
318         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
319         int result;
320         unsigned long logtime;
321         if (kstrtoul(buf, 10, &logtime))
322                 return -EINVAL;
323         result = sprd_sys_set_logtime(tz, logtime);
324         if (result)
325                 return result;
326
327         return count;
328 }
329 static ssize_t
330 logswitch_show(struct device *dev, struct device_attribute *attr, char *buf)
331 {
332         //struct thermal_zone_device *tz = to_thermal_zone(dev);
333         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
334         enum thermal_log_switch logswtich;
335         int result;
336
337         result = sprd_sys_get_logswitch(tz, &logswtich);
338         if (result)
339                 return result;
340
341         return sprintf(buf, "%s\n", logswtich == THERMAL_LOG_ENABLED ? "enabled"
342                        : "disabled");
343 }
344 static ssize_t
345 logswitch_store(struct device *dev, struct device_attribute *attr,
346            const char *buf, size_t count)
347 {
348         struct thermal_zone_device *tz = container_of(dev, struct thermal_zone_device, device);
349         int result;
350
351         if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
352                 result = sprd_sys_set_logswitch(tz, THERMAL_LOG_ENABLED);
353         else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
354                 result = sprd_sys_set_logswitch(tz, THERMAL_LOG_DISABLED);
355         else
356                 result = -EINVAL;
357
358         if (result)
359                 return result;
360
361         return count;
362 }
363
364 static DEVICE_ATTR(logtime, 0644, logtime_show, logtime_store);
365 static DEVICE_ATTR(logswitch, 0644, logswitch_show, logswitch_store);
366
367 static int create_trip_attrs(struct thermal_zone_device *tz)
368 {
369         int indx;
370         int size = sizeof(struct thermal_attr) * tz->trips;
371     int result;
372         result = device_create_file(&tz->device, &dev_attr_logswitch);
373         if (result)
374                 return result;
375         result = device_create_file(&tz->device, &dev_attr_logtime);
376         if (result)
377             return result;
378         tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
379         if (!tz->trip_temp_attrs) {
380                 return -ENOMEM;
381         }
382
383         for (indx = 0; indx < tz->trips; indx++) {
384                 /* create trip temp attribute */
385                 snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
386                          "trip_%d_temp", indx);
387
388                 sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
389                 tz->trip_temp_attrs[indx].attr.attr.name =
390                                                 tz->trip_temp_attrs[indx].name;
391                 tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
392                 tz->trip_temp_attrs[indx].attr.show = trip_point_debug_temp_show;
393                 tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
394                 tz->trip_temp_attrs[indx].attr.store =trip_point_debug_temp_store;
395                 device_create_file(&tz->device,
396                                    &tz->trip_temp_attrs[indx].attr);
397         }
398         return 0;
399 }
400
401 static void remove_trip_attrs(struct thermal_zone_device *tz)
402 {
403         int indx;
404         device_remove_file(&tz->device, &dev_attr_logswitch);
405         device_remove_file(&tz->device, &dev_attr_logtime);
406         for (indx = 0; indx < tz->trips; indx++) {
407                 device_remove_file(&tz->device,
408                                    &tz->trip_temp_attrs[indx].attr);
409         }
410         kfree(tz->trip_temp_attrs);
411 }
412 #endif
413 static int sprd_sys_get_trend(struct thermal_zone_device *thermal,
414                 int trip, enum thermal_trend * ptrend)
415 {
416         struct sprd_thermal_zone *pzone = thermal->devdata;
417         return pzone->ops->get_trend(pzone, trip, ptrend);
418 }
419
420 static int sprd_sys_get_hyst(struct thermal_zone_device *thermal,
421                 int trip, unsigned long *physt)
422 {
423         struct sprd_thermal_zone *pzone = thermal->devdata;
424         return pzone->ops->get_hyst(pzone, trip, physt);
425 }
426
427
428 /* Callback to get trip point type */
429 static int sprd_sys_get_trip_type(struct thermal_zone_device *thermal,
430                                   int trip, enum thermal_trip_type *type)
431 {
432         struct sprd_thermal_zone *pzone = thermal->devdata;
433         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
434         if (trip >= ptrips->num_trips)
435                 return -EINVAL;
436         *type = ptrips->trip_points[trip].type;
437         return 0;
438 }
439
440 /* Callback to get trip point temperature */
441 static int sprd_sys_get_trip_temp(struct thermal_zone_device *thermal,
442                                   int trip, unsigned long *temp)
443 {
444         struct sprd_thermal_zone *pzone = thermal->devdata;
445         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
446         if (trip >= ptrips->num_trips)
447                 return -EINVAL;
448         *temp = ptrips->trip_points[trip].temp;
449         return 0;
450 }
451
452 /* Callback to get critical trip point temperature */
453 static int sprd_sys_get_crit_temp(struct thermal_zone_device *thermal,
454                                   unsigned long *temp)
455 {
456         struct sprd_thermal_zone *pzone = thermal->devdata;
457         struct sprd_thm_platform_data *ptrips = pzone->trip_tab;
458         int i;
459         for (i = ptrips->num_trips - 1; i > 0; i--) {
460                 if (ptrips->trip_points[i].type == THERMAL_TRIP_CRITICAL) {
461                         *temp = ptrips->trip_points[i].temp;
462                         return 0;
463                 }
464         }
465         return -EINVAL;
466 }
467
468 static struct thermal_zone_device_ops thdev_ops = {
469         .bind = sprd_cdev_bind,
470         .unbind = sprd_cdev_unbind,
471         .get_temp = sprd_sys_get_temp,
472         .get_mode = sprd_sys_get_mode,
473         .set_mode = sprd_sys_set_mode,
474         .get_trip_type = sprd_sys_get_trip_type,
475         .get_trip_temp = sprd_sys_get_trip_temp,
476         .get_trip_hyst = sprd_sys_get_hyst,
477         .get_crit_temp = sprd_sys_get_crit_temp,
478         .get_trend = sprd_sys_get_trend,
479 };
480
481 static irqreturn_t sprd_thm_irq_handler(int irq, void *irq_data)
482 {
483         struct sprd_thermal_zone *pzone = irq_data;
484
485         dev_dbg(&pzone->therm_dev->device, "sprd_thm_irq_handler\n");
486         if (!pzone->ops->irq_handle(pzone)) {
487                 schedule_work(&pzone->therm_work);
488         }
489         return IRQ_HANDLED;
490 }
491
492 static void sprd_thermal_work(struct work_struct *work)
493 {
494         enum thermal_device_mode cur_mode;
495         struct sprd_thermal_zone *pzone;
496
497         pzone = container_of(work, struct sprd_thermal_zone, therm_work);
498         mutex_lock(&pzone->th_lock);
499         cur_mode = pzone->mode;
500         mutex_unlock(&pzone->th_lock);
501         if (cur_mode == THERMAL_DEVICE_DISABLED)
502                 return;
503         thermal_zone_device_update(pzone->therm_dev);
504         dev_dbg(&pzone->therm_dev->device, "thermal work finished.\n");
505 }
506
507 static void sprd_thermal_resume_delay_work(struct work_struct *work)
508 {
509         struct sprd_thermal_zone *pzone;
510
511         pzone = container_of(work, struct sprd_thermal_zone, resume_delay_work.work);
512         dev_dbg(&pzone->therm_dev->device, "thermal resume delay work Started.\n");
513         pzone->ops->resume(pzone);
514         dev_dbg(&pzone->therm_dev->device, "thermal resume delay work finished.\n");
515 }
516
517 #ifdef CONFIG_OF
518 static struct sprd_thm_platform_data *thermal_detect_parse_dt(
519                          struct device *dev)
520 {
521         struct sprd_thm_platform_data *pdata;
522         struct device_node *np = dev->of_node;
523         const char *cooling_names = "cooling-names";
524         const char *point_arr[16];
525         int ret;
526         u32 trip_points_critical,trip_num,cool_num;
527         u32 trip_temp[COOLING_DEV_MAX], trip_lowoff[COOLING_DEV_MAX];
528         int i = 0,j=0,cool=1,k;
529
530         pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
531         if (!pdata) {
532                 dev_err(dev, "could not allocate memory for platform data\n");
533                 return NULL;
534         }
535         ret = of_property_read_u32(np, "trip_points_critical", &trip_points_critical);
536         if(ret){
537                 dev_err(dev, "fail to get trip_points_critical\n");
538                 goto fail;
539         }
540         ret = of_property_read_u32(np, "trip_num", &trip_num);
541         if(ret){
542                 dev_err(dev, "fail to get trip_num\n");
543                 goto fail;
544         }
545         ret = of_property_read_u32(np, "cool_num", &cool_num);
546         if(ret){
547                 cool=0;
548         }else{
549                 cool=1;
550         }
551         for (i = 0; i < trip_num-1; i++) {
552                 ret = of_property_read_u32_index(np, "trip_points_active", i,
553                                                  &trip_temp[i]);
554                 if(ret){
555                         dev_err(dev, "fail to get trip_points_active\n");
556                         goto fail;
557                 }
558                 ret = of_property_read_u32_index(np, "trip_points_lowoff", i,
559                                                  &trip_lowoff[i]);
560                 if(ret){
561                         dev_err(dev, "fail to get trip_points_lowoff\n");
562                         goto fail;
563                 }
564         }
565         if(cool==1){
566          for (j = 0; j < cool_num*(trip_num-1); ++j){
567                 ret = of_property_read_string_index(np, cooling_names, j,
568                                                                   &point_arr[j]);
569                 if (ret) {
570                                 printk("cooling_names: %s: missing %s in dt node\n", __func__, cooling_names);
571                                 } else {
572                                 printk("cooling_names: %s: %s is %s\n", __func__, cooling_names, point_arr[j]);
573                                 }
574                         }
575          }
576         pdata->num_trips = trip_num;
577     
578         for (i = 0; i < trip_num -1; ++i){
579                         pdata->trip_points[i].temp = trip_temp[i];
580                         pdata->trip_points[i].lowoff = trip_lowoff[i];
581                         pdata->trip_points[i].type = THERMAL_TRIP_ACTIVE;
582                         if(cool==1){
583                                 for (k = 0; k < cool_num; ++k){
584                                         memcpy(pdata->trip_points[i].cdev_name[k],
585                                                         point_arr[i+k*(trip_num-1)], strlen(point_arr[i+k*(trip_num-1)])+1);
586                                         dev_info(dev,"cdev name: %s \n", pdata->trip_points[i].cdev_name[k]);
587                                         }
588                            }else{
589                         memcpy(pdata->trip_points[i].cdev_name[0],
590                                         "thermal-cpufreq-0", sizeof("thermal-cpufreq-0"));
591                         dev_info(dev, "def cdev name:is %s\n",  pdata->trip_points[i].cdev_name[0]);
592                         }
593                         dev_info(dev, "trip[%d] temp: %d lowoff: %d\n",
594                                         i, trip_temp[i], trip_lowoff[i]);
595                                 
596         }
597         pdata->trip_points[i].temp = trip_points_critical;
598         pdata->trip_points[i].type = THERMAL_TRIP_CRITICAL;
599
600         return pdata;
601
602 fail:
603         kfree(pdata);
604         return NULL;
605
606 }
607
608 #endif
609
610 #ifdef CONFIG_OF
611 extern int of_address_to_resource(struct device_node *dev, int index,
612                                   struct resource *r);
613 #endif
614
615 static void thm_logtime_work(struct work_struct *work)
616 {
617         struct sprd_thermal_zone *pzone;
618         int temp;
619         pzone = container_of(work, struct sprd_thermal_zone, thm_logtime_work.work);
620         temp = pzone->ops->read_temp(pzone);
621     printk(" thm sensor id:%d, logtime:%ld, temp:%d\n", pzone->sensor_id,pzone->logtime,temp);
622         if(pzone->thmlog_switch){
623                 schedule_delayed_work(&pzone->thm_logtime_work, (HZ * pzone->logtime));
624         }
625 }
626
627 static int sprd_thermal_probe(struct platform_device *pdev)
628 {
629         struct sprd_thermal_zone *pzone = NULL;
630         struct sprd_thm_platform_data *ptrips = NULL;
631         struct resource *regs;
632         int thm_irq, ret = 0;
633 #ifdef CONFIG_OF
634         struct device_node *np = pdev->dev.of_node;
635 #endif
636
637         printk(KERN_INFO " sprd_thermal_probe id:%d\n", pdev->id);
638 #ifdef CONFIG_OF
639         if (!np) {
640                 dev_err(&pdev->dev, "device node not found\n");
641                 return -EINVAL;
642         }
643         ptrips = thermal_detect_parse_dt(&pdev->dev);
644 #else
645         ptrips = dev_get_platdata(&pdev->dev);
646 #endif
647         if (!ptrips)
648                 return -EINVAL;
649         pzone = devm_kzalloc(&pdev->dev, sizeof(*pzone), GFP_KERNEL);
650         if (!pzone)
651                 return -ENOMEM;
652         mutex_init(&pzone->th_lock);
653         mutex_lock(&pzone->th_lock);
654         pzone->mode = THERMAL_DEVICE_DISABLED;
655         pzone->trip_tab = ptrips;
656         pzone->trend_val = THERMAL_TREND_STABLE;
657 #ifdef CONFIG_OF
658         ret = of_property_read_u32(np, "id", &pdev->id);
659         if(ret){
660                 printk(KERN_INFO "sprd_thermal_probe No sensor ID \n");
661                 return -EINVAL;
662         }
663         pzone->sensor_id = pdev->id;
664 #else
665         pzone->sensor_id = pdev->id;
666 #endif
667     pzone->logtime= 2;
668         pzone->thmlog_switch= THERMAL_LOG_DISABLED;
669         INIT_DELAYED_WORK(&pzone->thm_logtime_work, thm_logtime_work);
670         ret = sprd_thm_ops_init(pzone);
671         if(ret){
672                 dev_err(&pdev->dev, " pzone->ops =NULL id =%d\n",pzone->sensor_id);
673                 return -ENODEV;
674         }
675         INIT_WORK(&pzone->therm_work, sprd_thermal_work);
676         INIT_DELAYED_WORK(&pzone->resume_delay_work,sprd_thermal_resume_delay_work);
677 #ifdef CONFIG_OF
678         regs = kzalloc(sizeof(*regs), GFP_KERNEL);
679         ret = of_address_to_resource(np, 0, regs);
680 #else
681         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
682 #endif
683         if (!regs) {
684                 return -ENXIO;
685         }
686         ret = pzone->ops->get_reg_base(pzone , regs);
687         if(ret<0){
688                 dev_err(&pdev->dev, "Failed to get_reg_base.\n");
689                 return ret;
690         }
691         printk(KERN_INFO "sprd_thermal_probe id:%d,base:0x%lx \n", pdev->id,
692                (unsigned long)pzone->reg_base);
693 #ifdef CONFIG_OF
694         thm_irq = irq_of_parse_and_map(np, 0);
695 #else
696         thm_irq = platform_get_irq(pdev, 0);
697 #endif
698         if (thm_irq < 0) {
699                 dev_err(&pdev->dev, "Get IRQ_THM_INT failed.\n");
700                 return thm_irq;
701         }
702         ret =
703             devm_request_threaded_irq(&pdev->dev, thm_irq, NULL,
704                                       sprd_thm_irq_handler,
705                                       IRQF_NO_SUSPEND | IRQF_ONESHOT | IRQF_SHARED,
706                                       "sprd_thm_irq", pzone);
707         if (ret < 0) {
708                 dev_err(&pdev->dev, "Failed to allocate temp low irq.\n");
709                 return ret;
710         }
711
712         pzone->therm_dev =
713             thermal_zone_device_register(pzone->thermal_zone_name,
714                                          ptrips->num_trips, 0, pzone,
715                                          &thdev_ops, 0, 0, 0); 
716         if (IS_ERR_OR_NULL(pzone->therm_dev)) {
717                 dev_err(&pdev->dev, "Register thermal zone device failed.\n");
718                 return PTR_ERR(pzone->therm_dev);
719         }
720         dev_info(&pdev->dev, "Thermal zone device registered.\n");
721
722         pzone->ops->hw_init(pzone);
723         platform_set_drvdata(pdev, pzone);
724         pzone->mode = THERMAL_DEVICE_ENABLED;
725         mutex_unlock(&pzone->th_lock);
726
727 #ifdef THM_TEST
728         create_trip_attrs(pzone->therm_dev);    
729         ret = device_create_file(&pzone->therm_dev->device, &dev_attr_debug_reg);
730                 if (ret)
731                         dev_err(&pdev->dev, "create regs debug fail\n");
732 #endif
733         return 0;
734 }
735
736 static int sprd_thermal_remove(struct platform_device *pdev)
737 {
738         struct sprd_thermal_zone *pzone = platform_get_drvdata(pdev);
739 #ifdef THM_TEST
740         remove_trip_attrs(pzone->therm_dev);
741         device_remove_file(&pzone->therm_dev->device, &dev_attr_debug_reg);
742 #endif
743         thermal_zone_device_unregister(pzone->therm_dev);
744         cancel_work_sync(&pzone->therm_work);
745         mutex_destroy(&pzone->th_lock);
746         return 0;
747 }
748
749 static int sprd_thermal_suspend(struct platform_device *pdev,
750                                 pm_message_t state)
751 {
752         struct sprd_thermal_zone *pzone = platform_get_drvdata(pdev);
753         flush_work(&pzone->therm_work);
754         flush_delayed_work(&pzone->resume_delay_work);
755         pzone->ops->suspend(pzone);
756         return 0;
757 }
758
759 static int sprd_thermal_resume(struct platform_device *pdev)
760 {
761         struct sprd_thermal_zone *pzone = platform_get_drvdata(pdev);
762         schedule_delayed_work(&pzone->resume_delay_work, (HZ * 1));
763         //sprd_thm_hw_resume(pzone);
764
765         return 0;
766 }
767
768 #ifdef CONFIG_OF
769 static const struct of_device_id thermal_of_match[] = {
770         { .compatible = "sprd,sprd-thermal", },
771        {}
772 };
773 #endif
774
775 static struct platform_driver sprd_thermal_driver = {
776         .probe = sprd_thermal_probe,
777         .suspend = sprd_thermal_suspend,
778         .resume = sprd_thermal_resume,
779         .remove = sprd_thermal_remove,
780         .driver = {
781                    .owner = THIS_MODULE,
782                    .name = "sprd-thermal",
783 #ifdef CONFIG_OF
784                         .of_match_table = of_match_ptr(thermal_of_match),
785 #endif
786                    },
787 };
788 static int __init sprd_thermal_init(void)
789 {
790         return platform_driver_register(&sprd_thermal_driver);
791 }
792
793 static void __exit sprd_thermal_exit(void)
794 {
795         platform_driver_unregister(&sprd_thermal_driver);
796 }
797
798 //module_init(sprd_thermal_init);
799 //module_exit(sprd_thermal_exit);
800
801 device_initcall_sync(sprd_thermal_init);
802 module_exit(sprd_thermal_exit);
803 // module_platform_driver(sprd_thermal_driver);
804 MODULE_AUTHOR("Mingwei Zhang <mingwei.zhang@spreadtrum.com>");
805 MODULE_DESCRIPTION("sprd thermal driver");
806 MODULE_LICENSE("GPL");