Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mark Brown and committed by
Samuel Ortiz
fb6c023a 39b1772a

+197
+26
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.
+10
drivers/hwmon/Kconfig
··· 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
+1
drivers/hwmon/Makefile
··· 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
+151
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");
+3
drivers/mfd/wm8350-core.c
··· 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)); ··· 1500 1498 platform_device_unregister(wm8350->wdt.pdev); 1501 1499 platform_device_unregister(wm8350->rtc.pdev); 1502 1500 platform_device_unregister(wm8350->power.pdev); 1501 + platform_device_unregister(wm8350->hwmon.pdev); 1503 1502 platform_device_unregister(wm8350->gpio.pdev); 1504 1503 platform_device_unregister(wm8350->codec.pdev); 1505 1504
+6
include/linux/mfd/wm8350/core.h
··· 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 ··· 634 629 /* Client devices */ 635 630 struct wm8350_codec codec; 636 631 struct wm8350_gpio gpio; 632 + struct wm8350_hwmon hwmon; 637 633 struct wm8350_pmic pmic; 638 634 struct wm8350_power power; 639 635 struct wm8350_rtc rtc;