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
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.
11 * When AB8500 thermal shutdown temperature is reached a hardware shutdown of
12 * the AB8500 will occur.
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>
25 #include <linux/delay.h>
26 #include <linux/slab.h>
27 #include <linux/workqueue.h>
28 #include <linux/ioport.h>
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>
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>
43 #include <linux/of_device.h>
44 #include "hwmon-rockchip.h"
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
51 #define TSADC_USER_CON 0x00
52 #define TSADC_AUTO_CON 0x04
54 #define TSADC_CTRL_CH(ch) ((ch) << 0)
55 #define TSADC_CTRL_POWER_UP (1 << 3)
56 #define TSADC_CTRL_START (1 << 4)
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)
65 #define TSADC_INT_EN 0x08
66 #define TSADC_INT_PD 0x0c
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
74 #define TSADC_COMP0_INT 0x30
75 #define TSADC_COMP1_INT 0x34
76 #define TSADC_COMP2_INT 0x38
77 #define TSADC_COMP3_INT 0x3c
79 #define TSADC_COMP0_SHUT 0x40
80 #define TSADC_COMP1_SHUT 0x44
81 #define TSADC_COMP2_SHUT 0x48
82 #define TSADC_COMP3_SHUT 0x4c
84 #define TSADC_HIGHT_INT_DEBOUNCE 0x60
85 #define TSADC_HIGHT_TSHUT_DEBOUNCE 0x64
86 #define TSADC_HIGHT_INT_DEBOUNCE_TIME 0x0a
87 #define TSADC_HIGHT_TSHUT_DEBOUNCE_TIME 0x0a
89 #define TSADC_AUTO_PERIOD 0x68
90 #define TSADC_AUTO_PERIOD_HT 0x6c
91 #define TSADC_AUTO_PERIOD_TIME 0x03e8
92 #define TSADC_AUTO_PERIOD_HT_TIME 0x64
94 #define TSADC_AUTO_EVENT_NAME "tsadc"
96 #define TSADC_COMP_INT_DATA 80
97 #define TSADC_COMP_INT_DATA_MASK 0xfff
98 #define TSADC_COMP_SHUT_DATA_MASK 0xfff
99 #define TSADC_TEMP_INT_EN 0
100 #define TSADC_TEMP_SHUT_EN 1
101 static int tsadc_ht_temp;
102 static int tsadc_ht_reset_cru;
103 static int tsadc_ht_pull_gpio;
106 struct pinctrl *pctl;
107 struct pinctrl_state *pins_default;
108 struct pinctrl_state *pins_tsadc_int;
111 struct rockchip_tsadc_temp {
112 struct delayed_work power_off_work;
113 struct rockchip_temp *rockchip_data;
118 struct resource *ioarea;
119 struct tsadc_host *tsadc;
120 struct work_struct auto_ht_irq_work;
121 struct workqueue_struct *workqueue;
122 struct workqueue_struct *tsadc_workqueue;
130 static const struct tsadc_table table[] =
132 {TSADC_DATA_MASK, -40},
175 static struct rockchip_tsadc_temp *g_dev;
177 static DEFINE_MUTEX(tsadc_mutex);
179 static u32 tsadc_readl(u32 offset)
181 return readl_relaxed(g_dev->regs + offset);
184 static void tsadc_writel(u32 val, u32 offset)
186 writel_relaxed(val, g_dev->regs + offset);
189 void rockchip_tsadc_auto_ht_work(struct work_struct *work)
193 // printk("%s,line=%d\n", __func__,__LINE__);
195 mutex_lock(&tsadc_mutex);
197 val = tsadc_readl(TSADC_INT_PD);
198 tsadc_writel(val &(~ (1 <<8) ), TSADC_INT_PD);
199 ret = tsadc_readl(TSADC_INT_PD);
200 tsadc_writel(ret | 0xff, TSADC_INT_PD); //clr irq status
201 if ((val & 0x0f) != 0){
202 printk("rockchip tsadc is over temp . %s,line=%d\n", __func__,__LINE__);
203 pm_power_off(); //power_off
205 mutex_unlock(&tsadc_mutex);
208 static irqreturn_t rockchip_tsadc_auto_ht_interrupt(int irq, void *data)
210 struct rockchip_tsadc_temp *dev = data;
212 printk("%s,line=%d\n", __func__,__LINE__);
214 queue_work(dev->workqueue, &dev->auto_ht_irq_work);
219 static void rockchip_tsadc_set_cmpn_int_vale( int chn, int temp)
224 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
225 if (temp <= table[i].temp && temp > table[i -1].temp) {
226 code = table[i].code;
229 tsadc_writel((code & TSADC_COMP_INT_DATA_MASK), (TSADC_COMP0_INT + chn*4));
233 static void rockchip_tsadc_set_cmpn_shut_vale( int chn, int temp)
238 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
239 if (temp <= table[i].temp && temp > table[i -1].temp) {
240 code = table[i].code;
244 tsadc_writel((code & TSADC_COMP_SHUT_DATA_MASK), (TSADC_COMP0_SHUT + chn*4));
247 static void rockchip_tsadc_set_auto_int_en( int chn, int ht_int_en,int tshut_en)
250 tsadc_writel(0, TSADC_INT_EN);
252 ret = tsadc_readl(TSADC_INT_EN);
253 tsadc_writel( ret | (1 << chn), TSADC_INT_EN);
256 ret = tsadc_readl(TSADC_INT_EN);
257 if (tsadc_ht_pull_gpio)
258 tsadc_writel(ret | (0xf << (chn + 4)), TSADC_INT_EN);
259 else if (tsadc_ht_reset_cru)
260 tsadc_writel(ret | (0xf << (chn + 8)), TSADC_INT_EN);
264 static void rockchip_tsadc_auto_mode_set(int chn, int int_temp,
265 int shut_temp, int int_en, int shut_en)
269 if (!g_dev || chn > 4)
272 mutex_lock(&tsadc_mutex);
274 clk_enable(g_dev->pclk);
275 clk_enable(g_dev->clk);
278 tsadc_writel(0, TSADC_AUTO_CON);
279 tsadc_writel(1 << (4+chn), TSADC_AUTO_CON);
281 if ((tsadc_readl(TSADC_AUTO_CON) & TSADC_AUTO_STAS_BUSY_MASK) != TSADC_AUTO_STAS_BUSY) {
282 rockchip_tsadc_set_cmpn_int_vale(chn,int_temp);
283 rockchip_tsadc_set_cmpn_shut_vale(chn,shut_temp),
285 tsadc_writel(TSADC_AUTO_PERIOD_TIME, TSADC_AUTO_PERIOD);
286 tsadc_writel(TSADC_AUTO_PERIOD_HT_TIME, TSADC_AUTO_PERIOD_HT);
288 tsadc_writel(TSADC_HIGHT_INT_DEBOUNCE_TIME,
289 TSADC_HIGHT_INT_DEBOUNCE);
290 tsadc_writel(TSADC_HIGHT_TSHUT_DEBOUNCE_TIME,
291 TSADC_HIGHT_TSHUT_DEBOUNCE);
293 rockchip_tsadc_set_auto_int_en(chn,int_en,shut_en);
298 ret = tsadc_readl(TSADC_AUTO_CON);
299 tsadc_writel(ret | (1 <<0) , TSADC_AUTO_CON);
301 mutex_unlock(&tsadc_mutex);
305 int rockchip_tsadc_set_auto_temp(int chn)
307 rockchip_tsadc_auto_mode_set(chn, TSADC_COMP_INT_DATA,
308 tsadc_ht_temp, TSADC_TEMP_INT_EN, TSADC_TEMP_SHUT_EN);
311 EXPORT_SYMBOL(rockchip_tsadc_set_auto_temp);
313 static void rockchip_tsadc_get(int chn, int *temp, int *code)
319 if (!g_dev || chn > 4){
324 mutex_lock(&tsadc_mutex);
326 clk_enable(g_dev->pclk);
327 clk_enable(g_dev->clk);
330 tsadc_writel(0, TSADC_USER_CON);
331 tsadc_writel(TSADC_CTRL_POWER_UP | TSADC_CTRL_CH(chn), TSADC_USER_CON);
333 if ((tsadc_readl(TSADC_USER_CON) & TSADC_STAS_BUSY_MASK) != TSADC_STAS_BUSY) {
334 *code = tsadc_readl((TSADC_DATA0 + chn*4)) & TSADC_DATA_MASK;
335 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
336 if ((*code) <= table[i].code && (*code) > table[i + 1].code) {
337 *temp = table[i].temp + (table[i + 1].temp - table[i].temp) * (table[i].code - (*code)) / (table[i].code - table[i + 1].code);
342 tsadc_writel(0, TSADC_USER_CON);
344 clk_disable(g_dev->clk);
345 clk_disable(g_dev->pclk);
347 mutex_unlock(&tsadc_mutex);
349 *code = tsadc_readl((TSADC_DATA0 + chn*4)) & TSADC_DATA_MASK;
350 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
351 if ((*code) <= table[i].code && (*code) > table[i + 1].code)
352 *temp = table[i].temp + (table[i + 1].temp
353 - table[i].temp) * (table[i].code - (*code))
354 / (table[i].code - table[i + 1].code);
359 int rockchip_tsadc_get_temp(int chn)
363 rockchip_tsadc_get(chn, &temp, &code);
367 EXPORT_SYMBOL(rockchip_tsadc_get_temp);
369 static ssize_t rockchip_show_name(struct device *dev,
370 struct device_attribute *devattr, char *buf)
372 return sprintf(buf, "rockchip-tsadc\n");
375 static ssize_t rockchip_show_label(struct device *dev,
376 struct device_attribute *devattr, char *buf)
379 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
380 int index = attr->index;
399 return sprintf(buf, "%s\n", label);
402 int rockchip_hwmon_init(struct rockchip_temp *data)
404 struct rockchip_tsadc_temp *rockchip_tsadc_data;
405 struct resource *res;
406 struct device_node *np = data->pdev->dev.of_node;
409 struct tsadc_port *uap;
411 rockchip_tsadc_data = devm_kzalloc(&data->pdev->dev, sizeof(*rockchip_tsadc_data),
413 if (!rockchip_tsadc_data)
416 res = platform_get_resource(data->pdev, IORESOURCE_MEM, 0);
417 rockchip_tsadc_data->regs = devm_request_and_ioremap(&data->pdev->dev, res);
418 if (!rockchip_tsadc_data->regs) {
419 dev_err(&data->pdev->dev, "cannot map IO\n");
424 irq = platform_get_irq(data->pdev, 0);
426 dev_err(&data->pdev->dev, "no irq resource?\n");
429 rockchip_tsadc_data->irq = irq;
430 ret = request_threaded_irq(rockchip_tsadc_data->irq, NULL, rockchip_tsadc_auto_ht_interrupt, IRQF_ONESHOT, TSADC_AUTO_EVENT_NAME, rockchip_tsadc_data);
432 dev_err(&data->pdev->dev, "failed to attach tsadc irq\n");
436 rockchip_tsadc_data->workqueue = create_singlethread_workqueue("rockchip_tsadc");
437 INIT_WORK(&rockchip_tsadc_data->auto_ht_irq_work, rockchip_tsadc_auto_ht_work);
440 rockchip_tsadc_data->clk = devm_clk_get(&data->pdev->dev, "tsadc");
441 if (IS_ERR(rockchip_tsadc_data->clk)) {
442 dev_err(&data->pdev->dev, "failed to get tsadc clock\n");
443 ret = PTR_ERR(rockchip_tsadc_data->clk);
447 if(of_property_read_u32(np, "clock-frequency", &rate)) {
448 dev_err(&data->pdev->dev, "Missing clock-frequency property in the DT.\n");
452 ret = clk_set_rate(rockchip_tsadc_data->clk, rate);
454 dev_err(&data->pdev->dev, "failed to set adc clk\n");
457 clk_prepare_enable(rockchip_tsadc_data->clk);
459 rockchip_tsadc_data->pclk = devm_clk_get(&data->pdev->dev, "pclk_tsadc");
460 if (IS_ERR(rockchip_tsadc_data->pclk)) {
461 dev_err(&data->pdev->dev, "failed to get tsadc pclk\n");
462 ret = PTR_ERR(rockchip_tsadc_data->pclk);
465 clk_prepare_enable(rockchip_tsadc_data->pclk);
467 platform_set_drvdata(data->pdev, rockchip_tsadc_data);
468 g_dev = rockchip_tsadc_data;
469 data->plat_data = rockchip_tsadc_data;
471 if (of_property_read_u32(np, "tsadc-ht-temp",
473 dev_err(&data->pdev->dev, "Missing tsadc_ht_temp in the DT.\n");
476 if (of_property_read_u32(np, "tsadc-ht-reset-cru",
477 &tsadc_ht_reset_cru)) {
478 dev_err(&data->pdev->dev, "Missing tsadc_ht_reset_cru in the DT.\n");
481 if (of_property_read_u32(np, "tsadc-ht-pull-gpio",
482 &tsadc_ht_pull_gpio)) {
483 dev_err(&data->pdev->dev, "Missing tsadc_ht_pull_gpio in the DT.\n");
487 if (tsadc_ht_pull_gpio){
488 /*bit8=1 gpio0_b2 = 1 shutdown else gpio0_b2 =1 shutdown*/
490 ret = tsadc_readl(TSADC_AUTO_CON);
491 tsadc_writel(ret | (1 << 8) , TSADC_AUTO_CON);
493 uap = devm_kzalloc(&data->pdev->dev, sizeof(struct tsadc_port),
496 dev_err(&data->pdev->dev,
497 "uap is not set %s,line=%d\n", __func__, __LINE__);
498 uap->pctl = devm_pinctrl_get(&data->pdev->dev);
499 uap->pins_default = pinctrl_lookup_state(uap->pctl, "default");
500 uap->pins_tsadc_int = pinctrl_lookup_state(uap->pctl, "tsadc_int");
501 pinctrl_select_state(uap->pctl, uap->pins_tsadc_int);
504 rockchip_tsadc_set_auto_temp(1);
506 data->monitored_sensors = NUM_MONITORED_SENSORS;
507 data->ops.read_sensor = rockchip_tsadc_get_temp;
508 data->ops.show_name = rockchip_show_name;
509 data->ops.show_label = rockchip_show_label;
510 data->ops.is_visible = NULL;
512 dev_info(&data->pdev->dev, "initialized\n");
515 EXPORT_SYMBOL(rockchip_hwmon_init);
517 MODULE_LICENSE("GPL");
518 MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
519 MODULE_DESCRIPTION("Driver for TSADC");