1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/hwmon/wm831x-hwmon.c - Wolfson Microelectronics WM831x PMIC
4 * hardware monitoring features.
6 * Copyright (C) 2009 Wolfson Microelectronics plc
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/err.h>
13 #include <linux/hwmon.h>
14 #include <linux/hwmon-sysfs.h>
15 #include <linux/slab.h>
17 #include <linux/mfd/wm831x/core.h>
18 #include <linux/mfd/wm831x/auxadc.h>
20 static const char * const input_names
[] = {
21 [WM831X_AUX_SYSVDD
] = "SYSVDD",
22 [WM831X_AUX_USB
] = "USB",
23 [WM831X_AUX_BKUP_BATT
] = "Backup battery",
24 [WM831X_AUX_BATT
] = "Battery",
25 [WM831X_AUX_WALL
] = "WALL",
26 [WM831X_AUX_CHIP_TEMP
] = "PMIC",
27 [WM831X_AUX_BATT_TEMP
] = "Battery",
30 static ssize_t
show_voltage(struct device
*dev
,
31 struct device_attribute
*attr
, char *buf
)
33 struct wm831x
*wm831x
= dev_get_drvdata(dev
);
34 int channel
= to_sensor_dev_attr(attr
)->index
;
37 ret
= wm831x_auxadc_read_uv(wm831x
, channel
);
41 return sprintf(buf
, "%d\n", DIV_ROUND_CLOSEST(ret
, 1000));
44 static ssize_t
show_chip_temp(struct device
*dev
,
45 struct device_attribute
*attr
, char *buf
)
47 struct wm831x
*wm831x
= dev_get_drvdata(dev
);
48 int channel
= to_sensor_dev_attr(attr
)->index
;
51 ret
= wm831x_auxadc_read(wm831x
, channel
);
55 /* Degrees celsius = (512.18-ret) / 1.0983 */
56 ret
= 512180 - (ret
* 1000);
57 ret
= DIV_ROUND_CLOSEST(ret
* 10000, 10983);
59 return sprintf(buf
, "%d\n", ret
);
62 static ssize_t
show_label(struct device
*dev
,
63 struct device_attribute
*attr
, char *buf
)
65 int channel
= to_sensor_dev_attr(attr
)->index
;
67 return sprintf(buf
, "%s\n", input_names
[channel
]);
70 #define WM831X_VOLTAGE(id, name) \
71 static SENSOR_DEVICE_ATTR(in##id##_input, S_IRUGO, show_voltage, \
74 #define WM831X_NAMED_VOLTAGE(id, name) \
75 WM831X_VOLTAGE(id, name); \
76 static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \
79 WM831X_VOLTAGE(0, WM831X_AUX_AUX1
);
80 WM831X_VOLTAGE(1, WM831X_AUX_AUX2
);
81 WM831X_VOLTAGE(2, WM831X_AUX_AUX3
);
82 WM831X_VOLTAGE(3, WM831X_AUX_AUX4
);
84 WM831X_NAMED_VOLTAGE(4, WM831X_AUX_SYSVDD
);
85 WM831X_NAMED_VOLTAGE(5, WM831X_AUX_USB
);
86 WM831X_NAMED_VOLTAGE(6, WM831X_AUX_BATT
);
87 WM831X_NAMED_VOLTAGE(7, WM831X_AUX_WALL
);
88 WM831X_NAMED_VOLTAGE(8, WM831X_AUX_BKUP_BATT
);
90 static SENSOR_DEVICE_ATTR(temp1_input
, S_IRUGO
, show_chip_temp
, NULL
,
91 WM831X_AUX_CHIP_TEMP
);
92 static SENSOR_DEVICE_ATTR(temp1_label
, S_IRUGO
, show_label
, NULL
,
93 WM831X_AUX_CHIP_TEMP
);
95 * Report as a voltage since conversion depends on external components
96 * and that's what the ABI wants.
98 static SENSOR_DEVICE_ATTR(temp2_input
, S_IRUGO
, show_voltage
, NULL
,
99 WM831X_AUX_BATT_TEMP
);
100 static SENSOR_DEVICE_ATTR(temp2_label
, S_IRUGO
, show_label
, NULL
,
101 WM831X_AUX_BATT_TEMP
);
103 static struct attribute
*wm831x_attrs
[] = {
104 &sensor_dev_attr_in0_input
.dev_attr
.attr
,
105 &sensor_dev_attr_in1_input
.dev_attr
.attr
,
106 &sensor_dev_attr_in2_input
.dev_attr
.attr
,
107 &sensor_dev_attr_in3_input
.dev_attr
.attr
,
109 &sensor_dev_attr_in4_input
.dev_attr
.attr
,
110 &sensor_dev_attr_in4_label
.dev_attr
.attr
,
111 &sensor_dev_attr_in5_input
.dev_attr
.attr
,
112 &sensor_dev_attr_in5_label
.dev_attr
.attr
,
113 &sensor_dev_attr_in6_input
.dev_attr
.attr
,
114 &sensor_dev_attr_in6_label
.dev_attr
.attr
,
115 &sensor_dev_attr_in7_input
.dev_attr
.attr
,
116 &sensor_dev_attr_in7_label
.dev_attr
.attr
,
117 &sensor_dev_attr_in8_input
.dev_attr
.attr
,
118 &sensor_dev_attr_in8_label
.dev_attr
.attr
,
120 &sensor_dev_attr_temp1_input
.dev_attr
.attr
,
121 &sensor_dev_attr_temp1_label
.dev_attr
.attr
,
122 &sensor_dev_attr_temp2_input
.dev_attr
.attr
,
123 &sensor_dev_attr_temp2_label
.dev_attr
.attr
,
128 ATTRIBUTE_GROUPS(wm831x
);
130 static int wm831x_hwmon_probe(struct platform_device
*pdev
)
132 struct wm831x
*wm831x
= dev_get_drvdata(pdev
->dev
.parent
);
133 struct device
*hwmon_dev
;
135 hwmon_dev
= devm_hwmon_device_register_with_groups(&pdev
->dev
, "wm831x",
138 return PTR_ERR_OR_ZERO(hwmon_dev
);
141 static struct platform_driver wm831x_hwmon_driver
= {
142 .probe
= wm831x_hwmon_probe
,
144 .name
= "wm831x-hwmon",
148 module_platform_driver(wm831x_hwmon_driver
);
150 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
151 MODULE_DESCRIPTION("WM831x Hardware Monitoring");
152 MODULE_LICENSE("GPL");
153 MODULE_ALIAS("platform:wm831x-hwmon");