summaryrefslogtreecommitdiff
path: root/drivers/hwmon/lm87.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/lm87.c')
-rw-r--r--drivers/hwmon/lm87.c429
1 files changed, 213 insertions, 216 deletions
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 16e45d702152..37bf2d1d3d09 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* lm87.c
*
@@ -5,7 +6,7 @@
* Philip Edelbrock <phil@netroedge.com>
* Stephen Rousset <stephen.rousset@rocketlogix.com>
* Dan Eaton <dan.eaton@rocketlogix.com>
- * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2008 Jean Delvare <jdelvare@suse.de>
*
* Original port to Linux 2.6 by Jeff Oliver.
*
@@ -39,21 +40,7 @@
* This driver also supports the ADM1024, a sensor chip made by Analog
* Devices. That chip is fully compatible with the LM87. Complete
* datasheet can be obtained from Analog's website at:
- * http://www.analog.com/en/prod/0,2877,ADM1024,00.html
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * https://www.analog.com/en/prod/0,2877,ADM1024,00.html
*/
#include <linux/module.h>
@@ -66,6 +53,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
/*
* Addresses to scan
@@ -74,8 +62,6 @@
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-enum chips { lm87, adm1024 };
-
/*
* The LM87 registers
*/
@@ -121,7 +107,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
#define IN_FROM_REG(reg, scale) (((reg) * (scale) + 96) / 192)
#define IN_TO_REG(val, scale) ((val) <= 0 ? 0 : \
- (val) * 192 >= (scale) * 255 ? 255 : \
+ (val) >= (scale) * 255 / 192 ? 255 : \
((val) * 192 + (scale) / 2) / (scale))
#define TEMP_FROM_REG(reg) ((reg) * 1000)
@@ -130,8 +116,14 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
(((val) < 0 ? (val) - 500 : \
(val) + 500) / 1000))
-#define FAN_FROM_REG(reg, div) ((reg) == 255 || (reg) == 0 ? 0 : \
- (1350000 + (reg)*(div) / 2) / ((reg) * (div)))
+static int fan_from_reg(int reg, int div)
+{
+ if (reg == 255 || reg == 0)
+ return 0;
+
+ return (1350000 + reg * div / 2) / (reg * div);
+}
+
#define FAN_TO_REG(val, div) ((val) * (div) * 255 <= 1350000 ? 255 : \
(1350000 + (val)*(div) / 2) / ((val) * (div)))
@@ -154,9 +146,8 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
*/
struct lm87_data {
- struct device *hwmon_dev;
struct mutex update_lock;
- char valid; /* zero until following fields are valid */
+ bool valid; /* false until following fields are valid */
unsigned long last_updated; /* In jiffies */
u8 channel; /* register value */
@@ -181,6 +172,8 @@ struct lm87_data {
u16 alarms; /* register values, combined */
u8 vid; /* register values, combined */
u8 vrm;
+
+ const struct attribute_group *attr_groups[6];
};
static inline int lm87_read_value(struct i2c_client *client, u8 reg)
@@ -195,7 +188,7 @@ static inline int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
static struct lm87_data *lm87_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
@@ -264,7 +257,7 @@ static struct lm87_data *lm87_update_device(struct device *dev)
data->aout = lm87_read_value(client, LM87_REG_AOUT);
data->last_updated = jiffies;
- data->valid = 1;
+ data->valid = true;
}
mutex_unlock(&data->update_lock);
@@ -276,8 +269,8 @@ static struct lm87_data *lm87_update_device(struct device *dev)
* Sysfs stuff
*/
-static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t in_input_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int nr = to_sensor_dev_attr(attr)->index;
@@ -286,8 +279,8 @@ static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
data->in_scale[nr]));
}
-static ssize_t show_in_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t in_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int nr = to_sensor_dev_attr(attr)->index;
@@ -296,8 +289,8 @@ static ssize_t show_in_min(struct device *dev,
data->in_scale[nr]));
}
-static ssize_t show_in_max(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t in_max_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int nr = to_sensor_dev_attr(attr)->index;
@@ -306,10 +299,10 @@ static ssize_t show_in_max(struct device *dev,
data->in_scale[nr]));
}
-static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t in_min_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
long val;
@@ -327,10 +320,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t in_max_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
long val;
@@ -348,23 +341,32 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
return count;
}
-#define set_in(offset) \
-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
- show_in_input, NULL, offset); \
-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
- show_in_min, set_in_min, offset); \
-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
- show_in_max, set_in_max, offset)
-set_in(0);
-set_in(1);
-set_in(2);
-set_in(3);
-set_in(4);
-set_in(5);
-set_in(6);
-set_in(7);
-
-static ssize_t show_temp_input(struct device *dev,
+static SENSOR_DEVICE_ATTR_RO(in0_input, in_input, 0);
+static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
+static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_input, in_input, 1);
+static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
+static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, in_input, 2);
+static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
+static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_input, in_input, 3);
+static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
+static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_input, in_input, 4);
+static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
+static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
+static SENSOR_DEVICE_ATTR_RO(in5_input, in_input, 5);
+static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5);
+static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5);
+static SENSOR_DEVICE_ATTR_RO(in6_input, in_input, 6);
+static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6);
+static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6);
+static SENSOR_DEVICE_ATTR_RO(in7_input, in_input, 7);
+static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 7);
+static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 7);
+
+static ssize_t temp_input_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
@@ -373,7 +375,7 @@ static ssize_t show_temp_input(struct device *dev,
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
}
-static ssize_t show_temp_low(struct device *dev,
+static ssize_t temp_low_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
@@ -383,7 +385,7 @@ static ssize_t show_temp_low(struct device *dev,
TEMP_FROM_REG(data->temp_low[nr]));
}
-static ssize_t show_temp_high(struct device *dev,
+static ssize_t temp_high_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
@@ -393,10 +395,11 @@ static ssize_t show_temp_high(struct device *dev,
TEMP_FROM_REG(data->temp_high[nr]));
}
-static ssize_t set_temp_low(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_low_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
long val;
@@ -413,10 +416,11 @@ static ssize_t set_temp_low(struct device *dev, struct device_attribute *attr,
return count;
}
-static ssize_t set_temp_high(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t temp_high_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
long val;
@@ -433,57 +437,56 @@ static ssize_t set_temp_high(struct device *dev, struct device_attribute *attr,
return count;
}
-#define set_temp(offset) \
-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp_input, NULL, offset - 1); \
-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
- show_temp_high, set_temp_high, offset - 1); \
-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
- show_temp_low, set_temp_low, offset - 1)
-set_temp(1);
-set_temp(2);
-set_temp(3);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_low, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_high, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
+static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_low, 1);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_high, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp_input, 2);
+static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_low, 2);
+static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_high, 2);
-static ssize_t show_temp_crit_int(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp1_crit_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_int));
}
-static ssize_t show_temp_crit_ext(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t temp2_crit_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_ext));
}
-static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit_int, NULL);
-static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit_ext, NULL);
-static DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit_ext, NULL);
+static DEVICE_ATTR_RO(temp1_crit);
+static DEVICE_ATTR_RO(temp2_crit);
+static DEVICE_ATTR(temp3_crit, 0444, temp2_crit_show, NULL);
-static ssize_t show_fan_input(struct device *dev,
+static ssize_t fan_input_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int nr = to_sensor_dev_attr(attr)->index;
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+ return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr],
FAN_DIV_FROM_REG(data->fan_div[nr])));
}
-static ssize_t show_fan_min(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int nr = to_sensor_dev_attr(attr)->index;
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+ return sprintf(buf, "%d\n", fan_from_reg(data->fan_min[nr],
FAN_DIV_FROM_REG(data->fan_div[nr])));
}
-static ssize_t show_fan_div(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int nr = to_sensor_dev_attr(attr)->index;
@@ -492,10 +495,11 @@ static ssize_t show_fan_div(struct device *dev,
FAN_DIV_FROM_REG(data->fan_div[nr]));
}
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_min_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
long val;
@@ -519,10 +523,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
* of least surprise; the user doesn't expect the fan minimum to change just
* because the divider changed.
*/
-static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fan_div_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
long val;
@@ -535,7 +540,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
return err;
mutex_lock(&data->update_lock);
- min = FAN_FROM_REG(data->fan_min[nr],
+ min = fan_from_reg(data->fan_min[nr],
FAN_DIV_FROM_REG(data->fan_div[nr]));
switch (val) {
@@ -575,40 +580,37 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
return count;
}
-#define set_fan(offset) \
-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
- show_fan_input, NULL, offset - 1); \
-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
- show_fan_min, set_fan_min, offset - 1); \
-static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
- show_fan_div, set_fan_div, offset - 1)
-set_fan(1);
-set_fan(2);
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
}
-static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static DEVICE_ATTR_RO(alarms);
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t cpu0_vid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
}
-static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR_RO(cpu0_vid);
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+static ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm87_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", data->vrm);
}
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct lm87_data *data = dev_get_drvdata(dev);
unsigned long val;
@@ -617,21 +619,26 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
err = kstrtoul(buf, 10, &val);
if (err)
return err;
+
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+static DEVICE_ATTR_RW(vrm);
-static ssize_t show_aout(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t aout_output_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
}
-static ssize_t set_aout(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t aout_output_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = dev_get_drvdata(dev);
struct lm87_data *data = i2c_get_clientdata(client);
long val;
int err;
@@ -646,30 +653,30 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr,
mutex_unlock(&data->update_lock);
return count;
}
-static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
+static DEVICE_ATTR_RW(aout_output);
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
int bitnr = to_sensor_dev_attr(attr)->index;
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
-static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
-static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
-static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
-static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 5);
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 14);
-static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
+static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8);
+static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 9);
+static SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(in7_alarm, alarm, 7);
+static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4);
+static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 5);
+static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6);
+static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7);
+static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 14);
+static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 15);
/*
* Real code
@@ -832,31 +839,44 @@ static int lm87_detect(struct i2c_client *client, struct i2c_board_info *info)
return -ENODEV;
}
- strlcpy(info->type, name, I2C_NAME_SIZE);
+ strscpy(info->type, name, I2C_NAME_SIZE);
return 0;
}
-static void lm87_remove_files(struct i2c_client *client)
+static void lm87_restore_config(void *arg)
{
- struct device *dev = &client->dev;
+ struct i2c_client *client = arg;
+ struct lm87_data *data = i2c_get_clientdata(client);
- sysfs_remove_group(&dev->kobj, &lm87_group);
- sysfs_remove_group(&dev->kobj, &lm87_group_in6);
- sysfs_remove_group(&dev->kobj, &lm87_group_fan1);
- sysfs_remove_group(&dev->kobj, &lm87_group_in7);
- sysfs_remove_group(&dev->kobj, &lm87_group_fan2);
- sysfs_remove_group(&dev->kobj, &lm87_group_temp3);
- sysfs_remove_group(&dev->kobj, &lm87_group_in0_5);
- sysfs_remove_group(&dev->kobj, &lm87_group_vid);
+ lm87_write_value(client, LM87_REG_CONFIG, data->config);
}
-static void lm87_init_client(struct i2c_client *client)
+static int lm87_init_client(struct i2c_client *client)
{
struct lm87_data *data = i2c_get_clientdata(client);
-
- if (client->dev.platform_data) {
- data->channel = *(u8 *)client->dev.platform_data;
+ int rc;
+ struct device_node *of_node = client->dev.of_node;
+ u8 val = 0;
+ struct regulator *vcc = NULL;
+
+ if (of_node) {
+ if (of_property_read_bool(of_node, "has-temp3"))
+ val |= CHAN_TEMP3;
+ if (of_property_read_bool(of_node, "has-in6"))
+ val |= CHAN_NO_FAN(0);
+ if (of_property_read_bool(of_node, "has-in7"))
+ val |= CHAN_NO_FAN(1);
+ vcc = devm_regulator_get_optional(&client->dev, "vcc");
+ if (!IS_ERR(vcc)) {
+ if (regulator_get_voltage(vcc) == 5000000)
+ val |= CHAN_VCC_5V;
+ }
+ data->channel = val;
+ lm87_write_value(client,
+ LM87_REG_CHANNEL_MODE, data->channel);
+ } else if (dev_get_platdata(&client->dev)) {
+ data->channel = *(u8 *)dev_get_platdata(&client->dev);
lm87_write_value(client,
LM87_REG_CHANNEL_MODE, data->channel);
} else {
@@ -864,6 +884,10 @@ static void lm87_init_client(struct i2c_client *client)
}
data->config = lm87_read_value(client, LM87_REG_CONFIG) & 0x6F;
+ rc = devm_add_action(&client->dev, lm87_restore_config, client);
+ if (rc)
+ return rc;
+
if (!(data->config & 0x01)) {
int i;
@@ -891,23 +915,27 @@ static void lm87_init_client(struct i2c_client *client)
if ((data->config & 0x09) != 0x01)
lm87_write_value(client, LM87_REG_CONFIG,
(data->config & 0x77) | 0x01);
+ return 0;
}
-static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int lm87_probe(struct i2c_client *client)
{
struct lm87_data *data;
+ struct device *hwmon_dev;
int err;
+ unsigned int group_tail = 0;
data = devm_kzalloc(&client->dev, sizeof(struct lm87_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
- data->valid = 0;
mutex_init(&data->update_lock);
/* Initialize the LM87 chip */
- lm87_init_client(client);
+ err = lm87_init_client(client);
+ if (err)
+ return err;
data->in_scale[0] = 2500;
data->in_scale[1] = 2700;
@@ -918,72 +946,34 @@ static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->in_scale[6] = 1875;
data->in_scale[7] = 1875;
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &lm87_group);
- if (err)
- goto exit_stop;
-
- if (data->channel & CHAN_NO_FAN(0)) {
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_in6);
- if (err)
- goto exit_remove;
- } else {
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_fan1);
- if (err)
- goto exit_remove;
- }
-
- if (data->channel & CHAN_NO_FAN(1)) {
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_in7);
- if (err)
- goto exit_remove;
- } else {
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_fan2);
- if (err)
- goto exit_remove;
- }
-
- if (data->channel & CHAN_TEMP3) {
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_temp3);
- if (err)
- goto exit_remove;
- } else {
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_in0_5);
- if (err)
- goto exit_remove;
- }
+ /*
+ * Construct the list of attributes, the list depends on the
+ * configuration of the chip
+ */
+ data->attr_groups[group_tail++] = &lm87_group;
+ if (data->channel & CHAN_NO_FAN(0))
+ data->attr_groups[group_tail++] = &lm87_group_in6;
+ else
+ data->attr_groups[group_tail++] = &lm87_group_fan1;
+
+ if (data->channel & CHAN_NO_FAN(1))
+ data->attr_groups[group_tail++] = &lm87_group_in7;
+ else
+ data->attr_groups[group_tail++] = &lm87_group_fan2;
+
+ if (data->channel & CHAN_TEMP3)
+ data->attr_groups[group_tail++] = &lm87_group_temp3;
+ else
+ data->attr_groups[group_tail++] = &lm87_group_in0_5;
if (!(data->channel & CHAN_NO_VID)) {
data->vrm = vid_which_vrm();
- err = sysfs_create_group(&client->dev.kobj, &lm87_group_vid);
- if (err)
- goto exit_remove;
+ data->attr_groups[group_tail++] = &lm87_group_vid;
}
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- lm87_remove_files(client);
-exit_stop:
- lm87_write_value(client, LM87_REG_CONFIG, data->config);
- return err;
-}
-
-static int lm87_remove(struct i2c_client *client)
-{
- struct lm87_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- lm87_remove_files(client);
-
- lm87_write_value(client, LM87_REG_CONFIG, data->config);
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(
+ &client->dev, client->name, client, data->attr_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
/*
@@ -991,19 +981,26 @@ static int lm87_remove(struct i2c_client *client)
*/
static const struct i2c_device_id lm87_id[] = {
- { "lm87", lm87 },
- { "adm1024", adm1024 },
+ { "lm87" },
+ { "adm1024" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm87_id);
+static const struct of_device_id lm87_of_match[] = {
+ { .compatible = "ti,lm87" },
+ { .compatible = "adi,adm1024" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, lm87_of_match);
+
static struct i2c_driver lm87_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "lm87",
+ .of_match_table = lm87_of_match,
},
.probe = lm87_probe,
- .remove = lm87_remove,
.id_table = lm87_id,
.detect = lm87_detect,
.address_list = normal_i2c,
@@ -1011,6 +1008,6 @@ static struct i2c_driver lm87_driver = {
module_i2c_driver(lm87_driver);
-MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org> and others");
+MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de> and others");
MODULE_DESCRIPTION("LM87 driver");
MODULE_LICENSE("GPL");