aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt3
-rw-r--r--Documentation/hwmon/k10temp2
-rw-r--r--Documentation/hwmon/menf21bmc50
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/hwmon/Kconfig15
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/ab8500.c5
-rw-r--r--drivers/hwmon/ads1015.c21
-rw-r--r--drivers/hwmon/da9052-hwmon.c54
-rw-r--r--drivers/hwmon/da9055-hwmon.c52
-rw-r--r--drivers/hwmon/k10temp.c157
-rw-r--r--drivers/hwmon/menf21bmc_hwmon.c230
-rw-r--r--drivers/hwmon/ntc_thermistor.c25
-rw-r--r--drivers/hwmon/smsc47b397.c51
-rw-r--r--drivers/leds/Kconfig9
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-menf21bmc.c131
-rw-r--r--drivers/mfd/Kconfig15
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/menf21bmc.c132
-rw-r--r--drivers/watchdog/Kconfig10
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/menf21bmc_wdt.c203
23 files changed, 949 insertions, 228 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
index 2391e5c41999..fcca8e744f41 100644
--- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -25,6 +25,9 @@ Requires node properties:
25- "io-channels" Channel node of ADC to be used for 25- "io-channels" Channel node of ADC to be used for
26 conversion. 26 conversion.
27 27
28Optional node properties:
29- "#thermal-sensor-cells" Used to expose itself to thermal fw.
30
28Read more about iio bindings at 31Read more about iio bindings at
29 Documentation/devicetree/bindings/iio/iio-bindings.txt 32 Documentation/devicetree/bindings/iio/iio-bindings.txt
30 33
diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp
index ee6d30ec1522..254d2f55345a 100644
--- a/Documentation/hwmon/k10temp
+++ b/Documentation/hwmon/k10temp
@@ -11,7 +11,7 @@ Supported chips:
11 Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra) 11 Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
12* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series) 12* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
13* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series) 13* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
14* AMD Family 15h processors: "Bulldozer" (FX-Series), "Trinity", "Kaveri" 14* AMD Family 15h processors: "Bulldozer" (FX-Series), "Trinity", "Kaveri", "Carrizo"
15* AMD Family 16h processors: "Kabini", "Mullins" 15* AMD Family 16h processors: "Kabini", "Mullins"
16 16
17 Prefix: 'k10temp' 17 Prefix: 'k10temp'
diff --git a/Documentation/hwmon/menf21bmc b/Documentation/hwmon/menf21bmc
new file mode 100644
index 000000000000..2a273a065c5e
--- /dev/null
+++ b/Documentation/hwmon/menf21bmc
@@ -0,0 +1,50 @@
1Kernel driver menf21bmc_hwmon
2=============================
3
4Supported chips:
5 * MEN 14F021P00
6 Prefix: 'menf21bmc_hwmon'
7 Adresses scanned: -
8
9Author: Andreas Werner <andreas.werner@men.de>
10
11Description
12-----------
13
14The menf21bmc is a Board Management Controller (BMC) which provides an I2C
15interface to the host to access the features implemented in the BMC.
16
17This driver gives access to the voltage monitoring feature of the main
18voltages of the board.
19The voltage sensors are connected to the ADC inputs of the BMC which is
20a PIC16F917 Mikrocontroller.
21
22Usage Notes
23-----------
24
25This driver is part of the MFD driver named "menf21bmc" and does
26not auto-detect devices.
27You will have to instantiate the MFD driver explicitly.
28Please see Documentation/i2c/instantiating-devices for
29details.
30
31Sysfs entries
32-------------
33
34The following attributes are supported. All attributes are read only
35The Limits are read once by the driver.
36
37in0_input +3.3V input voltage
38in1_input +5.0V input voltage
39in2_input +12.0V input voltage
40in3_input +5V Standby input voltage
41in4_input VBAT (on board battery)
42
43in[0-4]_min Minimum voltage limit
44in[0-4]_max Maximum voltage limit
45
46in0_label "MON_3_3V"
47in1_label "MON_5V"
48in2_label "MON_12V"
49in3_label "5V_STANDBY"
50in4_label "VBAT"
diff --git a/MAINTAINERS b/MAINTAINERS
index 40d4796886c9..8b0902106cc0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7364,6 +7364,14 @@ T: git git://linuxtv.org/media_tree.git
7364S: Maintained 7364S: Maintained
7365F: drivers/media/usb/pwc/* 7365F: drivers/media/usb/pwc/*
7366 7366
7367PWM FAN DRIVER
7368M: Kamil Debski <k.debski@samsung.com>
7369L: lm-sensors@lm-sensors.org
7370S: Supported
7371F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
7372F: Documentation/hwmon/pwm-fan
7373F: drivers/hwmon/pwm-fan.c
7374
7367PWM SUBSYSTEM 7375PWM SUBSYSTEM
7368M: Thierry Reding <thierry.reding@gmail.com> 7376M: Thierry Reding <thierry.reding@gmail.com>
7369L: linux-pwm@vger.kernel.org 7377L: linux-pwm@vger.kernel.org
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f00d048aa583..5286d7ce1f9e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -280,8 +280,8 @@ config SENSORS_K10TEMP
280 If you say yes here you get support for the temperature 280 If you say yes here you get support for the temperature
281 sensor(s) inside your CPU. Supported are later revisions of 281 sensor(s) inside your CPU. Supported are later revisions of
282 the AMD Family 10h and all revisions of the AMD Family 11h, 282 the AMD Family 10h and all revisions of the AMD Family 11h,
283 12h (Llano), 14h (Brazos), 15h (Bulldozer/Trinity/Kaveri) and 283 12h (Llano), 14h (Brazos), 15h (Bulldozer/Trinity/Kaveri/Carrizo)
284 16h (Kabini/Mullins) microarchitectures. 284 and 16h (Kabini/Mullins) microarchitectures.
285 285
286 This driver can also be built as a module. If so, the module 286 This driver can also be built as a module. If so, the module
287 will be called k10temp. 287 will be called k10temp.
@@ -839,6 +839,16 @@ config SENSORS_MCP3021
839 This driver can also be built as a module. If so, the module 839 This driver can also be built as a module. If so, the module
840 will be called mcp3021. 840 will be called mcp3021.
841 841
842config SENSORS_MENF21BMC_HWMON
843 tristate "MEN 14F021P00 BMC Hardware Monitoring"
844 depends on MFD_MENF21BMC
845 help
846 Say Y here to include support for the MEN 14F021P00 BMC
847 hardware monitoring.
848
849 This driver can also be built as a module. If so the module
850 will be called menf21bmc_hwmon.
851
842config SENSORS_ADCXX 852config SENSORS_ADCXX
843 tristate "National Semiconductor ADCxxxSxxx" 853 tristate "National Semiconductor ADCxxxSxxx"
844 depends on SPI_MASTER 854 depends on SPI_MASTER
@@ -1077,6 +1087,7 @@ config SENSORS_PC87427
1077config SENSORS_NTC_THERMISTOR 1087config SENSORS_NTC_THERMISTOR
1078 tristate "NTC thermistor support from Murata" 1088 tristate "NTC thermistor support from Murata"
1079 depends on !OF || IIO=n || IIO 1089 depends on !OF || IIO=n || IIO
1090 depends on THERMAL || !THERMAL_OF
1080 help 1091 help
1081 This driver supports NTC thermistors sensor reading and its 1092 This driver supports NTC thermistors sensor reading and its
1082 interpretation. The driver can also monitor the temperature and 1093 interpretation. The driver can also monitor the temperature and
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index be28152c9848..c90a7611efaa 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -115,6 +115,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
115obj-$(CONFIG_SENSORS_MAX6697) += max6697.o 115obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
116obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o 116obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
117obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o 117obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
118obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
118obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o 119obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o
119obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o 120obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
120obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o 121obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
diff --git a/drivers/hwmon/ab8500.c b/drivers/hwmon/ab8500.c
index d844dc806853..8b6a4f4c8774 100644
--- a/drivers/hwmon/ab8500.c
+++ b/drivers/hwmon/ab8500.c
@@ -6,7 +6,7 @@
6 * 6 *
7 * When the AB8500 thermal warning temperature is reached (threshold cannot 7 * When the AB8500 thermal warning temperature is reached (threshold cannot
8 * be changed by SW), an interrupt is set, and if no further action is taken 8 * be changed by SW), an interrupt is set, and if no further action is taken
9 * within a certain time frame, pm_power off will be called. 9 * within a certain time frame, kernel_power_off will be called.
10 * 10 *
11 * When AB8500 thermal shutdown temperature is reached a hardware shutdown of 11 * When AB8500 thermal shutdown temperature is reached a hardware shutdown of
12 * the AB8500 will occur. 12 * the AB8500 will occur.
@@ -21,6 +21,7 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/power/ab8500.h> 23#include <linux/power/ab8500.h>
24#include <linux/reboot.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include <linux/sysfs.h> 26#include <linux/sysfs.h>
26#include "abx500.h" 27#include "abx500.h"
@@ -106,7 +107,7 @@ static void ab8500_thermal_power_off(struct work_struct *work)
106 107
107 dev_warn(&abx500_data->pdev->dev, "Power off due to critical temp\n"); 108 dev_warn(&abx500_data->pdev->dev, "Power off due to critical temp\n");
108 109
109 pm_power_off(); 110 kernel_power_off();
110} 111}
111 112
112static ssize_t ab8500_show_name(struct device *dev, 113static ssize_t ab8500_show_name(struct device *dev,
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
index 126516414c11..f155b8380481 100644
--- a/drivers/hwmon/ads1015.c
+++ b/drivers/hwmon/ads1015.c
@@ -184,20 +184,18 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
184 return -EINVAL; 184 return -EINVAL;
185 185
186 for_each_child_of_node(client->dev.of_node, node) { 186 for_each_child_of_node(client->dev.of_node, node) {
187 const __be32 *property; 187 u32 pval;
188 int len;
189 unsigned int channel; 188 unsigned int channel;
190 unsigned int pga = ADS1015_DEFAULT_PGA; 189 unsigned int pga = ADS1015_DEFAULT_PGA;
191 unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; 190 unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
192 191
193 property = of_get_property(node, "reg", &len); 192 if (of_property_read_u32(node, "reg", &pval)) {
194 if (!property || len != sizeof(int)) {
195 dev_err(&client->dev, "invalid reg on %s\n", 193 dev_err(&client->dev, "invalid reg on %s\n",
196 node->full_name); 194 node->full_name);
197 continue; 195 continue;
198 } 196 }
199 197
200 channel = be32_to_cpup(property); 198 channel = pval;
201 if (channel >= ADS1015_CHANNELS) { 199 if (channel >= ADS1015_CHANNELS) {
202 dev_err(&client->dev, 200 dev_err(&client->dev,
203 "invalid channel index %d on %s\n", 201 "invalid channel index %d on %s\n",
@@ -205,20 +203,17 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
205 continue; 203 continue;
206 } 204 }
207 205
208 property = of_get_property(node, "ti,gain", &len); 206 if (!of_property_read_u32(node, "ti,gain", &pval)) {
209 if (property && len == sizeof(int)) { 207 pga = pval;
210 pga = be32_to_cpup(property);
211 if (pga > 6) { 208 if (pga > 6) {
212 dev_err(&client->dev, 209 dev_err(&client->dev, "invalid gain on %s\n",
213 "invalid gain on %s\n",
214 node->full_name); 210 node->full_name);
215 return -EINVAL; 211 return -EINVAL;
216 } 212 }
217 } 213 }
218 214
219 property = of_get_property(node, "ti,datarate", &len); 215 if (!of_property_read_u32(node, "ti,datarate", &pval)) {
220 if (property && len == sizeof(int)) { 216 data_rate = pval;
221 data_rate = be32_to_cpup(property);
222 if (data_rate > 7) { 217 if (data_rate > 7) {
223 dev_err(&client->dev, 218 dev_err(&client->dev,
224 "invalid data_rate on %s\n", 219 "invalid data_rate on %s\n",
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
index d14ab3c45daa..692b3f34d88c 100644
--- a/drivers/hwmon/da9052-hwmon.c
+++ b/drivers/hwmon/da9052-hwmon.c
@@ -26,7 +26,6 @@
26 26
27struct da9052_hwmon { 27struct da9052_hwmon {
28 struct da9052 *da9052; 28 struct da9052 *da9052;
29 struct device *class_device;
30 struct mutex hwmon_lock; 29 struct mutex hwmon_lock;
31}; 30};
32 31
@@ -190,13 +189,6 @@ static ssize_t da9052_read_vbbat(struct device *dev,
190 return sprintf(buf, "%d\n", vbbat_reg_to_mv(ret)); 189 return sprintf(buf, "%d\n", vbbat_reg_to_mv(ret));
191} 190}
192 191
193static ssize_t da9052_hwmon_show_name(struct device *dev,
194 struct device_attribute *devattr,
195 char *buf)
196{
197 return sprintf(buf, "da9052\n");
198}
199
200static ssize_t show_label(struct device *dev, 192static ssize_t show_label(struct device *dev,
201 struct device_attribute *devattr, char *buf) 193 struct device_attribute *devattr, char *buf)
202{ 194{
@@ -243,10 +235,7 @@ static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, da9052_read_tjunc, NULL,
243static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_label, NULL, 235static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_label, NULL,
244 DA9052_ADC_TJUNC); 236 DA9052_ADC_TJUNC);
245 237
246static DEVICE_ATTR(name, S_IRUGO, da9052_hwmon_show_name, NULL); 238static struct attribute *da9052_attrs[] = {
247
248static struct attribute *da9052_attr[] = {
249 &dev_attr_name.attr,
250 &sensor_dev_attr_in0_input.dev_attr.attr, 239 &sensor_dev_attr_in0_input.dev_attr.attr,
251 &sensor_dev_attr_in0_label.dev_attr.attr, 240 &sensor_dev_attr_in0_label.dev_attr.attr,
252 &sensor_dev_attr_in3_input.dev_attr.attr, 241 &sensor_dev_attr_in3_input.dev_attr.attr,
@@ -268,54 +257,29 @@ static struct attribute *da9052_attr[] = {
268 NULL 257 NULL
269}; 258};
270 259
271static const struct attribute_group da9052_attr_group = {.attrs = da9052_attr}; 260ATTRIBUTE_GROUPS(da9052);
272 261
273static int da9052_hwmon_probe(struct platform_device *pdev) 262static int da9052_hwmon_probe(struct platform_device *pdev)
274{ 263{
264 struct device *dev = &pdev->dev;
275 struct da9052_hwmon *hwmon; 265 struct da9052_hwmon *hwmon;
276 int ret; 266 struct device *hwmon_dev;
277 267
278 hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9052_hwmon), 268 hwmon = devm_kzalloc(dev, sizeof(struct da9052_hwmon), GFP_KERNEL);
279 GFP_KERNEL);
280 if (!hwmon) 269 if (!hwmon)
281 return -ENOMEM; 270 return -ENOMEM;
282 271
283 mutex_init(&hwmon->hwmon_lock); 272 mutex_init(&hwmon->hwmon_lock);
284 hwmon->da9052 = dev_get_drvdata(pdev->dev.parent); 273 hwmon->da9052 = dev_get_drvdata(pdev->dev.parent);
285 274
286 platform_set_drvdata(pdev, hwmon); 275 hwmon_dev = devm_hwmon_device_register_with_groups(dev, "da9052",
287 276 hwmon,
288 ret = sysfs_create_group(&pdev->dev.kobj, &da9052_attr_group); 277 da9052_groups);
289 if (ret) 278 return PTR_ERR_OR_ZERO(hwmon_dev);
290 goto err_mem;
291
292 hwmon->class_device = hwmon_device_register(&pdev->dev);
293 if (IS_ERR(hwmon->class_device)) {
294 ret = PTR_ERR(hwmon->class_device);
295 goto err_sysfs;
296 }
297
298 return 0;
299
300err_sysfs:
301 sysfs_remove_group(&pdev->dev.kobj, &da9052_attr_group);
302err_mem:
303 return ret;
304}
305
306static int da9052_hwmon_remove(struct platform_device *pdev)
307{
308 struct da9052_hwmon *hwmon = platform_get_drvdata(pdev);
309
310 hwmon_device_unregister(hwmon->class_device);
311 sysfs_remove_group(&pdev->dev.kobj, &da9052_attr_group);
312
313 return 0;
314} 279}
315 280
316static struct platform_driver da9052_hwmon_driver = { 281static struct platform_driver da9052_hwmon_driver = {
317 .probe = da9052_hwmon_probe, 282 .probe = da9052_hwmon_probe,
318 .remove = da9052_hwmon_remove,
319 .driver = { 283 .driver = {
320 .name = "da9052-hwmon", 284 .name = "da9052-hwmon",
321 .owner = THIS_MODULE, 285 .owner = THIS_MODULE,
diff --git a/drivers/hwmon/da9055-hwmon.c b/drivers/hwmon/da9055-hwmon.c
index 35eb7738d711..9916a3fb4bb9 100644
--- a/drivers/hwmon/da9055-hwmon.c
+++ b/drivers/hwmon/da9055-hwmon.c
@@ -36,7 +36,6 @@
36 36
37struct da9055_hwmon { 37struct da9055_hwmon {
38 struct da9055 *da9055; 38 struct da9055 *da9055;
39 struct device *class_device;
40 struct mutex hwmon_lock; 39 struct mutex hwmon_lock;
41 struct mutex irq_lock; 40 struct mutex irq_lock;
42 struct completion done; 41 struct completion done;
@@ -200,13 +199,6 @@ static ssize_t da9055_read_tjunc(struct device *dev,
200 + 3076332, 10000)); 199 + 3076332, 10000));
201} 200}
202 201
203static ssize_t da9055_hwmon_show_name(struct device *dev,
204 struct device_attribute *devattr,
205 char *buf)
206{
207 return sprintf(buf, "da9055\n");
208}
209
210static ssize_t show_label(struct device *dev, 202static ssize_t show_label(struct device *dev,
211 struct device_attribute *devattr, char *buf) 203 struct device_attribute *devattr, char *buf)
212{ 204{
@@ -236,10 +228,7 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, da9055_read_tjunc, NULL,
236static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, 228static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL,
237 DA9055_ADC_TJUNC); 229 DA9055_ADC_TJUNC);
238 230
239static DEVICE_ATTR(name, S_IRUGO, da9055_hwmon_show_name, NULL); 231static struct attribute *da9055_attrs[] = {
240
241static struct attribute *da9055_attr[] = {
242 &dev_attr_name.attr,
243 &sensor_dev_attr_in0_input.dev_attr.attr, 232 &sensor_dev_attr_in0_input.dev_attr.attr,
244 &sensor_dev_attr_in0_label.dev_attr.attr, 233 &sensor_dev_attr_in0_label.dev_attr.attr,
245 &sensor_dev_attr_in1_input.dev_attr.attr, 234 &sensor_dev_attr_in1_input.dev_attr.attr,
@@ -254,15 +243,16 @@ static struct attribute *da9055_attr[] = {
254 NULL 243 NULL
255}; 244};
256 245
257static const struct attribute_group da9055_attr_group = {.attrs = da9055_attr}; 246ATTRIBUTE_GROUPS(da9055);
258 247
259static int da9055_hwmon_probe(struct platform_device *pdev) 248static int da9055_hwmon_probe(struct platform_device *pdev)
260{ 249{
250 struct device *dev = &pdev->dev;
261 struct da9055_hwmon *hwmon; 251 struct da9055_hwmon *hwmon;
252 struct device *hwmon_dev;
262 int hwmon_irq, ret; 253 int hwmon_irq, ret;
263 254
264 hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9055_hwmon), 255 hwmon = devm_kzalloc(dev, sizeof(struct da9055_hwmon), GFP_KERNEL);
265 GFP_KERNEL);
266 if (!hwmon) 256 if (!hwmon)
267 return -ENOMEM; 257 return -ENOMEM;
268 258
@@ -272,8 +262,6 @@ static int da9055_hwmon_probe(struct platform_device *pdev)
272 init_completion(&hwmon->done); 262 init_completion(&hwmon->done);
273 hwmon->da9055 = dev_get_drvdata(pdev->dev.parent); 263 hwmon->da9055 = dev_get_drvdata(pdev->dev.parent);
274 264
275 platform_set_drvdata(pdev, hwmon);
276
277 hwmon_irq = platform_get_irq_byname(pdev, "HWMON"); 265 hwmon_irq = platform_get_irq_byname(pdev, "HWMON");
278 if (hwmon_irq < 0) 266 if (hwmon_irq < 0)
279 return hwmon_irq; 267 return hwmon_irq;
@@ -288,36 +276,14 @@ static int da9055_hwmon_probe(struct platform_device *pdev)
288 return ret; 276 return ret;
289 } 277 }
290 278
291 ret = sysfs_create_group(&pdev->dev.kobj, &da9055_attr_group); 279 hwmon_dev = devm_hwmon_device_register_with_groups(dev, "da9055",
292 if (ret) 280 hwmon,
293 return ret; 281 da9055_groups);
294 282 return PTR_ERR_OR_ZERO(hwmon_dev);
295 hwmon->class_device = hwmon_device_register(&pdev->dev);
296 if (IS_ERR(hwmon->class_device)) {
297 ret = PTR_ERR(hwmon->class_device);
298 goto err;
299 }
300
301 return 0;
302
303err:
304 sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
305 return ret;
306}
307
308static int da9055_hwmon_remove(struct platform_device *pdev)
309{
310 struct da9055_hwmon *hwmon = platform_get_drvdata(pdev);
311
312 sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
313 hwmon_device_unregister(hwmon->class_device);
314
315 return 0;
316} 283}
317 284
318static struct platform_driver da9055_hwmon_driver = { 285static struct platform_driver da9055_hwmon_driver = {
319 .probe = da9055_hwmon_probe, 286 .probe = da9055_hwmon_probe,
320 .remove = da9055_hwmon_remove,
321 .driver = { 287 .driver = {
322 .name = "da9055-hwmon", 288 .name = "da9055-hwmon",
323 .owner = THIS_MODULE, 289 .owner = THIS_MODULE,
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index f7b46f68ef43..1e7bdcdcb295 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -33,6 +33,9 @@ static bool force;
33module_param(force, bool, 0444); 33module_param(force, bool, 0444);
34MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); 34MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
35 35
36/* Provide lock for writing to NB_SMU_IND_ADDR */
37static DEFINE_MUTEX(nb_smu_ind_mutex);
38
36/* CPUID function 0x80000001, ebx */ 39/* CPUID function 0x80000001, ebx */
37#define CPUID_PKGTYPE_MASK 0xf0000000 40#define CPUID_PKGTYPE_MASK 0xf0000000
38#define CPUID_PKGTYPE_F 0x00000000 41#define CPUID_PKGTYPE_F 0x00000000
@@ -51,13 +54,38 @@ MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
51#define REG_NORTHBRIDGE_CAPABILITIES 0xe8 54#define REG_NORTHBRIDGE_CAPABILITIES 0xe8
52#define NB_CAP_HTC 0x00000400 55#define NB_CAP_HTC 0x00000400
53 56
57/*
58 * For F15h M60h, functionality of REG_REPORTED_TEMPERATURE
59 * has been moved to D0F0xBC_xD820_0CA4 [Reported Temperature
60 * Control]
61 */
62#define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4
63#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573
64
65static void amd_nb_smu_index_read(struct pci_dev *pdev, unsigned int devfn,
66 int offset, u32 *val)
67{
68 mutex_lock(&nb_smu_ind_mutex);
69 pci_bus_write_config_dword(pdev->bus, devfn,
70 0xb8, offset);
71 pci_bus_read_config_dword(pdev->bus, devfn,
72 0xbc, val);
73 mutex_unlock(&nb_smu_ind_mutex);
74}
75
54static ssize_t show_temp(struct device *dev, 76static ssize_t show_temp(struct device *dev,
55 struct device_attribute *attr, char *buf) 77 struct device_attribute *attr, char *buf)
56{ 78{
57 u32 regval; 79 u32 regval;
58 80 struct pci_dev *pdev = dev_get_drvdata(dev);
59 pci_read_config_dword(to_pci_dev(dev), 81
60 REG_REPORTED_TEMPERATURE, &regval); 82 if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model == 0x60) {
83 amd_nb_smu_index_read(pdev, PCI_DEVFN(0, 0),
84 F15H_M60H_REPORTED_TEMP_CTRL_OFFSET,
85 &regval);
86 } else {
87 pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, &regval);
88 }
61 return sprintf(buf, "%u\n", (regval >> 21) * 125); 89 return sprintf(buf, "%u\n", (regval >> 21) * 125);
62} 90}
63 91
@@ -75,7 +103,7 @@ static ssize_t show_temp_crit(struct device *dev,
75 u32 regval; 103 u32 regval;
76 int value; 104 int value;
77 105
78 pci_read_config_dword(to_pci_dev(dev), 106 pci_read_config_dword(dev_get_drvdata(dev),
79 REG_HARDWARE_THERMAL_CONTROL, &regval); 107 REG_HARDWARE_THERMAL_CONTROL, &regval);
80 value = ((regval >> 16) & 0x7f) * 500 + 52000; 108 value = ((regval >> 16) & 0x7f) * 500 + 52000;
81 if (show_hyst) 109 if (show_hyst)
@@ -83,17 +111,43 @@ static ssize_t show_temp_crit(struct device *dev,
83 return sprintf(buf, "%d\n", value); 111 return sprintf(buf, "%d\n", value);
84} 112}
85 113
86static ssize_t show_name(struct device *dev,
87 struct device_attribute *attr, char *buf)
88{
89 return sprintf(buf, "k10temp\n");
90}
91
92static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); 114static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
93static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL); 115static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL);
94static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); 116static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
95static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); 117static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
96static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 118
119static umode_t k10temp_is_visible(struct kobject *kobj,
120 struct attribute *attr, int index)
121{
122 struct device *dev = container_of(kobj, struct device, kobj);
123 struct pci_dev *pdev = dev_get_drvdata(dev);
124
125 if (index >= 2) {
126 u32 reg_caps, reg_htc;
127
128 pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES,
129 &reg_caps);
130 pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL,
131 &reg_htc);
132 if (!(reg_caps & NB_CAP_HTC) || !(reg_htc & HTC_ENABLE))
133 return 0;
134 }
135 return attr->mode;
136}
137
138static struct attribute *k10temp_attrs[] = {
139 &dev_attr_temp1_input.attr,
140 &dev_attr_temp1_max.attr,
141 &sensor_dev_attr_temp1_crit.dev_attr.attr,
142 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
143 NULL
144};
145
146static const struct attribute_group k10temp_group = {
147 .attrs = k10temp_attrs,
148 .is_visible = k10temp_is_visible,
149};
150__ATTRIBUTE_GROUPS(k10temp);
97 151
98static bool has_erratum_319(struct pci_dev *pdev) 152static bool has_erratum_319(struct pci_dev *pdev)
99{ 153{
@@ -132,76 +186,23 @@ static bool has_erratum_319(struct pci_dev *pdev)
132static int k10temp_probe(struct pci_dev *pdev, 186static int k10temp_probe(struct pci_dev *pdev,
133 const struct pci_device_id *id) 187 const struct pci_device_id *id)
134{ 188{
135 struct device *hwmon_dev;
136 u32 reg_caps, reg_htc;
137 int unreliable = has_erratum_319(pdev); 189 int unreliable = has_erratum_319(pdev);
138 int err; 190 struct device *dev = &pdev->dev;
139 191 struct device *hwmon_dev;
140 if (unreliable && !force) {
141 dev_err(&pdev->dev,
142 "unreliable CPU thermal sensor; monitoring disabled\n");
143 err = -ENODEV;
144 goto exit;
145 }
146
147 err = device_create_file(&pdev->dev, &dev_attr_temp1_input);
148 if (err)
149 goto exit;
150 err = device_create_file(&pdev->dev, &dev_attr_temp1_max);
151 if (err)
152 goto exit_remove;
153
154 pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, &reg_caps);
155 pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, &reg_htc);
156 if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) {
157 err = device_create_file(&pdev->dev,
158 &sensor_dev_attr_temp1_crit.dev_attr);
159 if (err)
160 goto exit_remove;
161 err = device_create_file(&pdev->dev,
162 &sensor_dev_attr_temp1_crit_hyst.dev_attr);
163 if (err)
164 goto exit_remove;
165 }
166
167 err = device_create_file(&pdev->dev, &dev_attr_name);
168 if (err)
169 goto exit_remove;
170
171 hwmon_dev = hwmon_device_register(&pdev->dev);
172 if (IS_ERR(hwmon_dev)) {
173 err = PTR_ERR(hwmon_dev);
174 goto exit_remove;
175 }
176 pci_set_drvdata(pdev, hwmon_dev);
177 192
178 if (unreliable && force) 193 if (unreliable) {
179 dev_warn(&pdev->dev, 194 if (!force) {
195 dev_err(dev,
196 "unreliable CPU thermal sensor; monitoring disabled\n");
197 return -ENODEV;
198 }
199 dev_warn(dev,
180 "unreliable CPU thermal sensor; check erratum 319\n"); 200 "unreliable CPU thermal sensor; check erratum 319\n");
181 return 0; 201 }
182
183exit_remove:
184 device_remove_file(&pdev->dev, &dev_attr_name);
185 device_remove_file(&pdev->dev, &dev_attr_temp1_input);
186 device_remove_file(&pdev->dev, &dev_attr_temp1_max);
187 device_remove_file(&pdev->dev,
188 &sensor_dev_attr_temp1_crit.dev_attr);
189 device_remove_file(&pdev->dev,
190 &sensor_dev_attr_temp1_crit_hyst.dev_attr);
191exit:
192 return err;
193}
194 202
195static void k10temp_remove(struct pci_dev *pdev) 203 hwmon_dev = devm_hwmon_device_register_with_groups(dev, "k10temp", pdev,
196{ 204 k10temp_groups);
197 hwmon_device_unregister(pci_get_drvdata(pdev)); 205 return PTR_ERR_OR_ZERO(hwmon_dev);
198 device_remove_file(&pdev->dev, &dev_attr_name);
199 device_remove_file(&pdev->dev, &dev_attr_temp1_input);
200 device_remove_file(&pdev->dev, &dev_attr_temp1_max);
201 device_remove_file(&pdev->dev,
202 &sensor_dev_attr_temp1_crit.dev_attr);
203 device_remove_file(&pdev->dev,
204 &sensor_dev_attr_temp1_crit_hyst.dev_attr);
205} 206}
206 207
207static const struct pci_device_id k10temp_id_table[] = { 208static const struct pci_device_id k10temp_id_table[] = {
@@ -211,6 +212,7 @@ static const struct pci_device_id k10temp_id_table[] = {
211 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, 212 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
212 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, 213 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
213 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) }, 214 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
215 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
214 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, 216 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
215 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, 217 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
216 {} 218 {}
@@ -221,7 +223,6 @@ static struct pci_driver k10temp_driver = {
221 .name = "k10temp", 223 .name = "k10temp",
222 .id_table = k10temp_id_table, 224 .id_table = k10temp_id_table,
223 .probe = k10temp_probe, 225 .probe = k10temp_probe,
224 .remove = k10temp_remove,
225}; 226};
226 227
227module_pci_driver(k10temp_driver); 228module_pci_driver(k10temp_driver);
diff --git a/drivers/hwmon/menf21bmc_hwmon.c b/drivers/hwmon/menf21bmc_hwmon.c
new file mode 100644
index 000000000000..c92229d321c9
--- /dev/null
+++ b/drivers/hwmon/menf21bmc_hwmon.c
@@ -0,0 +1,230 @@
1/*
2 * MEN 14F021P00 Board Management Controller (BMC) hwmon driver.
3 *
4 * This is the core hwmon driver of the MEN 14F021P00 BMC.
5 * The BMC monitors the board voltages which can be access with this
6 * driver through sysfs.
7 *
8 * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/platform_device.h>
19#include <linux/hwmon.h>
20#include <linux/hwmon-sysfs.h>
21#include <linux/jiffies.h>
22#include <linux/slab.h>
23#include <linux/i2c.h>
24
25#define DRV_NAME "menf21bmc_hwmon"
26
27#define BMC_VOLT_COUNT 5
28#define MENF21BMC_V33 0
29#define MENF21BMC_V5 1
30#define MENF21BMC_V12 2
31#define MENF21BMC_V5_SB 3
32#define MENF21BMC_VBAT 4
33
34#define IDX_TO_VOLT_MIN_CMD(idx) (0x40 + idx)
35#define IDX_TO_VOLT_MAX_CMD(idx) (0x50 + idx)
36#define IDX_TO_VOLT_INP_CMD(idx) (0x60 + idx)
37
38struct menf21bmc_hwmon {
39 bool valid;
40 struct i2c_client *i2c_client;
41 unsigned long last_update;
42 int in_val[BMC_VOLT_COUNT];
43 int in_min[BMC_VOLT_COUNT];
44 int in_max[BMC_VOLT_COUNT];
45};
46
47static const char *const input_names[] = {
48 [MENF21BMC_V33] = "MON_3_3V",
49 [MENF21BMC_V5] = "MON_5V",
50 [MENF21BMC_V12] = "MON_12V",
51 [MENF21BMC_V5_SB] = "5V_STANDBY",
52 [MENF21BMC_VBAT] = "VBAT"
53};
54
55static struct menf21bmc_hwmon *menf21bmc_hwmon_update(struct device *dev)
56{
57 int i;
58 int val;
59 struct menf21bmc_hwmon *drv_data = dev_get_drvdata(dev);
60 struct menf21bmc_hwmon *data_ret = drv_data;
61
62 if (time_after(jiffies, drv_data->last_update + HZ)
63 || !drv_data->valid) {
64 for (i = 0; i < BMC_VOLT_COUNT; i++) {
65 val = i2c_smbus_read_word_data(drv_data->i2c_client,
66 IDX_TO_VOLT_INP_CMD(i));
67 if (val < 0) {
68 data_ret = ERR_PTR(val);
69 goto abort;
70 }
71 drv_data->in_val[i] = val;
72 }
73 drv_data->last_update = jiffies;
74 drv_data->valid = true;
75 }
76abort:
77 return data_ret;
78}
79
80static int menf21bmc_hwmon_get_volt_limits(struct menf21bmc_hwmon *drv_data)
81{
82 int i, val;
83
84 for (i = 0; i < BMC_VOLT_COUNT; i++) {
85 val = i2c_smbus_read_word_data(drv_data->i2c_client,
86 IDX_TO_VOLT_MIN_CMD(i));
87 if (val < 0)
88 return val;
89
90 drv_data->in_min[i] = val;
91
92 val = i2c_smbus_read_word_data(drv_data->i2c_client,
93 IDX_TO_VOLT_MAX_CMD(i));
94 if (val < 0)
95 return val;
96
97 drv_data->in_max[i] = val;
98 }
99 return 0;
100}
101
102static ssize_t
103show_label(struct device *dev, struct device_attribute *devattr, char *buf)
104{
105 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
106
107 return sprintf(buf, "%s\n", input_names[attr->index]);
108}
109
110static ssize_t
111show_in(struct device *dev, struct device_attribute *devattr, char *buf)
112{
113 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
114 struct menf21bmc_hwmon *drv_data = menf21bmc_hwmon_update(dev);
115
116 if (IS_ERR(drv_data))
117 return PTR_ERR(drv_data);
118
119 return sprintf(buf, "%d\n", drv_data->in_val[attr->index]);
120}
121
122static ssize_t
123show_min(struct device *dev, struct device_attribute *devattr, char *buf)
124{
125 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
126 struct menf21bmc_hwmon *drv_data = dev_get_drvdata(dev);
127
128 return sprintf(buf, "%d\n", drv_data->in_min[attr->index]);
129}
130
131static ssize_t
132show_max(struct device *dev, struct device_attribute *devattr, char *buf)
133{
134 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
135 struct menf21bmc_hwmon *drv_data = dev_get_drvdata(dev);
136
137 return sprintf(buf, "%d\n", drv_data->in_max[attr->index]);
138}
139
140#define create_voltage_sysfs(idx) \
141static SENSOR_DEVICE_ATTR(in##idx##_input, S_IRUGO, \
142 show_in, NULL, idx); \
143static SENSOR_DEVICE_ATTR(in##idx##_min, S_IRUGO, \
144 show_min, NULL, idx); \
145static SENSOR_DEVICE_ATTR(in##idx##_max, S_IRUGO, \
146 show_max, NULL, idx); \
147static SENSOR_DEVICE_ATTR(in##idx##_label, S_IRUGO, \
148 show_label, NULL, idx);
149
150create_voltage_sysfs(0);
151create_voltage_sysfs(1);
152create_voltage_sysfs(2);
153create_voltage_sysfs(3);
154create_voltage_sysfs(4);
155
156static struct attribute *menf21bmc_hwmon_attrs[] = {
157 &sensor_dev_attr_in0_input.dev_attr.attr,
158 &sensor_dev_attr_in0_min.dev_attr.attr,
159 &sensor_dev_attr_in0_max.dev_attr.attr,
160 &sensor_dev_attr_in0_label.dev_attr.attr,
161
162 &sensor_dev_attr_in1_input.dev_attr.attr,
163 &sensor_dev_attr_in1_min.dev_attr.attr,
164 &sensor_dev_attr_in1_max.dev_attr.attr,
165 &sensor_dev_attr_in1_label.dev_attr.attr,
166
167 &sensor_dev_attr_in2_input.dev_attr.attr,
168 &sensor_dev_attr_in2_min.dev_attr.attr,
169 &sensor_dev_attr_in2_max.dev_attr.attr,
170 &sensor_dev_attr_in2_label.dev_attr.attr,
171
172 &sensor_dev_attr_in3_input.dev_attr.attr,
173 &sensor_dev_attr_in3_min.dev_attr.attr,
174 &sensor_dev_attr_in3_max.dev_attr.attr,
175 &sensor_dev_attr_in3_label.dev_attr.attr,
176
177 &sensor_dev_attr_in4_input.dev_attr.attr,
178 &sensor_dev_attr_in4_min.dev_attr.attr,
179 &sensor_dev_attr_in4_max.dev_attr.attr,
180 &sensor_dev_attr_in4_label.dev_attr.attr,
181 NULL
182};
183
184ATTRIBUTE_GROUPS(menf21bmc_hwmon);
185
186static int menf21bmc_hwmon_probe(struct platform_device *pdev)
187{
188 int ret;
189 struct menf21bmc_hwmon *drv_data;
190 struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent);
191 struct device *hwmon_dev;
192
193 drv_data = devm_kzalloc(&pdev->dev, sizeof(struct menf21bmc_hwmon),
194 GFP_KERNEL);
195 if (!drv_data)
196 return -ENOMEM;
197
198 drv_data->i2c_client = i2c_client;
199
200 ret = menf21bmc_hwmon_get_volt_limits(drv_data);
201 if (ret) {
202 dev_err(&pdev->dev, "failed to read sensor limits");
203 return ret;
204 }
205
206 hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
207 "menf21bmc", drv_data,
208 menf21bmc_hwmon_groups);
209 if (IS_ERR(hwmon_dev))
210 return PTR_ERR(hwmon_dev);
211
212 dev_info(&pdev->dev, "MEN 14F021P00 BMC hwmon device enabled");
213
214 return 0;
215}
216
217static struct platform_driver menf21bmc_hwmon = {
218 .probe = menf21bmc_hwmon_probe,
219 .driver = {
220 .name = DRV_NAME,
221 .owner = THIS_MODULE,
222 },
223};
224
225module_platform_driver(menf21bmc_hwmon);
226
227MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
228MODULE_DESCRIPTION("MEN 14F021P00 BMC hwmon");
229MODULE_LICENSE("GPL v2");
230MODULE_ALIAS("platform:menf21bmc_hwmon");
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index bd410722cd4b..4ff89b2482e4 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -38,6 +38,7 @@
38 38
39#include <linux/hwmon.h> 39#include <linux/hwmon.h>
40#include <linux/hwmon-sysfs.h> 40#include <linux/hwmon-sysfs.h>
41#include <linux/thermal.h>
41 42
42struct ntc_compensation { 43struct ntc_compensation {
43 int temp_c; 44 int temp_c;
@@ -182,6 +183,7 @@ struct ntc_data {
182 struct device *dev; 183 struct device *dev;
183 int n_comp; 184 int n_comp;
184 char name[PLATFORM_NAME_SIZE]; 185 char name[PLATFORM_NAME_SIZE];
186 struct thermal_zone_device *tz;
185}; 187};
186 188
187#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO) 189#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
@@ -428,6 +430,20 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
428 return -EINVAL; 430 return -EINVAL;
429} 431}
430 432
433static int ntc_read_temp(void *dev, long *temp)
434{
435 struct ntc_data *data = dev_get_drvdata(dev);
436 int ohm;
437
438 ohm = ntc_thermistor_get_ohm(data);
439 if (ohm < 0)
440 return ohm;
441
442 *temp = get_temp_mc(data, ohm);
443
444 return 0;
445}
446
431static ssize_t ntc_show_name(struct device *dev, 447static ssize_t ntc_show_name(struct device *dev,
432 struct device_attribute *attr, char *buf) 448 struct device_attribute *attr, char *buf)
433{ 449{
@@ -562,6 +578,13 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
562 dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n", 578 dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
563 pdev_id->name); 579 pdev_id->name);
564 580
581 data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev,
582 ntc_read_temp, NULL);
583 if (IS_ERR(data->tz)) {
584 dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n");
585 data->tz = NULL;
586 }
587
565 return 0; 588 return 0;
566err_after_sysfs: 589err_after_sysfs:
567 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); 590 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
@@ -578,6 +601,8 @@ static int ntc_thermistor_remove(struct platform_device *pdev)
578 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); 601 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
579 ntc_iio_channel_release(pdata); 602 ntc_iio_channel_release(pdata);
580 603
604 thermal_zone_of_sensor_unregister(data->dev, data->tz);
605
581 return 0; 606 return 0;
582} 607}
583 608
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index bd89e87bd6ae..221f0931bf1c 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -100,8 +100,6 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
100 100
101struct smsc47b397_data { 101struct smsc47b397_data {
102 unsigned short addr; 102 unsigned short addr;
103 const char *name;
104 struct device *hwmon_dev;
105 struct mutex lock; 103 struct mutex lock;
106 104
107 struct mutex update_lock; 105 struct mutex update_lock;
@@ -202,15 +200,7 @@ static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
202static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); 200static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
203static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); 201static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
204 202
205static ssize_t show_name(struct device *dev, struct device_attribute 203static struct attribute *smsc47b397_attrs[] = {
206 *devattr, char *buf)
207{
208 struct smsc47b397_data *data = dev_get_drvdata(dev);
209 return sprintf(buf, "%s\n", data->name);
210}
211static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
212
213static struct attribute *smsc47b397_attributes[] = {
214 &sensor_dev_attr_temp1_input.dev_attr.attr, 204 &sensor_dev_attr_temp1_input.dev_attr.attr,
215 &sensor_dev_attr_temp2_input.dev_attr.attr, 205 &sensor_dev_attr_temp2_input.dev_attr.attr,
216 &sensor_dev_attr_temp3_input.dev_attr.attr, 206 &sensor_dev_attr_temp3_input.dev_attr.attr,
@@ -220,23 +210,10 @@ static struct attribute *smsc47b397_attributes[] = {
220 &sensor_dev_attr_fan3_input.dev_attr.attr, 210 &sensor_dev_attr_fan3_input.dev_attr.attr,
221 &sensor_dev_attr_fan4_input.dev_attr.attr, 211 &sensor_dev_attr_fan4_input.dev_attr.attr,
222 212
223 &dev_attr_name.attr,
224 NULL 213 NULL
225}; 214};
226 215
227static const struct attribute_group smsc47b397_group = { 216ATTRIBUTE_GROUPS(smsc47b397);
228 .attrs = smsc47b397_attributes,
229};
230
231static int smsc47b397_remove(struct platform_device *pdev)
232{
233 struct smsc47b397_data *data = platform_get_drvdata(pdev);
234
235 hwmon_device_unregister(data->hwmon_dev);
236 sysfs_remove_group(&pdev->dev.kobj, &smsc47b397_group);
237
238 return 0;
239}
240 217
241static int smsc47b397_probe(struct platform_device *pdev); 218static int smsc47b397_probe(struct platform_device *pdev);
242 219
@@ -246,15 +223,14 @@ static struct platform_driver smsc47b397_driver = {
246 .name = DRVNAME, 223 .name = DRVNAME,
247 }, 224 },
248 .probe = smsc47b397_probe, 225 .probe = smsc47b397_probe,
249 .remove = smsc47b397_remove,
250}; 226};
251 227
252static int smsc47b397_probe(struct platform_device *pdev) 228static int smsc47b397_probe(struct platform_device *pdev)
253{ 229{
254 struct device *dev = &pdev->dev; 230 struct device *dev = &pdev->dev;
255 struct smsc47b397_data *data; 231 struct smsc47b397_data *data;
232 struct device *hwmon_dev;
256 struct resource *res; 233 struct resource *res;
257 int err = 0;
258 234
259 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 235 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
260 if (!devm_request_region(dev, res->start, SMSC_EXTENT, 236 if (!devm_request_region(dev, res->start, SMSC_EXTENT,
@@ -270,26 +246,13 @@ static int smsc47b397_probe(struct platform_device *pdev)
270 return -ENOMEM; 246 return -ENOMEM;
271 247
272 data->addr = res->start; 248 data->addr = res->start;
273 data->name = "smsc47b397";
274 mutex_init(&data->lock); 249 mutex_init(&data->lock);
275 mutex_init(&data->update_lock); 250 mutex_init(&data->update_lock);
276 platform_set_drvdata(pdev, data);
277
278 err = sysfs_create_group(&dev->kobj, &smsc47b397_group);
279 if (err)
280 return err;
281 251
282 data->hwmon_dev = hwmon_device_register(dev); 252 hwmon_dev = devm_hwmon_device_register_with_groups(dev, "smsc47b397",
283 if (IS_ERR(data->hwmon_dev)) { 253 data,
284 err = PTR_ERR(data->hwmon_dev); 254 smsc47b397_groups);
285 goto error_remove; 255 return PTR_ERR_OR_ZERO(hwmon_dev);
286 }
287
288 return 0;
289
290error_remove:
291 sysfs_remove_group(&dev->kobj, &smsc47b397_group);
292 return err;
293} 256}
294 257
295static int __init smsc47b397_device_add(unsigned short address) 258static int __init smsc47b397_device_add(unsigned short address)
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 90e108f9e22e..a210338cfeb1 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -468,6 +468,15 @@ config LEDS_OT200
468 This option enables support for the LEDs on the Bachmann OT200. 468 This option enables support for the LEDs on the Bachmann OT200.
469 Say Y to enable LEDs on the Bachmann OT200. 469 Say Y to enable LEDs on the Bachmann OT200.
470 470
471config LEDS_MENF21BMC
472 tristate "LED support for the MEN 14F021P00 BMC"
473 depends on LEDS_CLASS && MFD_MENF21BMC
474 help
475 Say Y here to include support for the MEN 14F021P00 BMC LEDs.
476
477 This driver can also be built as a module. If so the module
478 will be called leds-menf21bmc.
479
471comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" 480comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)"
472 481
473config LEDS_BLINKM 482config LEDS_BLINKM
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 822dd83ef97a..a2b164741465 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o
55obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o 55obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
56obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o 56obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o
57obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o 57obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o
58obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o
58 59
59# LED SPI Drivers 60# LED SPI Drivers
60obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 61obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-menf21bmc.c b/drivers/leds/leds-menf21bmc.c
new file mode 100644
index 000000000000..89dd57769e3b
--- /dev/null
+++ b/drivers/leds/leds-menf21bmc.c
@@ -0,0 +1,131 @@
1/*
2 * MEN 14F021P00 Board Management Controller (BMC) LEDs Driver.
3 *
4 * This is the core LED driver of the MEN 14F021P00 BMC.
5 * There are four LEDs available which can be switched on and off.
6 * STATUS LED, HOT SWAP LED, USER LED 1, USER LED 2
7 *
8 * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/platform_device.h>
19#include <linux/leds.h>
20#include <linux/i2c.h>
21
22#define BMC_CMD_LED_GET_SET 0xA0
23#define BMC_BIT_LED_STATUS BIT(0)
24#define BMC_BIT_LED_HOTSWAP BIT(1)
25#define BMC_BIT_LED_USER1 BIT(2)
26#define BMC_BIT_LED_USER2 BIT(3)
27
28struct menf21bmc_led {
29 struct led_classdev cdev;
30 u8 led_bit;
31 const char *name;
32 struct i2c_client *i2c_client;
33};
34
35static struct menf21bmc_led leds[] = {
36 {
37 .name = "menf21bmc:led_status",
38 .led_bit = BMC_BIT_LED_STATUS,
39 },
40 {
41 .name = "menf21bmc:led_hotswap",
42 .led_bit = BMC_BIT_LED_HOTSWAP,
43 },
44 {
45 .name = "menf21bmc:led_user1",
46 .led_bit = BMC_BIT_LED_USER1,
47 },
48 {
49 .name = "menf21bmc:led_user2",
50 .led_bit = BMC_BIT_LED_USER2,
51 }
52};
53
54static DEFINE_MUTEX(led_lock);
55
56static void
57menf21bmc_led_set(struct led_classdev *led_cdev, enum led_brightness value)
58{
59 int led_val;
60 struct menf21bmc_led *led = container_of(led_cdev,
61 struct menf21bmc_led, cdev);
62
63 mutex_lock(&led_lock);
64 led_val = i2c_smbus_read_byte_data(led->i2c_client,
65 BMC_CMD_LED_GET_SET);
66 if (led_val < 0)
67 goto err_out;
68
69 if (value == LED_OFF)
70 led_val &= ~led->led_bit;
71 else
72 led_val |= led->led_bit;
73
74 i2c_smbus_write_byte_data(led->i2c_client,
75 BMC_CMD_LED_GET_SET, led_val);
76err_out:
77 mutex_unlock(&led_lock);
78}
79
80static int menf21bmc_led_probe(struct platform_device *pdev)
81{
82 int i;
83 int ret;
84 struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent);
85
86 for (i = 0; i < ARRAY_SIZE(leds); i++) {
87 leds[i].cdev.name = leds[i].name;
88 leds[i].cdev.brightness_set = menf21bmc_led_set;
89 leds[i].i2c_client = i2c_client;
90 ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
91 if (ret < 0)
92 goto err_free_leds;
93 }
94 dev_info(&pdev->dev, "MEN 140F21P00 BMC LED device enabled\n");
95
96 return 0;
97
98err_free_leds:
99 dev_err(&pdev->dev, "failed to register LED device\n");
100
101 for (i = i - 1; i >= 0; i--)
102 led_classdev_unregister(&leds[i].cdev);
103
104 return ret;
105}
106
107static int menf21bmc_led_remove(struct platform_device *pdev)
108{
109 int i;
110
111 for (i = 0; i < ARRAY_SIZE(leds); i++)
112 led_classdev_unregister(&leds[i].cdev);
113
114 return 0;
115}
116
117static struct platform_driver menf21bmc_led = {
118 .probe = menf21bmc_led_probe,
119 .remove = menf21bmc_led_remove,
120 .driver = {
121 .name = "menf21bmc_led",
122 .owner = THIS_MODULE,
123 },
124};
125
126module_platform_driver(menf21bmc_led);
127
128MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
129MODULE_DESCRIPTION("MEN 14F021P00 BMC led driver");
130MODULE_LICENSE("GPL v2");
131MODULE_ALIAS("platform:menf21bmc_led");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index de5abf244746..cf66ef1ffaf3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -454,6 +454,21 @@ config MFD_MAX8998
454 additional drivers must be enabled in order to use the functionality 454 additional drivers must be enabled in order to use the functionality
455 of the device. 455 of the device.
456 456
457config MFD_MENF21BMC
458 tristate "MEN 14F021P00 Board Management Controller Support"
459 depends on I2C
460 select MFD_CORE
461 help
462 Say yes here to add support for the MEN 14F021P00 BMC
463 which is a Board Management Controller connected to the I2C bus.
464 The device supports multiple sub-devices like LED, HWMON and WDT.
465 This driver provides common support for accessing the devices;
466 additional drivers must be enabled in order to use the
467 functionality of the BMC device.
468
469 This driver can also be built as a module. If so the module
470 will be called menf21bmc.
471
457config EZX_PCAP 472config EZX_PCAP
458 bool "Motorola EZXPCAP Support" 473 bool "Motorola EZXPCAP Support"
459 depends on SPI_MASTER 474 depends on SPI_MASTER
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f00148782d9b..d58068aa8aa9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -169,6 +169,7 @@ obj-$(CONFIG_MFD_AS3711) += as3711.o
169obj-$(CONFIG_MFD_AS3722) += as3722.o 169obj-$(CONFIG_MFD_AS3722) += as3722.o
170obj-$(CONFIG_MFD_STW481X) += stw481x.o 170obj-$(CONFIG_MFD_STW481X) += stw481x.o
171obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o 171obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
172obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
172 173
173intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o 174intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
174obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o 175obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c
new file mode 100644
index 000000000000..1c274345820c
--- /dev/null
+++ b/drivers/mfd/menf21bmc.c
@@ -0,0 +1,132 @@
1/*
2 * MEN 14F021P00 Board Management Controller (BMC) MFD Core Driver.
3 *
4 * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/device.h>
14#include <linux/module.h>
15#include <linux/i2c.h>
16#include <linux/mfd/core.h>
17
18#define BMC_CMD_WDT_EXIT_PROD 0x18
19#define BMC_CMD_WDT_PROD_STAT 0x19
20#define BMC_CMD_REV_MAJOR 0x80
21#define BMC_CMD_REV_MINOR 0x81
22#define BMC_CMD_REV_MAIN 0x82
23
24static struct mfd_cell menf21bmc_cell[] = {
25 { .name = "menf21bmc_wdt", },
26 { .name = "menf21bmc_led", },
27 { .name = "menf21bmc_hwmon", }
28};
29
30static int menf21bmc_wdt_exit_prod_mode(struct i2c_client *client)
31{
32 int val, ret;
33
34 val = i2c_smbus_read_byte_data(client, BMC_CMD_WDT_PROD_STAT);
35 if (val < 0)
36 return val;
37
38 /*
39 * Production mode should be not active after delivery of the Board.
40 * To be sure we check it, inform the user and exit the mode
41 * if active.
42 */
43 if (val == 0x00) {
44 dev_info(&client->dev,
45 "BMC in production mode. Exit production mode\n");
46
47 ret = i2c_smbus_write_byte(client, BMC_CMD_WDT_EXIT_PROD);
48 if (ret < 0)
49 return ret;
50 }
51
52 return 0;
53}
54
55static int
56menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids)
57{
58 int rev_major, rev_minor, rev_main;
59 int ret;
60
61 ret = i2c_check_functionality(client->adapter,
62 I2C_FUNC_SMBUS_BYTE_DATA |
63 I2C_FUNC_SMBUS_WORD_DATA |
64 I2C_FUNC_SMBUS_BYTE);
65 if (!ret)
66 return -ENODEV;
67
68 rev_major = i2c_smbus_read_word_data(client, BMC_CMD_REV_MAJOR);
69 if (rev_major < 0) {
70 dev_err(&client->dev, "failed to get BMC major revision\n");
71 return rev_major;
72 }
73
74 rev_minor = i2c_smbus_read_word_data(client, BMC_CMD_REV_MINOR);
75 if (rev_minor < 0) {
76 dev_err(&client->dev, "failed to get BMC minor revision\n");
77 return rev_minor;
78 }
79
80 rev_main = i2c_smbus_read_word_data(client, BMC_CMD_REV_MAIN);
81 if (rev_main < 0) {
82 dev_err(&client->dev, "failed to get BMC main revision\n");
83 return rev_main;
84 }
85
86 dev_info(&client->dev, "FW Revision: %02d.%02d.%02d\n",
87 rev_major, rev_minor, rev_main);
88
89 /*
90 * We have to exit the Production Mode of the BMC to activate the
91 * Watchdog functionality and the BIOS life sign monitoring.
92 */
93 ret = menf21bmc_wdt_exit_prod_mode(client);
94 if (ret < 0) {
95 dev_err(&client->dev, "failed to leave production mode\n");
96 return ret;
97 }
98
99 ret = mfd_add_devices(&client->dev, 0, menf21bmc_cell,
100 ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL);
101 if (ret < 0) {
102 dev_err(&client->dev, "failed to add BMC sub-devices\n");
103 return ret;
104 }
105
106 return 0;
107}
108
109static int menf21bmc_remove(struct i2c_client *client)
110{
111 mfd_remove_devices(&client->dev);
112 return 0;
113}
114
115static const struct i2c_device_id menf21bmc_id_table[] = {
116 { "menf21bmc" },
117 { }
118};
119MODULE_DEVICE_TABLE(i2c, menf21bmc_id_table);
120
121static struct i2c_driver menf21bmc_driver = {
122 .driver.name = "menf21bmc",
123 .id_table = menf21bmc_id_table,
124 .probe = menf21bmc_probe,
125 .remove = menf21bmc_remove,
126};
127
128module_i2c_driver(menf21bmc_driver);
129
130MODULE_DESCRIPTION("MEN 14F021P00 BMC mfd core driver");
131MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
132MODULE_LICENSE("GPL v2");
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 1d1330a78af3..e3d5bf0a5021 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -95,6 +95,16 @@ config GPIO_WATCHDOG
95 If you say yes here you get support for watchdog device 95 If you say yes here you get support for watchdog device
96 controlled through GPIO-line. 96 controlled through GPIO-line.
97 97
98config MENF21BMC_WATCHDOG
99 tristate "MEN 14F021P00 BMC Watchdog"
100 depends on MFD_MENF21BMC
101 select WATCHDOG_CORE
102 help
103 Say Y here to include support for the MEN 14F021P00 BMC Watchdog.
104
105 This driver can also be built as a module. If so the module
106 will be called menf21bmc_wdt.
107
98config WM831X_WATCHDOG 108config WM831X_WATCHDOG
99 tristate "WM831x watchdog" 109 tristate "WM831x watchdog"
100 depends on MFD_WM831X 110 depends on MFD_WM831X
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 468c3204c3b1..de1701470c14 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -178,3 +178,4 @@ obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
178obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o 178obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
179obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o 179obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
180obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o 180obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
181obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
diff --git a/drivers/watchdog/menf21bmc_wdt.c b/drivers/watchdog/menf21bmc_wdt.c
new file mode 100644
index 000000000000..2042874d5ce3
--- /dev/null
+++ b/drivers/watchdog/menf21bmc_wdt.c
@@ -0,0 +1,203 @@
1/*
2 * MEN 14F021P00 Board Management Controller (BMC) Watchdog Driver.
3 *
4 * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/device.h>
14#include <linux/module.h>
15#include <linux/watchdog.h>
16#include <linux/platform_device.h>
17#include <linux/i2c.h>
18
19#define DEVNAME "menf21bmc_wdt"
20
21#define BMC_CMD_WD_ON 0x11
22#define BMC_CMD_WD_OFF 0x12
23#define BMC_CMD_WD_TRIG 0x13
24#define BMC_CMD_WD_TIME 0x14
25#define BMC_CMD_WD_STATE 0x17
26#define BMC_WD_OFF_VAL 0x69
27#define BMC_CMD_RST_RSN 0x92
28
29#define BMC_WD_TIMEOUT_MIN 1 /* in sec */
30#define BMC_WD_TIMEOUT_MAX 6553 /* in sec */
31
32static bool nowayout = WATCHDOG_NOWAYOUT;
33module_param(nowayout, bool, 0);
34MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
35 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
36
37struct menf21bmc_wdt {
38 struct watchdog_device wdt;
39 struct i2c_client *i2c_client;
40};
41
42static int menf21bmc_wdt_set_bootstatus(struct menf21bmc_wdt *data)
43{
44 int rst_rsn;
45
46 rst_rsn = i2c_smbus_read_byte_data(data->i2c_client, BMC_CMD_RST_RSN);
47 if (rst_rsn < 0)
48 return rst_rsn;
49
50 if (rst_rsn == 0x02)
51 data->wdt.bootstatus |= WDIOF_CARDRESET;
52 else if (rst_rsn == 0x05)
53 data->wdt.bootstatus |= WDIOF_EXTERN1;
54 else if (rst_rsn == 0x06)
55 data->wdt.bootstatus |= WDIOF_EXTERN2;
56 else if (rst_rsn == 0x0A)
57 data->wdt.bootstatus |= WDIOF_POWERUNDER;
58
59 return 0;
60}
61
62static int menf21bmc_wdt_start(struct watchdog_device *wdt)
63{
64 struct menf21bmc_wdt *drv_data = watchdog_get_drvdata(wdt);
65
66 return i2c_smbus_write_byte(drv_data->i2c_client, BMC_CMD_WD_ON);
67}
68
69static int menf21bmc_wdt_stop(struct watchdog_device *wdt)
70{
71 struct menf21bmc_wdt *drv_data = watchdog_get_drvdata(wdt);
72
73 return i2c_smbus_write_byte_data(drv_data->i2c_client,
74 BMC_CMD_WD_OFF, BMC_WD_OFF_VAL);
75}
76
77static int
78menf21bmc_wdt_settimeout(struct watchdog_device *wdt, unsigned int timeout)
79{
80 int ret;
81 struct menf21bmc_wdt *drv_data = watchdog_get_drvdata(wdt);
82
83 /*
84 * BMC Watchdog does have a resolution of 100ms.
85 * Watchdog API defines the timeout in seconds, so we have to
86 * multiply the value.
87 */
88 ret = i2c_smbus_write_word_data(drv_data->i2c_client,
89 BMC_CMD_WD_TIME, timeout * 10);
90 if (ret < 0)
91 return ret;
92
93 wdt->timeout = timeout;
94
95 return 0;
96}
97
98static int menf21bmc_wdt_ping(struct watchdog_device *wdt)
99{
100 struct menf21bmc_wdt *drv_data = watchdog_get_drvdata(wdt);
101
102 return i2c_smbus_write_byte(drv_data->i2c_client, BMC_CMD_WD_TRIG);
103}
104
105static const struct watchdog_info menf21bmc_wdt_info = {
106 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
107 .identity = DEVNAME,
108};
109
110static const struct watchdog_ops menf21bmc_wdt_ops = {
111 .owner = THIS_MODULE,
112 .start = menf21bmc_wdt_start,
113 .stop = menf21bmc_wdt_stop,
114 .ping = menf21bmc_wdt_ping,
115 .set_timeout = menf21bmc_wdt_settimeout,
116};
117
118static int menf21bmc_wdt_probe(struct platform_device *pdev)
119{
120 int ret, bmc_timeout;
121 struct menf21bmc_wdt *drv_data;
122 struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent);
123
124 drv_data = devm_kzalloc(&pdev->dev,
125 sizeof(struct menf21bmc_wdt), GFP_KERNEL);
126 if (!drv_data)
127 return -ENOMEM;
128
129 drv_data->wdt.ops = &menf21bmc_wdt_ops;
130 drv_data->wdt.info = &menf21bmc_wdt_info;
131 drv_data->wdt.min_timeout = BMC_WD_TIMEOUT_MIN;
132 drv_data->wdt.max_timeout = BMC_WD_TIMEOUT_MAX;
133 drv_data->i2c_client = i2c_client;
134
135 /*
136 * Get the current wdt timeout value from the BMC because
137 * the BMC will save the value set before if the system restarts.
138 */
139 bmc_timeout = i2c_smbus_read_word_data(drv_data->i2c_client,
140 BMC_CMD_WD_TIME);
141 if (bmc_timeout < 0) {
142 dev_err(&pdev->dev, "failed to get current WDT timeout\n");
143 return bmc_timeout;
144 }
145
146 watchdog_init_timeout(&drv_data->wdt, bmc_timeout / 10, &pdev->dev);
147 watchdog_set_nowayout(&drv_data->wdt, nowayout);
148 watchdog_set_drvdata(&drv_data->wdt, drv_data);
149 platform_set_drvdata(pdev, drv_data);
150
151 ret = menf21bmc_wdt_set_bootstatus(drv_data);
152 if (ret < 0) {
153 dev_err(&pdev->dev, "failed to set Watchdog bootstatus\n");
154 return ret;
155 }
156
157 ret = watchdog_register_device(&drv_data->wdt);
158 if (ret) {
159 dev_err(&pdev->dev, "failed to register Watchdog device\n");
160 return ret;
161 }
162
163 dev_info(&pdev->dev, "MEN 14F021P00 BMC Watchdog device enabled\n");
164
165 return 0;
166}
167
168static int menf21bmc_wdt_remove(struct platform_device *pdev)
169{
170 struct menf21bmc_wdt *drv_data = platform_get_drvdata(pdev);
171
172 dev_warn(&pdev->dev,
173 "Unregister MEN 14F021P00 BMC Watchdog device, board may reset\n");
174
175 watchdog_unregister_device(&drv_data->wdt);
176
177 return 0;
178}
179
180static void menf21bmc_wdt_shutdown(struct platform_device *pdev)
181{
182 struct menf21bmc_wdt *drv_data = platform_get_drvdata(pdev);
183
184 i2c_smbus_write_word_data(drv_data->i2c_client,
185 BMC_CMD_WD_OFF, BMC_WD_OFF_VAL);
186}
187
188static struct platform_driver menf21bmc_wdt = {
189 .driver = {
190 .owner = THIS_MODULE,
191 .name = DEVNAME,
192 },
193 .probe = menf21bmc_wdt_probe,
194 .remove = menf21bmc_wdt_remove,
195 .shutdown = menf21bmc_wdt_shutdown,
196};
197
198module_platform_driver(menf21bmc_wdt);
199
200MODULE_DESCRIPTION("MEN 14F021P00 BMC Watchdog driver");
201MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
202MODULE_LICENSE("GPL v2");
203MODULE_ALIAS("platform:menf21bmc_wdt");