aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/sun4i-ts.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
index 28a06749ae42..9ae53d4289fb 100644
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -34,6 +34,7 @@
34 34
35#include <linux/err.h> 35#include <linux/err.h>
36#include <linux/hwmon.h> 36#include <linux/hwmon.h>
37#include <linux/thermal.h>
37#include <linux/init.h> 38#include <linux/init.h>
38#include <linux/input.h> 39#include <linux/input.h>
39#include <linux/interrupt.h> 40#include <linux/interrupt.h>
@@ -107,6 +108,7 @@
107struct sun4i_ts_data { 108struct sun4i_ts_data {
108 struct device *dev; 109 struct device *dev;
109 struct input_dev *input; 110 struct input_dev *input;
111 struct thermal_zone_device *tz;
110 void __iomem *base; 112 void __iomem *base;
111 unsigned int irq; 113 unsigned int irq;
112 bool ignore_fifo_data; 114 bool ignore_fifo_data;
@@ -180,16 +182,48 @@ static void sun4i_ts_close(struct input_dev *dev)
180 writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); 182 writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
181} 183}
182 184
185static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
186{
187 /* No temp_data until the first irq */
188 if (ts->temp_data == -1)
189 return -EAGAIN;
190
191 /*
192 * The user manuals do not contain the formula for calculating
193 * the temperature. The formula used here is from the AXP209,
194 * which is designed by X-Powers, an affiliate of Allwinner:
195 *
196 * temperature = -144.7 + (value * 0.1)
197 *
198 * This should be replaced with the correct one if such information
199 * becomes available.
200 */
201 *temp = (ts->temp_data - 1447) * 100;
202
203 return 0;
204}
205
206static int sun4i_get_tz_temp(void *data, long *temp)
207{
208 return sun4i_get_temp(data, temp);
209}
210
211static struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
212 .get_temp = sun4i_get_tz_temp,
213};
214
183static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 215static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
184 char *buf) 216 char *buf)
185{ 217{
186 struct sun4i_ts_data *ts = dev_get_drvdata(dev); 218 struct sun4i_ts_data *ts = dev_get_drvdata(dev);
219 long temp;
220 int error;
187 221
188 /* No temp_data until the first irq */ 222 error = sun4i_get_temp(ts, &temp);
189 if (ts->temp_data == -1) 223 if (error)
190 return -EAGAIN; 224 return error;
191 225
192 return sprintf(buf, "%d\n", (ts->temp_data - 1447) * 100); 226 return sprintf(buf, "%ld\n", temp);
193} 227}
194 228
195static ssize_t show_temp_label(struct device *dev, 229static ssize_t show_temp_label(struct device *dev,
@@ -283,17 +317,27 @@ static int sun4i_ts_probe(struct platform_device *pdev)
283 writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1), 317 writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1),
284 ts->base + TP_CTRL1); 318 ts->base + TP_CTRL1);
285 319
320 /*
321 * The thermal core does not register hwmon devices for DT-based
322 * thermal zone sensors, such as this one.
323 */
286 hwmon = devm_hwmon_device_register_with_groups(ts->dev, "sun4i_ts", 324 hwmon = devm_hwmon_device_register_with_groups(ts->dev, "sun4i_ts",
287 ts, sun4i_ts_groups); 325 ts, sun4i_ts_groups);
288 if (IS_ERR(hwmon)) 326 if (IS_ERR(hwmon))
289 return PTR_ERR(hwmon); 327 return PTR_ERR(hwmon);
290 328
329 ts->tz = thermal_zone_of_sensor_register(ts->dev, 0, ts,
330 &sun4i_ts_tz_ops);
331 if (IS_ERR(ts->tz))
332 ts->tz = NULL;
333
291 writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); 334 writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
292 335
293 if (ts_attached) { 336 if (ts_attached) {
294 error = input_register_device(ts->input); 337 error = input_register_device(ts->input);
295 if (error) { 338 if (error) {
296 writel(0, ts->base + TP_INT_FIFOC); 339 writel(0, ts->base + TP_INT_FIFOC);
340 thermal_zone_of_sensor_unregister(ts->dev, ts->tz);
297 return error; 341 return error;
298 } 342 }
299 } 343 }
@@ -310,6 +354,8 @@ static int sun4i_ts_remove(struct platform_device *pdev)
310 if (ts->input) 354 if (ts->input)
311 input_unregister_device(ts->input); 355 input_unregister_device(ts->input);
312 356
357 thermal_zone_of_sensor_unregister(ts->dev, ts->tz);
358
313 /* Deactivate all IRQs */ 359 /* Deactivate all IRQs */
314 writel(0, ts->base + TP_INT_FIFOC); 360 writel(0, ts->base + TP_INT_FIFOC);
315 361