Commit fb6c023a2b845df1ec383b74644ac35a4bbb76b6

Authored by Mark Brown
Committed by Samuel Ortiz
1 parent 39b1772a24

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;