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 <linux/rockchip/common.h>
45 #include "hwmon-rockchip.h"
48 #define DEFAULT_POWER_OFF_DELAY (HZ * 10)
49 /* Number of monitored sensors should not greater than NUM_SENSORS */
50 #define NUM_MONITORED_SENSORS 4
52 #define TSADC_USER_CON 0x00
53 #define TSADC_AUTO_CON 0x04
55 #define TSADC_CTRL_CH(ch) ((ch) << 0)
56 #define TSADC_CTRL_POWER_UP (1 << 3)
57 #define TSADC_CTRL_START (1 << 4)
59 #define TSADC_STAS_BUSY (1 << 12)
60 #define TSADC_STAS_BUSY_MASK (1 << 12)
61 #define TSADC_AUTO_STAS_BUSY (1 << 16)
62 #define TSADC_AUTO_STAS_BUSY_MASK (1 << 16)
63 #define TSADC_SAMPLE_DLY_SEL (1 << 17)
64 #define TSADC_SAMPLE_DLY_SEL_MASK (1 << 17)
66 #define TSADC_INT_EN 0x08
67 #define TSADC_INT_PD 0x0c
69 #define TSADC_DATA0 0x20
70 #define TSADC_DATA1 0x24
71 #define TSADC_DATA2 0x28
72 #define TSADC_DATA3 0x2c
73 #define TSADC_DATA_MASK 0xfff
75 #define TSADC_COMP0_INT 0x30
76 #define TSADC_COMP1_INT 0x34
77 #define TSADC_COMP2_INT 0x38
78 #define TSADC_COMP3_INT 0x3c
80 #define TSADC_COMP0_SHUT 0x40
81 #define TSADC_COMP1_SHUT 0x44
82 #define TSADC_COMP2_SHUT 0x48
83 #define TSADC_COMP3_SHUT 0x4c
85 #define TSADC_HIGHT_INT_DEBOUNCE 0x60
86 #define TSADC_HIGHT_TSHUT_DEBOUNCE 0x64
87 #define TSADC_HIGHT_INT_DEBOUNCE_TIME 0x0a
88 #define TSADC_HIGHT_TSHUT_DEBOUNCE_TIME 0x0a
90 #define TSADC_AUTO_PERIOD 0x68
91 #define TSADC_AUTO_PERIOD_HT 0x6c
92 #define TSADC_AUTO_PERIOD_TIME 0x03e8
93 #define TSADC_AUTO_PERIOD_HT_TIME 0x64
95 #define TSADC_AUTO_EVENT_NAME "tsadc"
97 #define TSADC_COMP_INT_DATA 80
98 #define TSADC_COMP_INT_DATA_MASK 0xfff
99 #define TSADC_COMP_SHUT_DATA_MASK 0xfff
100 #define TSADC_TEMP_INT_EN 0
101 #define TSADC_TEMP_SHUT_EN 1
102 static int tsadc_ht_temp;
103 static int tsadc_ht_reset_cru;
104 static int tsadc_ht_pull_gpio;
107 struct pinctrl *pctl;
108 struct pinctrl_state *pins_default;
109 struct pinctrl_state *pins_tsadc_int;
112 struct rockchip_tsadc_temp {
113 struct delayed_work power_off_work;
114 struct rockchip_temp *rockchip_data;
119 struct resource *ioarea;
120 struct tsadc_host *tsadc;
121 struct work_struct auto_ht_irq_work;
122 struct workqueue_struct *workqueue;
123 struct workqueue_struct *tsadc_workqueue;
131 static const struct tsadc_table table[] =
133 {TSADC_DATA_MASK, -40},
176 static struct rockchip_tsadc_temp *g_dev;
178 static DEFINE_MUTEX(tsadc_mutex);
180 static u32 tsadc_readl(u32 offset)
182 return readl_relaxed(g_dev->regs + offset);
185 static void tsadc_writel(u32 val, u32 offset)
187 writel_relaxed(val, g_dev->regs + offset);
190 void rockchip_tsadc_auto_ht_work(struct work_struct *work)
194 // printk("%s,line=%d\n", __func__,__LINE__);
196 mutex_lock(&tsadc_mutex);
198 val = tsadc_readl(TSADC_INT_PD);
199 tsadc_writel(val &(~ (1 <<8) ), TSADC_INT_PD);
200 ret = tsadc_readl(TSADC_INT_PD);
201 tsadc_writel(ret | 0xff, TSADC_INT_PD); //clr irq status
202 if ((val & 0x0f) != 0){
203 printk("rockchip tsadc is over temp . %s,line=%d\n", __func__,__LINE__);
204 pm_power_off(); //power_off
206 mutex_unlock(&tsadc_mutex);
209 static irqreturn_t rockchip_tsadc_auto_ht_interrupt(int irq, void *data)
211 struct rockchip_tsadc_temp *dev = data;
213 printk("%s,line=%d\n", __func__,__LINE__);
215 queue_work(dev->workqueue, &dev->auto_ht_irq_work);
220 static void rockchip_tsadc_set_cmpn_int_vale( int chn, int temp)
225 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
226 if (temp <= table[i].temp && temp > table[i -1].temp) {
227 code = table[i].code;
230 tsadc_writel((code & TSADC_COMP_INT_DATA_MASK), (TSADC_COMP0_INT + chn*4));
234 static void rockchip_tsadc_set_cmpn_shut_vale( int chn, int temp)
239 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
240 if (temp <= table[i].temp && temp > table[i -1].temp) {
241 code = table[i].code;
245 tsadc_writel((code & TSADC_COMP_SHUT_DATA_MASK), (TSADC_COMP0_SHUT + chn*4));
248 static void rockchip_tsadc_set_auto_int_en( int chn, int ht_int_en,int tshut_en)
251 tsadc_writel(0, TSADC_INT_EN);
253 ret = tsadc_readl(TSADC_INT_EN);
254 tsadc_writel( ret | (1 << chn), TSADC_INT_EN);
257 ret = tsadc_readl(TSADC_INT_EN);
258 if (tsadc_ht_pull_gpio)
259 tsadc_writel(ret | (0xf << (chn + 4)), TSADC_INT_EN);
260 else if (tsadc_ht_reset_cru)
261 tsadc_writel(ret | (0xf << (chn + 8)), TSADC_INT_EN);
265 static void rockchip_tsadc_auto_mode_set(int chn, int int_temp,
266 int shut_temp, int int_en, int shut_en)
270 if (!g_dev || chn > 4)
273 mutex_lock(&tsadc_mutex);
275 clk_enable(g_dev->pclk);
276 clk_enable(g_dev->clk);
279 tsadc_writel(0, TSADC_AUTO_CON);
280 tsadc_writel(3 << (4+chn), TSADC_AUTO_CON);
282 if ((tsadc_readl(TSADC_AUTO_CON) & TSADC_AUTO_STAS_BUSY_MASK) != TSADC_AUTO_STAS_BUSY) {
283 rockchip_tsadc_set_cmpn_int_vale(chn,int_temp);
284 rockchip_tsadc_set_cmpn_shut_vale(chn,shut_temp),
286 tsadc_writel(TSADC_AUTO_PERIOD_TIME, TSADC_AUTO_PERIOD);
287 tsadc_writel(TSADC_AUTO_PERIOD_HT_TIME, TSADC_AUTO_PERIOD_HT);
289 tsadc_writel(TSADC_HIGHT_INT_DEBOUNCE_TIME,
290 TSADC_HIGHT_INT_DEBOUNCE);
291 tsadc_writel(TSADC_HIGHT_TSHUT_DEBOUNCE_TIME,
292 TSADC_HIGHT_TSHUT_DEBOUNCE);
294 rockchip_tsadc_set_auto_int_en(chn,int_en,shut_en);
299 ret = tsadc_readl(TSADC_AUTO_CON);
300 tsadc_writel(ret | (1 <<0) , TSADC_AUTO_CON);
302 mutex_unlock(&tsadc_mutex);
306 int rockchip_tsadc_set_auto_temp(int chn)
308 rockchip_tsadc_auto_mode_set(chn, TSADC_COMP_INT_DATA,
309 tsadc_ht_temp, TSADC_TEMP_INT_EN, TSADC_TEMP_SHUT_EN);
312 EXPORT_SYMBOL(rockchip_tsadc_set_auto_temp);
314 static void rockchip_tsadc_get(int chn, int *temp, int *code)
320 if (!g_dev || chn > 4){
321 *temp = INVALID_TEMP;
325 mutex_lock(&tsadc_mutex);
327 clk_enable(g_dev->pclk);
328 clk_enable(g_dev->clk);
331 tsadc_writel(0, TSADC_USER_CON);
332 tsadc_writel(TSADC_CTRL_POWER_UP | TSADC_CTRL_CH(chn), TSADC_USER_CON);
334 if ((tsadc_readl(TSADC_USER_CON) & TSADC_STAS_BUSY_MASK) != TSADC_STAS_BUSY) {
335 *code = tsadc_readl((TSADC_DATA0 + chn*4)) & TSADC_DATA_MASK;
336 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
337 if ((*code) <= table[i].code && (*code) > table[i + 1].code) {
338 *temp = table[i].temp + (table[i + 1].temp - table[i].temp) * (table[i].code - (*code)) / (table[i].code - table[i + 1].code);
343 tsadc_writel(0, TSADC_USER_CON);
345 clk_disable(g_dev->clk);
346 clk_disable(g_dev->pclk);
348 mutex_unlock(&tsadc_mutex);
350 *code = tsadc_readl((TSADC_DATA0 + chn*4)) & TSADC_DATA_MASK;
351 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
352 if ((*code) <= table[i].code && (*code) > table[i + 1].code)
353 *temp = table[i].temp + (table[i + 1].temp
354 - table[i].temp) * (table[i].code - (*code))
355 / (table[i].code - table[i + 1].code);
360 int rockchip_tsadc_get_temp(int chn)
364 rockchip_tsadc_get(chn, &temp, &code);
368 EXPORT_SYMBOL(rockchip_tsadc_get_temp);
370 static ssize_t rockchip_show_name(struct device *dev,
371 struct device_attribute *devattr, char *buf)
373 return sprintf(buf, "rockchip-tsadc\n");
376 static ssize_t rockchip_show_label(struct device *dev,
377 struct device_attribute *devattr, char *buf)
380 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
381 int index = attr->index;
400 return sprintf(buf, "%s\n", label);
403 int rockchip_hwmon_init(struct rockchip_temp *data)
405 struct rockchip_tsadc_temp *rockchip_tsadc_data;
406 struct resource *res;
407 struct device_node *np = data->pdev->dev.of_node;
410 struct tsadc_port *uap;
412 rockchip_tsadc_data = devm_kzalloc(&data->pdev->dev, sizeof(*rockchip_tsadc_data),
414 if (!rockchip_tsadc_data)
417 res = platform_get_resource(data->pdev, IORESOURCE_MEM, 0);
418 rockchip_tsadc_data->regs = devm_request_and_ioremap(&data->pdev->dev, res);
419 if (!rockchip_tsadc_data->regs) {
420 dev_err(&data->pdev->dev, "cannot map IO\n");
425 irq = platform_get_irq(data->pdev, 0);
427 dev_err(&data->pdev->dev, "no irq resource?\n");
430 rockchip_tsadc_data->irq = irq;
431 ret = request_threaded_irq(rockchip_tsadc_data->irq, NULL, rockchip_tsadc_auto_ht_interrupt, IRQF_ONESHOT, TSADC_AUTO_EVENT_NAME, rockchip_tsadc_data);
433 dev_err(&data->pdev->dev, "failed to attach tsadc irq\n");
437 rockchip_tsadc_data->workqueue = create_singlethread_workqueue("rockchip_tsadc");
438 INIT_WORK(&rockchip_tsadc_data->auto_ht_irq_work, rockchip_tsadc_auto_ht_work);
441 rockchip_tsadc_data->clk = devm_clk_get(&data->pdev->dev, "tsadc");
442 if (IS_ERR(rockchip_tsadc_data->clk)) {
443 dev_err(&data->pdev->dev, "failed to get tsadc clock\n");
444 ret = PTR_ERR(rockchip_tsadc_data->clk);
448 if(of_property_read_u32(np, "clock-frequency", &rate)) {
449 dev_err(&data->pdev->dev, "Missing clock-frequency property in the DT.\n");
453 ret = clk_set_rate(rockchip_tsadc_data->clk, rate);
455 dev_err(&data->pdev->dev, "failed to set adc clk\n");
458 clk_prepare_enable(rockchip_tsadc_data->clk);
460 rockchip_tsadc_data->pclk = devm_clk_get(&data->pdev->dev, "pclk_tsadc");
461 if (IS_ERR(rockchip_tsadc_data->pclk)) {
462 dev_err(&data->pdev->dev, "failed to get tsadc pclk\n");
463 ret = PTR_ERR(rockchip_tsadc_data->pclk);
466 clk_prepare_enable(rockchip_tsadc_data->pclk);
468 platform_set_drvdata(data->pdev, rockchip_tsadc_data);
469 g_dev = rockchip_tsadc_data;
470 data->plat_data = rockchip_tsadc_data;
472 if (of_property_read_u32(np, "tsadc-ht-temp",
474 dev_err(&data->pdev->dev, "Missing tsadc_ht_temp in the DT.\n");
477 if (of_property_read_u32(np, "tsadc-ht-reset-cru",
478 &tsadc_ht_reset_cru)) {
479 dev_err(&data->pdev->dev, "Missing tsadc_ht_reset_cru in the DT.\n");
482 if (of_property_read_u32(np, "tsadc-ht-pull-gpio",
483 &tsadc_ht_pull_gpio)) {
484 dev_err(&data->pdev->dev, "Missing tsadc_ht_pull_gpio in the DT.\n");
488 if (tsadc_ht_pull_gpio){
489 /*bit8=1 gpio0_b2 = 1 shutdown else gpio0_b2 =1 shutdown*/
491 ret = tsadc_readl(TSADC_AUTO_CON);
492 tsadc_writel(ret | (1 << 8) , TSADC_AUTO_CON);
494 uap = devm_kzalloc(&data->pdev->dev, sizeof(struct tsadc_port),
497 dev_err(&data->pdev->dev,
498 "uap is not set %s,line=%d\n", __func__, __LINE__);
499 uap->pctl = devm_pinctrl_get(&data->pdev->dev);
500 uap->pins_default = pinctrl_lookup_state(uap->pctl, "default");
501 uap->pins_tsadc_int = pinctrl_lookup_state(uap->pctl, "tsadc_int");
502 pinctrl_select_state(uap->pctl, uap->pins_tsadc_int);
505 rockchip_tsadc_set_auto_temp(1);
507 data->monitored_sensors = NUM_MONITORED_SENSORS;
508 data->ops.read_sensor = rockchip_tsadc_get_temp;
509 data->ops.show_name = rockchip_show_name;
510 data->ops.show_label = rockchip_show_label;
511 data->ops.is_visible = NULL;
513 dev_info(&data->pdev->dev, "initialized\n");
516 EXPORT_SYMBOL(rockchip_hwmon_init);
518 MODULE_LICENSE("GPL");
519 MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
520 MODULE_DESCRIPTION("Driver for TSADC");