Merge tag 'lsk-android-14.04' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / hwmon / rockchip_tsadc.c
1 /*
2  * Copyright (C) ST-Ericsson 2010 - 2013
3  * Author: Martin Persson <martin.persson@stericsson.com>
4  *         Hongbo Zhang <hongbo.zhang@linaro.org>
5  * License Terms: GNU General Public License v2
6  *
7  * When the AB8500 thermal warning temperature is reached (threshold cannot
8  * be changed by SW), an interrupt is set, and if no further action is taken
9  * within a certain time frame, pm_power off will be called.
10  *
11  * When AB8500 thermal shutdown temperature is reached a hardware shutdown of
12  * the AB8500 will occur.
13  */
14
15  #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/init.h>
18 #include <linux/device.h>
19 #include <linux/platform_device.h>
20 #include <linux/err.h>
21 #include <linux/clk.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/io.h>
25 #include <linux/delay.h>
26 #include <linux/slab.h>
27 #include <linux/workqueue.h>
28 #include <linux/ioport.h>
29
30 #include <linux/err.h>
31 #include <linux/hwmon.h>
32 #include <linux/hwmon-sysfs.h>
33 #include <linux/module.h>
34 #include <linux/slab.h>
35 #include <linux/sysfs.h>
36
37 #include <linux/timer.h>
38 #include <linux/completion.h>
39 #include <linux/of_irq.h>
40 #include <linux/regulator/consumer.h>
41 #include <linux/of_platform.h>
42 #include <linux/of.h>
43 #include <linux/of_device.h>
44 #include "hwmon-rockchip.h"
45
46
47 #define DEFAULT_POWER_OFF_DELAY (HZ * 10)
48 /* Number of monitored sensors should not greater than NUM_SENSORS */
49 #define NUM_MONITORED_SENSORS   4
50
51 #define TSADC_USER_CON  0x00
52 #define TSADC_AUTO_CON  0x04
53
54 #define TSADC_CTRL_CH(ch)       ((ch) << 0)
55 #define TSADC_CTRL_POWER_UP     (1 << 3)
56 #define TSADC_CTRL_START        (1 << 4)
57
58 #define TSADC_STAS_BUSY         (1 << 12)
59 #define TSADC_STAS_BUSY_MASK    (1 << 12)
60 #define TSADC_AUTO_STAS_BUSY            (1 << 16)
61 #define TSADC_AUTO_STAS_BUSY_MASK       (1 << 16)
62 #define TSADC_SAMPLE_DLY_SEL  (1 << 17)
63 #define TSADC_SAMPLE_DLY_SEL_MASK  (1 << 17)
64
65 #define TSADC_INT_EN  0x08
66 #define TSADC_INT_PD  0x0c
67
68 #define TSADC_DATA0  0x20
69 #define TSADC_DATA1  0x24
70 #define TSADC_DATA2  0x28
71 #define TSADC_DATA3  0x2c
72 #define TSADC_DATA_MASK         0xfff
73
74 #define TSADC_COMP0_INT  0x30
75 #define TSADC_COMP1_INT  0x34
76 #define TSADC_COMP2_INT  0x38
77 #define TSADC_COMP3_INT  0x3c
78
79 #define TSADC_COMP0_SHUT  0x40
80 #define TSADC_COMP1_SHUT  0x44
81 #define TSADC_COMP2_SHUT  0x48
82 #define TSADC_COMP3_SHUT  0x4c
83
84 #define TSADC_HIGHT_INT_DEBOUNCE  0x60
85 #define TSADC_HIGHT_TSHUT_DEBOUNCE  0x64
86 #define TSADC_HIGHT_INT_DEBOUNCE_TIME 0x03
87 #define TSADC_HIGHT_TSHUT_DEBOUNCE_TIME 0x03
88
89 #define TSADC_AUTO_PERIOD  0x68
90 #define TSADC_AUTO_PERIOD_HT  0x6c
91 #define TSADC_AUTO_PERIOD_TIME  0x10
92 #define TSADC_AUTO_PERIOD_HT_TIME  0x10
93
94 #define TSADC_AUTO_EVENT_NAME           "tsadc"
95
96 #define TSADC_COMP_INT_DATA             80
97 #define TSADC_COMP_INT_DATA_MASK                0xfff
98 #define TSADC_COMP_SHUT_DATA            100
99 #define TSADC_COMP_SHUT_DATA_MASK               0xfff
100 #define TSADC_HIGH_TEMP_TO_SHUTDOWN 0  // 1: set gpio0_a0 output 0 ; 0:reset cpu
101 #define TSADC_TEMP_INT_EN 1
102 #define TSADC_TEMP_SHUT_EN 1
103
104 struct rockchip_tsadc_temp {
105         struct delayed_work power_off_work;
106         struct rockchip_temp *rockchip_data;
107         void __iomem            *regs;
108         struct clk              *clk;
109         struct clk              *pclk;
110         int irq;
111         struct resource         *ioarea;
112         struct tsadc_host               *tsadc;
113         struct work_struct      auto_ht_irq_work;
114         struct workqueue_struct  *workqueue;
115         struct workqueue_struct  *tsadc_workqueue;
116 };
117 struct tsadc_table
118 {
119         int code;
120         int temp;
121 };
122
123 static const struct tsadc_table table[] =
124 {
125         {TSADC_DATA_MASK, -40},
126
127         {3800, -40},
128         {3792, -35},
129         {3783, -30},
130         {3774, -25},
131         {3765, -20},
132         {3756, -15},
133         {3747, -10},
134         {3737, -5},
135         {3728, 0},
136         {3718, 5},
137
138         {3708, 10},
139         {3698, 15},
140         {3688, 20},
141         {3678, 25},
142         {3667, 30},
143         {3656, 35},
144         {3645, 40},
145         {3634, 45},
146         {3623, 50},
147         {3611, 55},
148
149         {3600, 60},
150         {3588, 65},
151         {3575, 70},
152         {3563, 75},
153         {3550, 80},
154         {3537, 85},
155         {3524, 90},
156         {3510, 95},
157         {3496, 100},
158         {3482, 105},
159
160         {3467, 110},
161         {3452, 115},
162         {3437, 120},
163         {3421, 125},
164
165         {0, 125},
166 };
167
168 static struct rockchip_tsadc_temp *g_dev;
169
170 static DEFINE_MUTEX(tsadc_mutex);
171
172 static u32 tsadc_readl(u32 offset)
173 {
174         return readl_relaxed(g_dev->regs + offset);
175 }
176
177 static void tsadc_writel(u32 val, u32 offset)
178 {
179         writel_relaxed(val, g_dev->regs + offset);
180 }
181
182 void rockchip_tsadc_auto_ht_work(struct work_struct *work)
183 {
184         int ret,val;
185
186 //      printk("%s,line=%d\n", __func__,__LINE__);
187
188         mutex_lock(&tsadc_mutex);
189
190         val = tsadc_readl(TSADC_INT_PD);
191         tsadc_writel(val &(~ (1 <<8) ), TSADC_INT_PD);
192         ret = tsadc_readl(TSADC_INT_PD);
193         tsadc_writel(ret | 0xff, TSADC_INT_PD);       //clr irq status
194         if ((val & 0x0f) != 0){
195                 printk("rockchip tsadc is over temp . %s,line=%d\n", __func__,__LINE__);
196                 pm_power_off();                                 //power_off
197         }
198         mutex_unlock(&tsadc_mutex);
199 }
200
201 static irqreturn_t rockchip_tsadc_auto_ht_interrupt(int irq, void *data)
202 {
203         struct rockchip_tsadc_temp *dev = data;
204
205         printk("%s,line=%d\n", __func__,__LINE__);
206         
207         queue_work(dev->workqueue, &dev->auto_ht_irq_work);
208         
209         return IRQ_HANDLED;
210 }
211
212 static void rockchip_tsadc_set_cmpn_int_vale( int chn, int temp)
213 {
214         u32 code = 0;
215         int i;
216
217         for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
218                 if (temp <= table[i].temp && temp > table[i -1].temp) {
219                         code = table[i].code;
220                 }
221         }
222         tsadc_writel((code & TSADC_COMP_INT_DATA_MASK), (TSADC_COMP0_INT + chn*4));
223
224 }
225
226 static void rockchip_tsadc_set_cmpn_shut_vale( int chn, int temp)
227 {
228         u32 code=0;
229         int i;
230
231         for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
232                 if (temp <= table[i].temp && temp > table[i -1].temp) {
233                         code = table[i].code;
234                 }
235         }
236
237         tsadc_writel((code & TSADC_COMP_SHUT_DATA_MASK), (TSADC_COMP0_SHUT + chn*4));
238 }
239
240 static void rockchip_tsadc_set_auto_int_en( int chn, int ht_int_en,int tshut_en)
241 {
242         u32 ret;
243         tsadc_writel(0, TSADC_INT_EN);
244         if (ht_int_en){
245                 ret = tsadc_readl(TSADC_INT_EN);
246                 tsadc_writel( ret | (1 << chn), TSADC_INT_EN);
247         }
248         if (tshut_en){
249                 ret = tsadc_readl(TSADC_INT_EN);
250                 #ifdef TSADC_HIGH_TEMP_TO_SHUTDOWN
251                 tsadc_writel( ret | (1 << (chn + 4)), TSADC_INT_EN);
252                 #else
253                 tsadc_writel( ret | (1 << (chn + 8)), TSADC_INT_EN);
254                 #endif
255         }       
256
257 }
258 static void rockchip_tsadc_auto_mode_set( int chn, int int_temp, int shut_temp,int int_en, int shut_en)
259 {
260
261         u32 ret;
262         
263         if (!g_dev || chn > 1)
264                 return;
265         
266         mutex_lock(&tsadc_mutex);
267         
268         clk_enable(g_dev->pclk);
269         clk_enable(g_dev->clk);
270         
271         msleep(10);
272         tsadc_writel(0, TSADC_AUTO_CON);
273         tsadc_writel( 1 << (4+chn), TSADC_AUTO_CON);
274         msleep(10);
275         if ((tsadc_readl(TSADC_AUTO_CON) & TSADC_AUTO_STAS_BUSY_MASK) != TSADC_AUTO_STAS_BUSY) {
276                 rockchip_tsadc_set_cmpn_int_vale(chn,int_temp);
277                 rockchip_tsadc_set_cmpn_shut_vale(chn,shut_temp),
278
279 //              tsadc_writel(TSADC_AUTO_PERIOD_TIME, TSADC_AUTO_PERIOD);
280 //              tsadc_writel(TSADC_AUTO_PERIOD_HT_TIME, TSADC_AUTO_PERIOD_HT);
281
282 //              tsadc_writel(TSADC_HIGHT_INT_DEBOUNCE_TIME, TSADC_HIGHT_INT_DEBOUNCE);
283 //              tsadc_writel(TSADC_HIGHT_TSHUT_DEBOUNCE_TIME, TSADC_HIGHT_TSHUT_DEBOUNCE);
284                 
285                 rockchip_tsadc_set_auto_int_en(chn,int_en,shut_en);     
286         }
287
288         msleep(10);
289
290         ret = tsadc_readl(TSADC_AUTO_CON);
291         tsadc_writel(ret | (1 <<0) , TSADC_AUTO_CON);
292         
293         mutex_unlock(&tsadc_mutex);
294                 
295 }
296
297 int rockchip_tsadc_set_auto_temp(int chn)
298 {
299         rockchip_tsadc_auto_mode_set(chn, TSADC_COMP_INT_DATA,TSADC_COMP_SHUT_DATA,TSADC_TEMP_INT_EN,TSADC_TEMP_SHUT_EN);
300         return 0;
301 }
302 EXPORT_SYMBOL(rockchip_tsadc_set_auto_temp);
303
304 static void rockchip_tsadc_get(int chn, int *temp, int *code)
305 {
306         *temp = 0;
307         *code = 0;
308
309         if (!g_dev || chn > 4){
310                 *temp = 150;
311                 return ;
312         }
313                 
314         mutex_lock(&tsadc_mutex);
315
316         clk_enable(g_dev->pclk);
317         clk_enable(g_dev->clk);
318
319         msleep(10);
320         tsadc_writel(0, TSADC_USER_CON);
321         tsadc_writel(TSADC_CTRL_POWER_UP | TSADC_CTRL_CH(chn), TSADC_USER_CON);
322         msleep(20);
323         if ((tsadc_readl(TSADC_USER_CON) & TSADC_STAS_BUSY_MASK) != TSADC_STAS_BUSY) {
324                 int i;
325                 *code = tsadc_readl((TSADC_DATA0 + chn*4)) & TSADC_DATA_MASK;
326                 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
327                         if ((*code) <= table[i].code && (*code) > table[i + 1].code) {
328                                 *temp = table[i].temp + (table[i + 1].temp - table[i].temp) * (table[i].code - (*code)) / (table[i].code - table[i + 1].code);
329                         }
330                 }
331         }
332         
333         tsadc_writel(0, TSADC_USER_CON);
334
335         clk_disable(g_dev->clk);
336         clk_disable(g_dev->pclk);
337
338         mutex_unlock(&tsadc_mutex);
339 }
340
341  int rockchip_tsadc_get_temp(int chn)
342 {
343         int temp, code;
344         
345         rockchip_tsadc_get(chn, &temp, &code);
346         return temp;
347 }
348 EXPORT_SYMBOL(rockchip_tsadc_get_temp);
349
350 static ssize_t rockchip_show_name(struct device *dev,
351                 struct device_attribute *devattr, char *buf)
352 {
353         return sprintf(buf, "rockchip-tsadc\n");
354 }
355
356 static ssize_t rockchip_show_label(struct device *dev,
357                 struct device_attribute *devattr, char *buf)
358 {
359         char *label;
360         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
361         int index = attr->index;
362
363         switch (index) {
364         case 0:
365                 label = "tsadc0";
366                 break;
367         case 1:
368                 label = "tsadc1";
369                 break;
370         case 2:
371                 label = "tsadc2";
372                 break;
373         case 3:
374                 label = "tsadc3";
375                 break;
376         default:
377                 return -EINVAL;
378         }
379
380         return sprintf(buf, "%s\n", label);
381 }
382
383
384 int rockchip_hwmon_init(struct rockchip_temp *data)
385 {
386         struct rockchip_tsadc_temp *rockchip_tsadc_data;
387         struct resource *res;
388         struct device_node *np = data->pdev->dev.of_node;
389         int ret,irq;
390         u32 rate;
391         
392         rockchip_tsadc_data = devm_kzalloc(&data->pdev->dev, sizeof(*rockchip_tsadc_data),
393                 GFP_KERNEL);
394         if (!rockchip_tsadc_data)
395                 return -ENOMEM;
396
397         res = platform_get_resource(data->pdev, IORESOURCE_MEM, 0);
398         rockchip_tsadc_data->regs = devm_request_and_ioremap(&data->pdev->dev, res);
399         if (!rockchip_tsadc_data->regs) {
400                 dev_err(&data->pdev->dev, "cannot map IO\n");
401                 return -ENXIO;
402         } 
403
404         //irq request   
405         irq = platform_get_irq(data->pdev, 0);
406         if (irq < 0) {
407                 dev_err(&data->pdev->dev, "no irq resource?\n");
408                 return -EPERM;
409         }
410         rockchip_tsadc_data->irq = irq;
411         ret = request_threaded_irq(rockchip_tsadc_data->irq, NULL, rockchip_tsadc_auto_ht_interrupt, IRQF_ONESHOT, TSADC_AUTO_EVENT_NAME, rockchip_tsadc_data);
412         if (ret < 0) {
413                 dev_err(&data->pdev->dev, "failed to attach tsadc irq\n");
414                 return -EPERM;
415         }       
416
417         rockchip_tsadc_data->workqueue = create_singlethread_workqueue("rockchip_tsadc");
418         INIT_WORK(&rockchip_tsadc_data->auto_ht_irq_work, rockchip_tsadc_auto_ht_work);
419         
420         //clk enable
421         rockchip_tsadc_data->clk = devm_clk_get(&data->pdev->dev, "tsadc");
422         if (IS_ERR(rockchip_tsadc_data->clk)) {
423             dev_err(&data->pdev->dev, "failed to get tsadc clock\n");
424             ret = PTR_ERR(rockchip_tsadc_data->clk);
425             return -EPERM;
426         }
427
428         if(of_property_read_u32(np, "clock-frequency", &rate)) {
429           dev_err(&data->pdev->dev, "Missing clock-frequency property in the DT.\n");
430           return -EPERM;
431         }
432
433         ret = clk_set_rate(rockchip_tsadc_data->clk, rate);
434             if(ret < 0) {
435             dev_err(&data->pdev->dev, "failed to set adc clk\n");
436             return -EPERM;
437         }
438         clk_prepare_enable(rockchip_tsadc_data->clk);
439
440         rockchip_tsadc_data->pclk = devm_clk_get(&data->pdev->dev, "pclk_tsadc");
441         if (IS_ERR(rockchip_tsadc_data->pclk)) {
442             dev_err(&data->pdev->dev, "failed to get tsadc pclk\n");
443             ret = PTR_ERR(rockchip_tsadc_data->pclk);
444             return -EPERM;
445         }
446         clk_prepare_enable(rockchip_tsadc_data->pclk);
447
448         platform_set_drvdata(data->pdev, rockchip_tsadc_data);
449         g_dev = rockchip_tsadc_data;
450         data->plat_data = rockchip_tsadc_data;
451
452         data->monitored_sensors = NUM_MONITORED_SENSORS;
453         data->ops.read_sensor = rockchip_tsadc_get_temp;
454         data->ops.show_name = rockchip_show_name;
455         data->ops.show_label = rockchip_show_label;
456         data->ops.is_visible = NULL;
457
458 //      rockchip_tsadc_set_auto_temp(0);
459
460         dev_info(&data->pdev->dev, "initialized\n");
461
462         return 0;
463 }
464 EXPORT_SYMBOL(rockchip_hwmon_init);
465
466 MODULE_DESCRIPTION("Driver for TSADC");
467 MODULE_AUTHOR("zhangqing, zhangqing@rock-chips.com");
468 MODULE_LICENSE("GPL");
469