Commit fb6c023a2b845df1ec383b74644ac35a4bbb76b6
Committed by
Samuel Ortiz
1 parent
39b1772a24
Exists in
master
and in
4 other branches
hwmon: Add WM835x PMIC hardware monitoring driver
This driver provides reporting of the status supply voltage rails of the WM835x series of PMICs via the hwmon API. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 6 changed files with 197 additions and 0 deletions Side-by-side Diff
Documentation/hwmon/wm8350
1 | +Kernel driver wm8350-hwmon | |
2 | +========================== | |
3 | + | |
4 | +Supported chips: | |
5 | + * Wolfson Microelectronics WM835x PMICs | |
6 | + Prefix: 'wm8350' | |
7 | + Datasheet: | |
8 | + http://www.wolfsonmicro.com/products/WM8350 | |
9 | + http://www.wolfsonmicro.com/products/WM8351 | |
10 | + http://www.wolfsonmicro.com/products/WM8352 | |
11 | + | |
12 | +Authors: Mark Brown <broonie@opensource.wolfsonmicro.com> | |
13 | + | |
14 | +Description | |
15 | +----------- | |
16 | + | |
17 | +The WM835x series of PMICs include an AUXADC which can be used to | |
18 | +monitor a range of system operating parameters, including the voltages | |
19 | +of the major supplies within the system. Currently the driver provides | |
20 | +simple access to these major supplies. | |
21 | + | |
22 | +Voltage Monitoring | |
23 | +------------------ | |
24 | + | |
25 | +Voltages are sampled by a 12 bit ADC. For the internal supplies the ADC | |
26 | +is referenced to the system VRTC. |
drivers/hwmon/Kconfig
... | ... | @@ -937,6 +937,16 @@ |
937 | 937 | This driver can also be built as a module. If so, the module |
938 | 938 | will be called w83627ehf. |
939 | 939 | |
940 | +config SENSORS_WM8350 | |
941 | + tristate "Wolfson Microelectronics WM835x" | |
942 | + depends on MFD_WM8350 | |
943 | + help | |
944 | + If you say yes here you get support for the hardware | |
945 | + monitoring features of the WM835x series of PMICs. | |
946 | + | |
947 | + This driver can also be built as a module. If so, the module | |
948 | + will be called wm8350-hwmon. | |
949 | + | |
940 | 950 | config SENSORS_ULTRA45 |
941 | 951 | tristate "Sun Ultra45 PIC16F747" |
942 | 952 | depends on SPARC64 |
drivers/hwmon/Makefile
... | ... | @@ -90,6 +90,7 @@ |
90 | 90 | obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o |
91 | 91 | obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o |
92 | 92 | obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o |
93 | +obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o | |
93 | 94 | |
94 | 95 | ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) |
95 | 96 | EXTRA_CFLAGS += -DDEBUG |
drivers/hwmon/wm8350-hwmon.c
1 | +/* | |
2 | + * drivers/hwmon/wm8350-hwmon.c - Wolfson Microelectronics WM8350 PMIC | |
3 | + * hardware monitoring features. | |
4 | + * | |
5 | + * Copyright (C) 2009 Wolfson Microelectronics plc | |
6 | + * | |
7 | + * This program is free software; you can redistribute it and/or modify it | |
8 | + * under the terms of the GNU General Public License v2 as published by the | |
9 | + * Free Software Foundation. | |
10 | + * | |
11 | + * This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | + * more details. | |
15 | + * | |
16 | + * You should have received a copy of the GNU General Public License along with | |
17 | + * this program; if not, write to the Free Software Foundation, Inc., | |
18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | |
19 | + */ | |
20 | + | |
21 | +#include <linux/kernel.h> | |
22 | +#include <linux/module.h> | |
23 | +#include <linux/err.h> | |
24 | +#include <linux/platform_device.h> | |
25 | +#include <linux/hwmon.h> | |
26 | +#include <linux/hwmon-sysfs.h> | |
27 | + | |
28 | +#include <linux/mfd/wm8350/core.h> | |
29 | +#include <linux/mfd/wm8350/comparator.h> | |
30 | + | |
31 | +static ssize_t show_name(struct device *dev, | |
32 | + struct device_attribute *attr, char *buf) | |
33 | +{ | |
34 | + return sprintf(buf, "wm8350\n"); | |
35 | +} | |
36 | + | |
37 | +static const char *input_names[] = { | |
38 | + [WM8350_AUXADC_USB] = "USB", | |
39 | + [WM8350_AUXADC_LINE] = "Line", | |
40 | + [WM8350_AUXADC_BATT] = "Battery", | |
41 | +}; | |
42 | + | |
43 | + | |
44 | +static ssize_t show_voltage(struct device *dev, | |
45 | + struct device_attribute *attr, char *buf) | |
46 | +{ | |
47 | + struct wm8350 *wm8350 = dev_get_drvdata(dev); | |
48 | + int channel = to_sensor_dev_attr(attr)->index; | |
49 | + int val; | |
50 | + | |
51 | + val = wm8350_read_auxadc(wm8350, channel, 0, 0) * WM8350_AUX_COEFF; | |
52 | + val = DIV_ROUND_CLOSEST(val, 1000); | |
53 | + | |
54 | + return sprintf(buf, "%d\n", val); | |
55 | +} | |
56 | + | |
57 | +static ssize_t show_label(struct device *dev, | |
58 | + struct device_attribute *attr, char *buf) | |
59 | +{ | |
60 | + int channel = to_sensor_dev_attr(attr)->index; | |
61 | + | |
62 | + return sprintf(buf, "%s\n", input_names[channel]); | |
63 | +} | |
64 | + | |
65 | +#define WM8350_NAMED_VOLTAGE(id, name) \ | |
66 | + static SENSOR_DEVICE_ATTR(in##id##_input, S_IRUGO, show_voltage,\ | |
67 | + NULL, name); \ | |
68 | + static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \ | |
69 | + NULL, name) | |
70 | + | |
71 | +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |
72 | + | |
73 | +WM8350_NAMED_VOLTAGE(0, WM8350_AUXADC_USB); | |
74 | +WM8350_NAMED_VOLTAGE(1, WM8350_AUXADC_BATT); | |
75 | +WM8350_NAMED_VOLTAGE(2, WM8350_AUXADC_LINE); | |
76 | + | |
77 | +static struct attribute *wm8350_attributes[] = { | |
78 | + &dev_attr_name.attr, | |
79 | + | |
80 | + &sensor_dev_attr_in0_input.dev_attr.attr, | |
81 | + &sensor_dev_attr_in0_label.dev_attr.attr, | |
82 | + &sensor_dev_attr_in1_input.dev_attr.attr, | |
83 | + &sensor_dev_attr_in1_label.dev_attr.attr, | |
84 | + &sensor_dev_attr_in2_input.dev_attr.attr, | |
85 | + &sensor_dev_attr_in2_label.dev_attr.attr, | |
86 | + | |
87 | + NULL, | |
88 | +}; | |
89 | + | |
90 | +static const struct attribute_group wm8350_attr_group = { | |
91 | + .attrs = wm8350_attributes, | |
92 | +}; | |
93 | + | |
94 | +static int __devinit wm8350_hwmon_probe(struct platform_device *pdev) | |
95 | +{ | |
96 | + struct wm8350 *wm8350 = platform_get_drvdata(pdev); | |
97 | + int ret; | |
98 | + | |
99 | + ret = sysfs_create_group(&pdev->dev.kobj, &wm8350_attr_group); | |
100 | + if (ret) | |
101 | + goto err; | |
102 | + | |
103 | + wm8350->hwmon.classdev = hwmon_device_register(&pdev->dev); | |
104 | + if (IS_ERR(wm8350->hwmon.classdev)) { | |
105 | + ret = PTR_ERR(wm8350->hwmon.classdev); | |
106 | + goto err_group; | |
107 | + } | |
108 | + | |
109 | + return 0; | |
110 | + | |
111 | +err_group: | |
112 | + sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group); | |
113 | +err: | |
114 | + return ret; | |
115 | +} | |
116 | + | |
117 | +static int __devexit wm8350_hwmon_remove(struct platform_device *pdev) | |
118 | +{ | |
119 | + struct wm8350 *wm8350 = platform_get_drvdata(pdev); | |
120 | + | |
121 | + hwmon_device_unregister(wm8350->hwmon.classdev); | |
122 | + sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group); | |
123 | + | |
124 | + return 0; | |
125 | +} | |
126 | + | |
127 | +static struct platform_driver wm8350_hwmon_driver = { | |
128 | + .probe = wm8350_hwmon_probe, | |
129 | + .remove = __devexit_p(wm8350_hwmon_remove), | |
130 | + .driver = { | |
131 | + .name = "wm8350-hwmon", | |
132 | + .owner = THIS_MODULE, | |
133 | + }, | |
134 | +}; | |
135 | + | |
136 | +static int __init wm8350_hwmon_init(void) | |
137 | +{ | |
138 | + return platform_driver_register(&wm8350_hwmon_driver); | |
139 | +} | |
140 | +module_init(wm8350_hwmon_init); | |
141 | + | |
142 | +static void __exit wm8350_hwmon_exit(void) | |
143 | +{ | |
144 | + platform_driver_unregister(&wm8350_hwmon_driver); | |
145 | +} | |
146 | +module_exit(wm8350_hwmon_exit); | |
147 | + | |
148 | +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | |
149 | +MODULE_DESCRIPTION("WM8350 Hardware Monitoring"); | |
150 | +MODULE_LICENSE("GPL"); | |
151 | +MODULE_ALIAS("platform:wm8350-hwmon"); |
drivers/mfd/wm8350-core.c
... | ... | @@ -1472,6 +1472,8 @@ |
1472 | 1472 | &(wm8350->codec.pdev)); |
1473 | 1473 | wm8350_client_dev_register(wm8350, "wm8350-gpio", |
1474 | 1474 | &(wm8350->gpio.pdev)); |
1475 | + wm8350_client_dev_register(wm8350, "wm8350-hwmon", | |
1476 | + &(wm8350->hwmon.pdev)); | |
1475 | 1477 | wm8350_client_dev_register(wm8350, "wm8350-power", |
1476 | 1478 | &(wm8350->power.pdev)); |
1477 | 1479 | wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev)); |
... | ... | @@ -1498,6 +1500,7 @@ |
1498 | 1500 | platform_device_unregister(wm8350->wdt.pdev); |
1499 | 1501 | platform_device_unregister(wm8350->rtc.pdev); |
1500 | 1502 | platform_device_unregister(wm8350->power.pdev); |
1503 | + platform_device_unregister(wm8350->hwmon.pdev); | |
1501 | 1504 | platform_device_unregister(wm8350->gpio.pdev); |
1502 | 1505 | platform_device_unregister(wm8350->codec.pdev); |
1503 | 1506 |
include/linux/mfd/wm8350/core.h
... | ... | @@ -605,6 +605,11 @@ |
605 | 605 | void *data; |
606 | 606 | }; |
607 | 607 | |
608 | +struct wm8350_hwmon { | |
609 | + struct platform_device *pdev; | |
610 | + struct device *classdev; | |
611 | +}; | |
612 | + | |
608 | 613 | struct wm8350 { |
609 | 614 | struct device *dev; |
610 | 615 | |
... | ... | @@ -629,6 +634,7 @@ |
629 | 634 | /* Client devices */ |
630 | 635 | struct wm8350_codec codec; |
631 | 636 | struct wm8350_gpio gpio; |
637 | + struct wm8350_hwmon hwmon; | |
632 | 638 | struct wm8350_pmic pmic; |
633 | 639 | struct wm8350_power power; |
634 | 640 | struct wm8350_rtc rtc; |