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, kernel_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/reboot.h>
25 #include <linux/slab.h>
26 #include <linux/sysfs.h>
29 #define DEFAULT_POWER_OFF_DELAY (HZ * 10)
30 #define THERMAL_VCC 1800
31 #define PULL_UP_RESISTOR 47000
32 /* Number of monitored sensors should not greater than NUM_SENSORS */
33 #define NUM_MONITORED_SENSORS 4
35 struct ab8500_gpadc_cfg
{
36 const struct abx500_res_to_temp
*temp_tbl
;
43 struct ab8500_gpadc
*gpadc
;
44 struct ab8500_btemp
*btemp
;
45 struct delayed_work power_off_work
;
46 struct ab8500_gpadc_cfg cfg
;
47 struct abx500_temp
*abx500_data
;
51 * The hardware connection is like this:
52 * VCC----[ R_up ]-----[ NTC ]----GND
53 * where R_up is pull-up resistance, and GPADC measures voltage on NTC.
54 * and res_to_temp table is strictly sorted by falling resistance values.
56 static int ab8500_voltage_to_temp(struct ab8500_gpadc_cfg
*cfg
,
59 int r_ntc
, i
= 0, tbl_sz
= cfg
->tbl_sz
;
60 const struct abx500_res_to_temp
*tbl
= cfg
->temp_tbl
;
62 if (cfg
->vcc
< 0 || v_ntc
>= cfg
->vcc
)
65 r_ntc
= v_ntc
* cfg
->r_up
/ (cfg
->vcc
- v_ntc
);
66 if (r_ntc
> tbl
[0].resist
|| r_ntc
< tbl
[tbl_sz
- 1].resist
)
69 while (!(r_ntc
<= tbl
[i
].resist
&& r_ntc
> tbl
[i
+ 1].resist
) &&
73 /* return milli-Celsius */
74 *temp
= tbl
[i
].temp
* 1000 + ((tbl
[i
+ 1].temp
- tbl
[i
].temp
) * 1000 *
75 (r_ntc
- tbl
[i
].resist
)) / (tbl
[i
+ 1].resist
- tbl
[i
].resist
);
80 static int ab8500_read_sensor(struct abx500_temp
*data
, u8 sensor
, int *temp
)
83 struct ab8500_temp
*ab8500_data
= data
->plat_data
;
85 if (sensor
== BAT_CTRL
) {
86 *temp
= ab8500_btemp_get_batctrl_temp(ab8500_data
->btemp
);
87 } else if (sensor
== BTEMP_BALL
) {
88 *temp
= ab8500_btemp_get_temp(ab8500_data
->btemp
);
90 voltage
= ab8500_gpadc_convert(ab8500_data
->gpadc
, sensor
);
94 ret
= ab8500_voltage_to_temp(&ab8500_data
->cfg
, voltage
, temp
);
102 static void ab8500_thermal_power_off(struct work_struct
*work
)
104 struct ab8500_temp
*ab8500_data
= container_of(work
,
105 struct ab8500_temp
, power_off_work
.work
);
106 struct abx500_temp
*abx500_data
= ab8500_data
->abx500_data
;
108 dev_warn(&abx500_data
->pdev
->dev
, "Power off due to critical temp\n");
113 static ssize_t
ab8500_show_name(struct device
*dev
,
114 struct device_attribute
*devattr
, char *buf
)
116 return sprintf(buf
, "ab8500\n");
119 static ssize_t
ab8500_show_label(struct device
*dev
,
120 struct device_attribute
*devattr
, char *buf
)
123 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
124 int index
= attr
->index
;
143 return sprintf(buf
, "%s\n", label
);
146 static int ab8500_temp_irq_handler(int irq
, struct abx500_temp
*data
)
148 struct ab8500_temp
*ab8500_data
= data
->plat_data
;
150 dev_warn(&data
->pdev
->dev
, "Power off in %d s\n",
151 DEFAULT_POWER_OFF_DELAY
/ HZ
);
153 schedule_delayed_work(&ab8500_data
->power_off_work
,
154 DEFAULT_POWER_OFF_DELAY
);
158 int abx500_hwmon_init(struct abx500_temp
*data
)
160 struct ab8500_temp
*ab8500_data
;
162 ab8500_data
= devm_kzalloc(&data
->pdev
->dev
, sizeof(*ab8500_data
),
167 ab8500_data
->gpadc
= ab8500_gpadc_get("ab8500-gpadc.0");
168 if (IS_ERR(ab8500_data
->gpadc
))
169 return PTR_ERR(ab8500_data
->gpadc
);
171 ab8500_data
->btemp
= ab8500_btemp_get();
172 if (IS_ERR(ab8500_data
->btemp
))
173 return PTR_ERR(ab8500_data
->btemp
);
175 INIT_DELAYED_WORK(&ab8500_data
->power_off_work
,
176 ab8500_thermal_power_off
);
178 ab8500_data
->cfg
.vcc
= THERMAL_VCC
;
179 ab8500_data
->cfg
.r_up
= PULL_UP_RESISTOR
;
180 ab8500_data
->cfg
.temp_tbl
= ab8500_temp_tbl_a_thermistor
;
181 ab8500_data
->cfg
.tbl_sz
= ab8500_temp_tbl_a_size
;
183 data
->plat_data
= ab8500_data
;
186 * ADC_AUX1 and ADC_AUX2, connected to external NTC
187 * BTEMP_BALL and BAT_CTRL, fixed usage
189 data
->gpadc_addr
[0] = ADC_AUX1
;
190 data
->gpadc_addr
[1] = ADC_AUX2
;
191 data
->gpadc_addr
[2] = BTEMP_BALL
;
192 data
->gpadc_addr
[3] = BAT_CTRL
;
193 data
->monitored_sensors
= NUM_MONITORED_SENSORS
;
195 data
->ops
.read_sensor
= ab8500_read_sensor
;
196 data
->ops
.irq_handler
= ab8500_temp_irq_handler
;
197 data
->ops
.show_name
= ab8500_show_name
;
198 data
->ops
.show_label
= ab8500_show_label
;
199 data
->ops
.is_visible
= NULL
;
203 EXPORT_SYMBOL(abx500_hwmon_init
);
205 MODULE_AUTHOR("Hongbo Zhang <hongbo.zhang@linaro.org>");
206 MODULE_DESCRIPTION("AB8500 temperature driver");
207 MODULE_LICENSE("GPL");