aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/abx500.c
diff options
context:
space:
mode:
authorHongbo Zhang <hongbo.zhang@linaro.org>2013-04-03 08:18:12 -0400
committerAnton Vorontsov <anton@enomsg.org>2013-04-16 21:27:52 -0400
commit0bbb06ed564d211d10eae12bdb423fce6178468f (patch)
tree5150a86a4ffe8cc225fb76f9a3b3cd04d730407c /drivers/hwmon/abx500.c
parentea2be6f21071b4af3b765a0f228be2bef08515e9 (diff)
hwmon: Add ST-Ericsson ABX500 hwmon driver
Each of ST-Ericsson X500 chip set series consists of both ABX500 and DBX500 chips. This is ABX500 hwmon driver, where the abx500.c is a common layer for all ABX500s, and the ab8500.c is specific for AB8500 chip. Under this designed structure, other chip specific files can be added simply using the same common layer abx500.c. Signed-off-by: Hongbo Zhang <hongbo.zhang@linaro.org> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Acked-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Anton Vorontsov <anton@enomsg.org>
Diffstat (limited to 'drivers/hwmon/abx500.c')
-rw-r--r--drivers/hwmon/abx500.c491
1 files changed, 491 insertions, 0 deletions
diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c
new file mode 100644
index 000000000000..b4ad87b31a37
--- /dev/null
+++ b/drivers/hwmon/abx500.c
@@ -0,0 +1,491 @@
1/*
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
6 *
7 * ABX500 does not provide auto ADC, so to monitor the required temperatures,
8 * a periodic work is used. It is more important to not wake up the CPU than
9 * to perform this job, hence the use of a deferred delay.
10 *
11 * A deferred delay for thermal monitor is considered safe because:
12 * If the chip gets too hot during a sleep state it's most likely due to
13 * external factors, such as the surrounding temperature. I.e. no SW decisions
14 * will make any difference.
15 */
16
17#include <linux/err.h>
18#include <linux/hwmon.h>
19#include <linux/hwmon-sysfs.h>
20#include <linux/interrupt.h>
21#include <linux/jiffies.h>
22#include <linux/module.h>
23#include <linux/mutex.h>
24#include <linux/of.h>
25#include <linux/platform_device.h>
26#include <linux/pm.h>
27#include <linux/slab.h>
28#include <linux/sysfs.h>
29#include <linux/workqueue.h>
30#include "abx500.h"
31
32#define DEFAULT_MONITOR_DELAY HZ
33#define DEFAULT_MAX_TEMP 130
34
35static inline void schedule_monitor(struct abx500_temp *data)
36{
37 data->work_active = true;
38 schedule_delayed_work(&data->work, DEFAULT_MONITOR_DELAY);
39}
40
41static void threshold_updated(struct abx500_temp *data)
42{
43 int i;
44 for (i = 0; i < data->monitored_sensors; i++)
45 if (data->max[i] != 0 || data->min[i] != 0) {
46 schedule_monitor(data);
47 return;
48 }
49
50 dev_dbg(&data->pdev->dev, "No active thresholds.\n");
51 cancel_delayed_work_sync(&data->work);
52 data->work_active = false;
53}
54
55static void gpadc_monitor(struct work_struct *work)
56{
57 int temp, i, ret;
58 char alarm_node[30];
59 bool updated_min_alarm, updated_max_alarm;
60 struct abx500_temp *data;
61
62 data = container_of(work, struct abx500_temp, work.work);
63 mutex_lock(&data->lock);
64
65 for (i = 0; i < data->monitored_sensors; i++) {
66 /* Thresholds are considered inactive if set to 0 */
67 if (data->max[i] == 0 && data->min[i] == 0)
68 continue;
69
70 if (data->max[i] < data->min[i])
71 continue;
72
73 ret = data->ops.read_sensor(data, data->gpadc_addr[i], &temp);
74 if (ret < 0) {
75 dev_err(&data->pdev->dev, "GPADC read failed\n");
76 continue;
77 }
78
79 updated_min_alarm = false;
80 updated_max_alarm = false;
81
82 if (data->min[i] != 0) {
83 if (temp < data->min[i]) {
84 if (data->min_alarm[i] == false) {
85 data->min_alarm[i] = true;
86 updated_min_alarm = true;
87 }
88 } else {
89 if (data->min_alarm[i] == true) {
90 data->min_alarm[i] = false;
91 updated_min_alarm = true;
92 }
93 }
94 }
95 if (data->max[i] != 0) {
96 if (temp > data->max[i]) {
97 if (data->max_alarm[i] == false) {
98 data->max_alarm[i] = true;
99 updated_max_alarm = true;
100 }
101 } else if (temp < data->max[i] - data->max_hyst[i]) {
102 if (data->max_alarm[i] == true) {
103 data->max_alarm[i] = false;
104 updated_max_alarm = true;
105 }
106 }
107 }
108
109 if (updated_min_alarm) {
110 ret = sprintf(alarm_node, "temp%d_min_alarm", i + 1);
111 sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node);
112 }
113 if (updated_max_alarm) {
114 ret = sprintf(alarm_node, "temp%d_max_alarm", i + 1);
115 sysfs_notify(&data->pdev->dev.kobj, NULL, alarm_node);
116 }
117 }
118
119 schedule_monitor(data);
120 mutex_unlock(&data->lock);
121}
122
123/* HWMON sysfs interfaces */
124static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
125 char *buf)
126{
127 struct abx500_temp *data = dev_get_drvdata(dev);
128 /* Show chip name */
129 return data->ops.show_name(dev, devattr, buf);
130}
131
132static ssize_t show_label(struct device *dev,
133 struct device_attribute *devattr, char *buf)
134{
135 struct abx500_temp *data = dev_get_drvdata(dev);
136 /* Show each sensor label */
137 return data->ops.show_label(dev, devattr, buf);
138}
139
140static ssize_t show_input(struct device *dev,
141 struct device_attribute *devattr, char *buf)
142{
143 int ret, temp;
144 struct abx500_temp *data = dev_get_drvdata(dev);
145 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
146 u8 gpadc_addr = data->gpadc_addr[attr->index];
147
148 ret = data->ops.read_sensor(data, gpadc_addr, &temp);
149 if (ret < 0)
150 return ret;
151
152 return sprintf(buf, "%d\n", temp);
153}
154
155/* Set functions (RW nodes) */
156static ssize_t set_min(struct device *dev, struct device_attribute *devattr,
157 const char *buf, size_t count)
158{
159 unsigned long val;
160 struct abx500_temp *data = dev_get_drvdata(dev);
161 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
162 int res = kstrtol(buf, 10, &val);
163 if (res < 0)
164 return res;
165
166 val = clamp_val(val, 0, DEFAULT_MAX_TEMP);
167
168 mutex_lock(&data->lock);
169 data->min[attr->index] = val;
170 threshold_updated(data);
171 mutex_unlock(&data->lock);
172
173 return count;
174}
175
176static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
177 const char *buf, size_t count)
178{
179 unsigned long val;
180 struct abx500_temp *data = dev_get_drvdata(dev);
181 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
182 int res = kstrtol(buf, 10, &val);
183 if (res < 0)
184 return res;
185
186 val = clamp_val(val, 0, DEFAULT_MAX_TEMP);
187
188 mutex_lock(&data->lock);
189 data->max[attr->index] = val;
190 threshold_updated(data);
191 mutex_unlock(&data->lock);
192
193 return count;
194}
195
196static ssize_t set_max_hyst(struct device *dev,
197 struct device_attribute *devattr,
198 const char *buf, size_t count)
199{
200 unsigned long val;
201 struct abx500_temp *data = dev_get_drvdata(dev);
202 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
203 int res = kstrtoul(buf, 10, &val);
204 if (res < 0)
205 return res;
206
207 val = clamp_val(val, 0, DEFAULT_MAX_TEMP);
208
209 mutex_lock(&data->lock);
210 data->max_hyst[attr->index] = val;
211 threshold_updated(data);
212 mutex_unlock(&data->lock);
213
214 return count;
215}
216
217/* Show functions (RO nodes) */
218static ssize_t show_min(struct device *dev,
219 struct device_attribute *devattr, char *buf)
220{
221 struct abx500_temp *data = dev_get_drvdata(dev);
222 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
223
224 return sprintf(buf, "%ld\n", data->min[attr->index]);
225}
226
227static ssize_t show_max(struct device *dev,
228 struct device_attribute *devattr, char *buf)
229{
230 struct abx500_temp *data = dev_get_drvdata(dev);
231 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
232
233 return sprintf(buf, "%ld\n", data->max[attr->index]);
234}
235
236static ssize_t show_max_hyst(struct device *dev,
237 struct device_attribute *devattr, char *buf)
238{
239 struct abx500_temp *data = dev_get_drvdata(dev);
240 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
241
242 return sprintf(buf, "%ld\n", data->max_hyst[attr->index]);
243}
244
245static ssize_t show_min_alarm(struct device *dev,
246 struct device_attribute *devattr, char *buf)
247{
248 struct abx500_temp *data = dev_get_drvdata(dev);
249 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
250
251 return sprintf(buf, "%d\n", data->min_alarm[attr->index]);
252}
253
254static ssize_t show_max_alarm(struct device *dev,
255 struct device_attribute *devattr, char *buf)
256{
257 struct abx500_temp *data = dev_get_drvdata(dev);
258 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
259
260 return sprintf(buf, "%d\n", data->max_alarm[attr->index]);
261}
262
263static mode_t abx500_attrs_visible(struct kobject *kobj,
264 struct attribute *attr, int n)
265{
266 struct device *dev = container_of(kobj, struct device, kobj);
267 struct abx500_temp *data = dev_get_drvdata(dev);
268
269 if (data->ops.is_visible)
270 return data->ops.is_visible(attr, n);
271
272 return attr->mode;
273}
274
275/* Chip name, required by hwmon */
276static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
277
278/* GPADC - SENSOR1 */
279static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 0);
280static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
281static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_min, set_min, 0);
282static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_max, set_max, 0);
283static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
284 show_max_hyst, set_max_hyst, 0);
285static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_min_alarm, NULL, 0);
286static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_max_alarm, NULL, 0);
287
288/* GPADC - SENSOR2 */
289static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, 1);
290static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 1);
291static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, 1);
292static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, 1);
293static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IWUSR | S_IRUGO,
294 show_max_hyst, set_max_hyst, 1);
295static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_min_alarm, NULL, 1);
296static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_max_alarm, NULL, 1);
297
298/* GPADC - SENSOR3 */
299static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_label, NULL, 2);
300static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 2);
301static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, 2);
302static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, 2);
303static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IWUSR | S_IRUGO,
304 show_max_hyst, set_max_hyst, 2);
305static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_min_alarm, NULL, 2);
306static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_max_alarm, NULL, 2);
307
308/* GPADC - SENSOR4 */
309static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_label, NULL, 3);
310static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_input, NULL, 3);
311static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_min, set_min, 3);
312static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_max, set_max, 3);
313static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IWUSR | S_IRUGO,
314 show_max_hyst, set_max_hyst, 3);
315static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_min_alarm, NULL, 3);
316static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 3);
317
318struct attribute *abx500_temp_attributes[] = {
319 &sensor_dev_attr_name.dev_attr.attr,
320
321 &sensor_dev_attr_temp1_label.dev_attr.attr,
322 &sensor_dev_attr_temp1_input.dev_attr.attr,
323 &sensor_dev_attr_temp1_min.dev_attr.attr,
324 &sensor_dev_attr_temp1_max.dev_attr.attr,
325 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
326 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
327 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
328
329 &sensor_dev_attr_temp2_label.dev_attr.attr,
330 &sensor_dev_attr_temp2_input.dev_attr.attr,
331 &sensor_dev_attr_temp2_min.dev_attr.attr,
332 &sensor_dev_attr_temp2_max.dev_attr.attr,
333 &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
334 &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
335 &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
336
337 &sensor_dev_attr_temp3_label.dev_attr.attr,
338 &sensor_dev_attr_temp3_input.dev_attr.attr,
339 &sensor_dev_attr_temp3_min.dev_attr.attr,
340 &sensor_dev_attr_temp3_max.dev_attr.attr,
341 &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
342 &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
343 &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
344
345 &sensor_dev_attr_temp4_label.dev_attr.attr,
346 &sensor_dev_attr_temp4_input.dev_attr.attr,
347 &sensor_dev_attr_temp4_min.dev_attr.attr,
348 &sensor_dev_attr_temp4_max.dev_attr.attr,
349 &sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
350 &sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
351 &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
352 NULL
353};
354
355static const struct attribute_group abx500_temp_group = {
356 .attrs = abx500_temp_attributes,
357 .is_visible = abx500_attrs_visible,
358};
359
360static irqreturn_t abx500_temp_irq_handler(int irq, void *irq_data)
361{
362 struct platform_device *pdev = irq_data;
363 struct abx500_temp *data = platform_get_drvdata(pdev);
364
365 data->ops.irq_handler(irq, data);
366 return IRQ_HANDLED;
367}
368
369static int setup_irqs(struct platform_device *pdev)
370{
371 int ret;
372 int irq = platform_get_irq_byname(pdev, "ABX500_TEMP_WARM");
373
374 if (irq < 0) {
375 dev_err(&pdev->dev, "Get irq by name failed\n");
376 return irq;
377 }
378
379 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
380 abx500_temp_irq_handler, IRQF_NO_SUSPEND, "abx500-temp", pdev);
381 if (ret < 0)
382 dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret);
383
384 return ret;
385}
386
387static int abx500_temp_probe(struct platform_device *pdev)
388{
389 struct abx500_temp *data;
390 int err;
391
392 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
393 if (!data)
394 return -ENOMEM;
395
396 data->pdev = pdev;
397 mutex_init(&data->lock);
398
399 /* Chip specific initialization */
400 err = abx500_hwmon_init(data);
401 if (err < 0 || !data->ops.read_sensor || !data->ops.show_name ||
402 !data->ops.show_label)
403 return err;
404
405 INIT_DEFERRABLE_WORK(&data->work, gpadc_monitor);
406
407 platform_set_drvdata(pdev, data);
408
409 err = sysfs_create_group(&pdev->dev.kobj, &abx500_temp_group);
410 if (err < 0) {
411 dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", err);
412 return err;
413 }
414
415 data->hwmon_dev = hwmon_device_register(&pdev->dev);
416 if (IS_ERR(data->hwmon_dev)) {
417 err = PTR_ERR(data->hwmon_dev);
418 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
419 goto exit_sysfs_group;
420 }
421
422 if (data->ops.irq_handler) {
423 err = setup_irqs(pdev);
424 if (err < 0)
425 goto exit_hwmon_reg;
426 }
427 return 0;
428
429exit_hwmon_reg:
430 hwmon_device_unregister(data->hwmon_dev);
431exit_sysfs_group:
432 sysfs_remove_group(&pdev->dev.kobj, &abx500_temp_group);
433 return err;
434}
435
436static int abx500_temp_remove(struct platform_device *pdev)
437{
438 struct abx500_temp *data = platform_get_drvdata(pdev);
439
440 cancel_delayed_work_sync(&data->work);
441 hwmon_device_unregister(data->hwmon_dev);
442 sysfs_remove_group(&pdev->dev.kobj, &abx500_temp_group);
443
444 return 0;
445}
446
447static int abx500_temp_suspend(struct platform_device *pdev,
448 pm_message_t state)
449{
450 struct abx500_temp *data = platform_get_drvdata(pdev);
451
452 if (data->work_active)
453 cancel_delayed_work_sync(&data->work);
454
455 return 0;
456}
457
458static int abx500_temp_resume(struct platform_device *pdev)
459{
460 struct abx500_temp *data = platform_get_drvdata(pdev);
461
462 if (data->work_active)
463 schedule_monitor(data);
464
465 return 0;
466}
467
468#ifdef CONFIG_OF
469static const struct of_device_id abx500_temp_match[] = {
470 { .compatible = "stericsson,abx500-temp" },
471 {},
472};
473#endif
474
475static struct platform_driver abx500_temp_driver = {
476 .driver = {
477 .owner = THIS_MODULE,
478 .name = "abx500-temp",
479 .of_match_table = of_match_ptr(abx500_temp_match),
480 },
481 .suspend = abx500_temp_suspend,
482 .resume = abx500_temp_resume,
483 .probe = abx500_temp_probe,
484 .remove = abx500_temp_remove,
485};
486
487module_platform_driver(abx500_temp_driver);
488
489MODULE_AUTHOR("Martin Persson <martin.persson@stericsson.com>");
490MODULE_DESCRIPTION("ABX500 temperature driver");
491MODULE_LICENSE("GPL");