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/err.h>
16 #include <linux/hwmon.h>
17 #include <linux/hwmon-sysfs.h>
18 #include <linux/mfd/abx500.h>
19 #include <linux/mfd/abx500/ab8500-bm.h>
20 #include <linux/mfd/abx500/ab8500-gpadc.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/power/ab8500.h>
24 #include <linux/slab.h>
25 #include <linux/sysfs.h>
28 #define DEFAULT_POWER_OFF_DELAY (HZ * 10)
29 #define THERMAL_VCC 1800
30 #define PULL_UP_RESISTOR 47000
31 /* Number of monitored sensors should not greater than NUM_SENSORS */
32 #define NUM_MONITORED_SENSORS 4
34 struct ab8500_gpadc_cfg
{
35 const struct abx500_res_to_temp
*temp_tbl
;
42 struct ab8500_gpadc
*gpadc
;
43 struct ab8500_btemp
*btemp
;
44 struct delayed_work power_off_work
;
45 struct ab8500_gpadc_cfg cfg
;
46 struct abx500_temp
*abx500_data
;
50 * The hardware connection is like this:
51 * VCC----[ R_up ]-----[ NTC ]----GND
52 * where R_up is pull-up resistance, and GPADC measures voltage on NTC.
53 * and res_to_temp table is strictly sorted by falling resistance values.
55 static int ab8500_voltage_to_temp(struct ab8500_gpadc_cfg
*cfg
,
58 int r_ntc
, i
= 0, tbl_sz
= cfg
->tbl_sz
;
59 const struct abx500_res_to_temp
*tbl
= cfg
->temp_tbl
;
61 if (cfg
->vcc
< 0 || v_ntc
>= cfg
->vcc
)
64 r_ntc
= v_ntc
* cfg
->r_up
/ (cfg
->vcc
- v_ntc
);
65 if (r_ntc
> tbl
[0].resist
|| r_ntc
< tbl
[tbl_sz
- 1].resist
)
68 while (!(r_ntc
<= tbl
[i
].resist
&& r_ntc
> tbl
[i
+ 1].resist
) &&
72 /* return milli-Celsius */
73 *temp
= tbl
[i
].temp
* 1000 + ((tbl
[i
+ 1].temp
- tbl
[i
].temp
) * 1000 *
74 (r_ntc
- tbl
[i
].resist
)) / (tbl
[i
+ 1].resist
- tbl
[i
].resist
);
79 static int ab8500_read_sensor(struct abx500_temp
*data
, u8 sensor
, int *temp
)
82 struct ab8500_temp
*ab8500_data
= data
->plat_data
;
84 if (sensor
== BAT_CTRL
) {
85 *temp
= ab8500_btemp_get_batctrl_temp(ab8500_data
->btemp
);
86 } else if (sensor
== BTEMP_BALL
) {
87 *temp
= ab8500_btemp_get_temp(ab8500_data
->btemp
);
89 voltage
= ab8500_gpadc_convert(ab8500_data
->gpadc
, sensor
);
93 ret
= ab8500_voltage_to_temp(&ab8500_data
->cfg
, voltage
, temp
);
101 static void ab8500_thermal_power_off(struct work_struct
*work
)
103 struct ab8500_temp
*ab8500_data
= container_of(work
,
104 struct ab8500_temp
, power_off_work
.work
);
105 struct abx500_temp
*abx500_data
= ab8500_data
->abx500_data
;
107 dev_warn(&abx500_data
->pdev
->dev
, "Power off due to critical temp\n");
112 static ssize_t
ab8500_show_name(struct device
*dev
,
113 struct device_attribute
*devattr
, char *buf
)
115 return sprintf(buf
, "ab8500\n");
118 static ssize_t
ab8500_show_label(struct device
*dev
,
119 struct device_attribute
*devattr
, char *buf
)
122 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
123 int index
= attr
->index
;
142 return sprintf(buf
, "%s\n", label
);
145 static int ab8500_temp_irq_handler(int irq
, struct abx500_temp
*data
)
147 struct ab8500_temp
*ab8500_data
= data
->plat_data
;
149 dev_warn(&data
->pdev
->dev
, "Power off in %d s\n",
150 DEFAULT_POWER_OFF_DELAY
/ HZ
);
152 schedule_delayed_work(&ab8500_data
->power_off_work
,
153 DEFAULT_POWER_OFF_DELAY
);
157 int abx500_hwmon_init(struct abx500_temp
*data
)
159 struct ab8500_temp
*ab8500_data
;
161 ab8500_data
= devm_kzalloc(&data
->pdev
->dev
, sizeof(*ab8500_data
),
166 ab8500_data
->gpadc
= ab8500_gpadc_get("ab8500-gpadc.0");
167 if (IS_ERR(ab8500_data
->gpadc
))
168 return PTR_ERR(ab8500_data
->gpadc
);
170 ab8500_data
->btemp
= ab8500_btemp_get();
171 if (IS_ERR(ab8500_data
->btemp
))
172 return PTR_ERR(ab8500_data
->btemp
);
174 INIT_DELAYED_WORK(&ab8500_data
->power_off_work
,
175 ab8500_thermal_power_off
);
177 ab8500_data
->cfg
.vcc
= THERMAL_VCC
;
178 ab8500_data
->cfg
.r_up
= PULL_UP_RESISTOR
;
179 ab8500_data
->cfg
.temp_tbl
= ab8500_temp_tbl_a_thermistor
;
180 ab8500_data
->cfg
.tbl_sz
= ab8500_temp_tbl_a_size
;
182 data
->plat_data
= ab8500_data
;
185 * ADC_AUX1 and ADC_AUX2, connected to external NTC
186 * BTEMP_BALL and BAT_CTRL, fixed usage
188 data
->gpadc_addr
[0] = ADC_AUX1
;
189 data
->gpadc_addr
[1] = ADC_AUX2
;
190 data
->gpadc_addr
[2] = BTEMP_BALL
;
191 data
->gpadc_addr
[3] = BAT_CTRL
;
192 data
->monitored_sensors
= NUM_MONITORED_SENSORS
;
194 data
->ops
.read_sensor
= ab8500_read_sensor
;
195 data
->ops
.irq_handler
= ab8500_temp_irq_handler
;
196 data
->ops
.show_name
= ab8500_show_name
;
197 data
->ops
.show_label
= ab8500_show_label
;
198 data
->ops
.is_visible
= NULL
;
202 EXPORT_SYMBOL(abx500_hwmon_init
);
204 MODULE_AUTHOR("Hongbo Zhang <hongbo.zhang@linaro.org>");
205 MODULE_DESCRIPTION("AB8500 temperature driver");
206 MODULE_LICENSE("GPL");