summaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-07-11 14:44:13 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-11 14:44:13 -0700
commit64b08df460cfdfc2b010263043a057cdd33500ed (patch)
treed993ef73fa985a9f40bebeae84ac934370820d84 /drivers/hwmon
parentc079512aad9718c12c6bb1b661880b15a73dfd69 (diff)
parent9f7546570bcb20debfaa97bcf720fa0fcb8fc05a (diff)
Merge tag 'hwmon-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck: - New drivers for Infineon PXE1610 and IRPS5401 - Minor improvements, cleanup, and fixes in several drivers * tag 'hwmon-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (33 commits) hwmon: (ina3221) Add of_node_put() before return hwmon: (gpio-fan) fix sysfs notifications and udev events for gpio-fan alarms hwmon: (gpio-fan) move fan_alarm_init after devm_hwmon_device_register_with_groups hwmon: (lm90) Introduce function to update configuration register hwmon: (lm90) Cache configuration register value hwmon: (lm90) Fix max6658 sporadic wrong temperature reading hwmon: (nct7904) Changes comments in probe function. hwmon: (nct7904) Add error handling in probe function. hwmon: Convert remaining drivers to use SPDX identifier hwmon: (max6650) Fix unused variable warning hwmon: (pmbus/adm1275) Fix power sampling support hwmon: (lm90) simplify getting the adapter of a client hwmon: (asus_atk0110) no need to check return value of debugfs_create functions hwmon: (max6650) Fix minor formatting issues hwmon: (max6650) Improve error handling in max6650_update_device hwmon: (max6650) Read non-volatile registers only once hwmon: (max6650) Convert to use devm_hwmon_device_register_with_info hwmon: (max6650) Simplify alarm handling hwmon: (max6650) Cache alarm_en register hwmon: (max6650) Declare valid as boolean ...
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/adm1029.c10
-rw-r--r--drivers/hwmon/asus_atk0110.c23
-rw-r--r--drivers/hwmon/gpio-fan.c22
-rw-r--r--drivers/hwmon/hwmon.c6
-rw-r--r--drivers/hwmon/ina3221.c4
-rw-r--r--drivers/hwmon/lm90.c106
-rw-r--r--drivers/hwmon/max6650.c710
-rw-r--r--drivers/hwmon/nct7904.c81
-rw-r--r--drivers/hwmon/occ/common.c6
-rw-r--r--drivers/hwmon/pmbus/Kconfig18
-rw-r--r--drivers/hwmon/pmbus/Makefile2
-rw-r--r--drivers/hwmon/pmbus/adm1275.c105
-rw-r--r--drivers/hwmon/pmbus/irps5401.c67
-rw-r--r--drivers/hwmon/pmbus/pxe1610.c139
-rw-r--r--drivers/hwmon/pwm-fan.c10
-rw-r--r--drivers/hwmon/scpi-hwmon.c10
-rw-r--r--drivers/hwmon/smsc47m1.c2
17 files changed, 864 insertions, 457 deletions
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 388060ff85e7..f7752a5bef31 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -10,16 +10,6 @@
* Very rare chip please let me know if you use it
*
* http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf
- *
- *
- * 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 version 2 of the License
- *
- * 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.
*/
#include <linux/module.h>
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 8dd5b1b8db60..ff64a39d56de 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -789,33 +789,16 @@ static const struct file_operations atk_debugfs_ggrp_fops = {
static void atk_debugfs_init(struct atk_data *data)
{
struct dentry *d;
- struct dentry *f;
data->debugfs.id = 0;
d = debugfs_create_dir("asus_atk0110", NULL);
- if (!d || IS_ERR(d))
- return;
- f = debugfs_create_x32("id", 0600, d, &data->debugfs.id);
- if (!f || IS_ERR(f))
- goto cleanup;
-
- f = debugfs_create_file_unsafe("gitm", 0400, d, data,
- &atk_debugfs_gitm);
- if (!f || IS_ERR(f))
- goto cleanup;
-
- f = debugfs_create_file("ggrp", 0400, d, data,
- &atk_debugfs_ggrp_fops);
- if (!f || IS_ERR(f))
- goto cleanup;
+ debugfs_create_x32("id", 0600, d, &data->debugfs.id);
+ debugfs_create_file_unsafe("gitm", 0400, d, data, &atk_debugfs_gitm);
+ debugfs_create_file("ggrp", 0400, d, data, &atk_debugfs_ggrp_fops);
data->debugfs.root = d;
-
- return;
-cleanup:
- debugfs_remove_recursive(d);
}
static void atk_debugfs_cleanup(struct atk_data *data)
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 84753680a4e8..3ea4021f267c 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -54,8 +54,8 @@ static void fan_alarm_notify(struct work_struct *ws)
struct gpio_fan_data *fan_data =
container_of(ws, struct gpio_fan_data, alarm_work);
- sysfs_notify(&fan_data->dev->kobj, NULL, "fan1_alarm");
- kobject_uevent(&fan_data->dev->kobj, KOBJ_CHANGE);
+ sysfs_notify(&fan_data->hwmon_dev->kobj, NULL, "fan1_alarm");
+ kobject_uevent(&fan_data->hwmon_dev->kobj, KOBJ_CHANGE);
}
static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)
@@ -510,13 +510,6 @@ static int gpio_fan_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fan_data);
mutex_init(&fan_data->lock);
- /* Configure alarm GPIO if available. */
- if (fan_data->alarm_gpio) {
- err = fan_alarm_init(fan_data);
- if (err)
- return err;
- }
-
/* Configure control GPIOs if available. */
if (fan_data->gpios && fan_data->num_gpios > 0) {
if (!fan_data->speed || fan_data->num_speed <= 1)
@@ -524,7 +517,9 @@ static int gpio_fan_probe(struct platform_device *pdev)
err = fan_ctrl_init(fan_data);
if (err)
return err;
- devm_add_action_or_reset(dev, gpio_fan_stop, fan_data);
+ err = devm_add_action_or_reset(dev, gpio_fan_stop, fan_data);
+ if (err)
+ return err;
}
/* Make this driver part of hwmon class. */
@@ -535,6 +530,13 @@ static int gpio_fan_probe(struct platform_device *pdev)
if (IS_ERR(fan_data->hwmon_dev))
return PTR_ERR(fan_data->hwmon_dev);
+ /* Configure alarm GPIO if available. */
+ if (fan_data->alarm_gpio) {
+ err = fan_alarm_init(fan_data);
+ if (err)
+ return err;
+ }
+
/* Optional cooling device register for Device tree platforms */
fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np,
"gpio-fan", fan_data, &gpio_fan_cool_ops);
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 05e120e01cb4..1f3b30b085b9 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -651,6 +651,12 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
hwdev, j);
if (err) {
device_unregister(hdev);
+ /*
+ * Don't worry about hwdev;
+ * hwmon_dev_release(), called
+ * from device_unregister(),
+ * will free it.
+ */
goto ida_remove;
}
}
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index 55943b4dcc7b..0037e2bdacd6 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -713,8 +713,10 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
for_each_child_of_node(np, child) {
ret = ina3221_probe_child_from_dt(dev, child, ina);
- if (ret)
+ if (ret) {
+ of_node_put(child);
return ret;
+ }
}
return 0;
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index e562a578f20e..9b3c9f390ef8 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -174,6 +174,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */
#define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */
#define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */
+#define LM90_PAUSE_FOR_CONFIG (1 << 8) /* Pause conversion for config */
/* LM90 status */
#define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */
@@ -367,6 +368,7 @@ static const struct lm90_params lm90_params[] = {
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
},
[max6657] = {
+ .flags = LM90_PAUSE_FOR_CONFIG,
.alert_alarms = 0x7c,
.max_convrate = 8,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
@@ -457,6 +459,7 @@ struct lm90_data {
unsigned int update_interval; /* in milliseconds */
+ u8 config; /* Current configuration register value */
u8 config_orig; /* Original configuration register value */
u8 convrate_orig; /* Original conversion rate register value */
u16 alert_alarms; /* Which alarm bits trigger ALERT# */
@@ -540,6 +543,21 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl)
return (newh << 8) | l;
}
+static int lm90_update_confreg(struct lm90_data *data, u8 config)
+{
+ if (data->config != config) {
+ int err;
+
+ err = i2c_smbus_write_byte_data(data->client,
+ LM90_REG_W_CONFIG1,
+ config);
+ if (err)
+ return err;
+ data->config = config;
+ }
+ return 0;
+}
+
/*
* client->update_lock must be held when calling this function (unless we are
* in detection or initialization steps), and while a remote channel other
@@ -548,23 +566,39 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl)
* various registers have different meanings as a result of selecting a
* non-default remote channel.
*/
-static inline int lm90_select_remote_channel(struct i2c_client *client,
- struct lm90_data *data,
- int channel)
+static int lm90_select_remote_channel(struct lm90_data *data, int channel)
{
- int config;
+ int err = 0;
if (data->kind == max6696) {
- config = lm90_read_reg(client, LM90_REG_R_CONFIG1);
- if (config < 0)
- return config;
- config &= ~0x08;
+ u8 config = data->config & ~0x08;
+
if (channel)
config |= 0x08;
- i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
- config);
+ err = lm90_update_confreg(data, config);
}
- return 0;
+ return err;
+}
+
+static int lm90_write_convrate(struct lm90_data *data, int val)
+{
+ u8 config = data->config;
+ int err;
+
+ /* Save config and pause conversion */
+ if (data->flags & LM90_PAUSE_FOR_CONFIG) {
+ err = lm90_update_confreg(data, config | 0x40);
+ if (err < 0)
+ return err;
+ }
+
+ /* Set conv rate */
+ err = i2c_smbus_write_byte_data(data->client, LM90_REG_W_CONVRATE, val);
+
+ /* Revert change to config */
+ lm90_update_confreg(data, config);
+
+ return err;
}
/*
@@ -587,7 +621,7 @@ static int lm90_set_convrate(struct i2c_client *client, struct lm90_data *data,
if (interval >= update_interval * 3 / 4)
break;
- err = i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, i);
+ err = lm90_write_convrate(data, i);
data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64);
return err;
}
@@ -658,7 +692,7 @@ static int lm90_update_limits(struct device *dev)
}
if (data->kind == max6696) {
- val = lm90_select_remote_channel(client, data, 1);
+ val = lm90_select_remote_channel(data, 1);
if (val < 0)
return val;
@@ -682,7 +716,7 @@ static int lm90_update_limits(struct device *dev)
return val;
data->temp11[REMOTE2_HIGH] = val << 8;
- lm90_select_remote_channel(client, data, 0);
+ lm90_select_remote_channel(data, 0);
}
return 0;
@@ -742,19 +776,19 @@ static int lm90_update_device(struct device *dev)
data->alarms = val; /* lower 8 bit of alarms */
if (data->kind == max6696) {
- val = lm90_select_remote_channel(client, data, 1);
+ val = lm90_select_remote_channel(data, 1);
if (val < 0)
return val;
val = lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
LM90_REG_R_REMOTE_TEMPL);
if (val < 0) {
- lm90_select_remote_channel(client, data, 0);
+ lm90_select_remote_channel(data, 0);
return val;
}
data->temp11[REMOTE2_TEMP] = val;
- lm90_select_remote_channel(client, data, 0);
+ lm90_select_remote_channel(data, 0);
val = lm90_read_reg(client, MAX6696_REG_R_STATUS2);
if (val < 0)
@@ -768,15 +802,9 @@ static int lm90_update_device(struct device *dev)
*/
if (!(data->config_orig & 0x80) &&
!(data->alarms & data->alert_alarms)) {
- val = lm90_read_reg(client, LM90_REG_R_CONFIG1);
- if (val < 0)
- return val;
-
- if (val & 0x80) {
+ if (data->config & 0x80) {
dev_dbg(&client->dev, "Re-enabling ALERT#\n");
- i2c_smbus_write_byte_data(client,
- LM90_REG_W_CONFIG1,
- val & ~0x80);
+ lm90_update_confreg(data, data->config & ~0x80);
}
}
@@ -994,7 +1022,7 @@ static int lm90_set_temp11(struct lm90_data *data, int index, long val)
else
data->temp11[index] = temp_to_s8(val) << 8;
- lm90_select_remote_channel(client, data, index >= 3);
+ lm90_select_remote_channel(data, index >= 3);
err = i2c_smbus_write_byte_data(client, regp->high,
data->temp11[index] >> 8);
if (err < 0)
@@ -1003,7 +1031,7 @@ static int lm90_set_temp11(struct lm90_data *data, int index, long val)
err = i2c_smbus_write_byte_data(client, regp->low,
data->temp11[index] & 0xff);
- lm90_select_remote_channel(client, data, 0);
+ lm90_select_remote_channel(data, 0);
return err;
}
@@ -1052,9 +1080,9 @@ static int lm90_set_temp8(struct lm90_data *data, int index, long val)
else
data->temp8[index] = temp_to_s8(val);
- lm90_select_remote_channel(client, data, index >= 6);
+ lm90_select_remote_channel(data, index >= 6);
err = i2c_smbus_write_byte_data(client, reg[index], data->temp8[index]);
- lm90_select_remote_channel(client, data, 0);
+ lm90_select_remote_channel(data, 0);
return err;
}
@@ -1593,8 +1621,7 @@ static void lm90_restore_conf(void *_data)
struct i2c_client *client = data->client;
/* Restore initial configuration */
- i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
- data->convrate_orig);
+ lm90_write_convrate(data, data->convrate_orig);
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
data->config_orig);
}
@@ -1611,11 +1638,13 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data)
/*
* Start the conversions.
*/
- lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */
config = lm90_read_reg(client, LM90_REG_R_CONFIG1);
if (config < 0)
return config;
data->config_orig = config;
+ data->config = config;
+
+ lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */
/* Check Temperature Range Select */
if (data->kind == adt7461 || data->kind == tmp451) {
@@ -1638,8 +1667,7 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data)
config &= ~0x08;
config &= 0xBF; /* run */
- if (config != data->config_orig) /* Only write if changed */
- i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
+ lm90_update_confreg(data, config);
return devm_add_action_or_reset(&client->dev, lm90_restore_conf, data);
}
@@ -1718,7 +1746,7 @@ static int lm90_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
- struct i2c_adapter *adapter = to_i2c_adapter(dev->parent);
+ struct i2c_adapter *adapter = client->adapter;
struct hwmon_channel_info *info;
struct regulator *regulator;
struct device *hwmon_dev;
@@ -1873,14 +1901,8 @@ static void lm90_alert(struct i2c_client *client, enum i2c_alert_protocol type,
if ((data->flags & LM90_HAVE_BROKEN_ALERT) &&
(alarms & data->alert_alarms)) {
- int config;
-
dev_dbg(&client->dev, "Disabling ALERT#\n");
- config = lm90_read_reg(client, LM90_REG_R_CONFIG1);
- if (config >= 0)
- i2c_smbus_write_byte_data(client,
- LM90_REG_W_CONFIG1,
- config | 0x80);
+ lm90_update_confreg(data, data->config | 0x80);
}
} else {
dev_info(&client->dev, "Everything OK\n");
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 6b9056f9483f..3d9d371c35b5 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -92,7 +92,8 @@ module_param(clock, int, 0444);
#define FAN_RPM_MIN 240
#define FAN_RPM_MAX 30000
-#define DIV_FROM_REG(reg) (1 << (reg & 7))
+#define DIV_FROM_REG(reg) (1 << ((reg) & 7))
+#define DAC_LIMIT(v12) ((v12) ? 180 : 76)
/*
* Client data (each client gets its own)
@@ -100,11 +101,9 @@ module_param(clock, int, 0444);
struct max6650_data {
struct i2c_client *client;
- const struct attribute_group *groups[3];
- struct thermal_cooling_device *cooling_dev;
- struct mutex update_lock;
+ struct mutex update_lock; /* protect alarm register updates */
int nr_fans;
- char valid; /* zero until following fields are valid */
+ bool valid; /* false until following fields are valid */
unsigned long last_updated; /* in jiffies */
/* register values */
@@ -114,6 +113,7 @@ struct max6650_data {
u8 count;
u8 dac;
u8 alarm;
+ u8 alarm_en;
unsigned long cooling_dev_state;
};
@@ -137,41 +137,60 @@ static const struct of_device_id __maybe_unused max6650_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, max6650_dt_match);
+static int dac_to_pwm(int dac, bool v12)
+{
+ /*
+ * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans.
+ * Lower DAC values mean higher speeds.
+ */
+ return clamp_val(255 - (255 * dac) / DAC_LIMIT(v12), 0, 255);
+}
+
+static u8 pwm_to_dac(unsigned int pwm, bool v12)
+{
+ int limit = DAC_LIMIT(v12);
+
+ return limit - (limit * pwm) / 255;
+}
+
static struct max6650_data *max6650_update_device(struct device *dev)
{
struct max6650_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
+ int reg, err = 0;
int i;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
- data->speed = i2c_smbus_read_byte_data(client,
- MAX6650_REG_SPEED);
- data->config = i2c_smbus_read_byte_data(client,
- MAX6650_REG_CONFIG);
for (i = 0; i < data->nr_fans; i++) {
- data->tach[i] = i2c_smbus_read_byte_data(client,
- tach_reg[i]);
+ reg = i2c_smbus_read_byte_data(client, tach_reg[i]);
+ if (reg < 0) {
+ err = reg;
+ goto error;
+ }
+ data->tach[i] = reg;
}
- data->count = i2c_smbus_read_byte_data(client,
- MAX6650_REG_COUNT);
- data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
/*
* Alarms are cleared on read in case the condition that
* caused the alarm is removed. Keep the value latched here
* for providing the register through different alarm files.
*/
- data->alarm |= i2c_smbus_read_byte_data(client,
- MAX6650_REG_ALARM);
-
+ reg = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM);
+ if (reg < 0) {
+ err = reg;
+ goto error;
+ }
+ data->alarm |= reg;
data->last_updated = jiffies;
- data->valid = 1;
+ data->valid = true;
}
+error:
mutex_unlock(&data->update_lock);
-
+ if (err)
+ data = ERR_PTR(err);
return data;
}
@@ -199,26 +218,6 @@ static int max6650_set_operating_mode(struct max6650_data *data, u8 mode)
return 0;
}
-static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct max6650_data *data = max6650_update_device(dev);
- int rpm;
-
- /*
- * Calculation details:
- *
- * Each tachometer counts over an interval given by the "count"
- * register (0.25, 0.5, 1 or 2 seconds). This module assumes
- * that the fans produce two pulses per revolution (this seems
- * to be the most common).
- */
-
- rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count));
- return sprintf(buf, "%d\n", rpm);
-}
-
/*
* Set the fan speed to the specified RPM (or read back the RPM setting).
* This works in closed loop mode only. Use pwm1 for open loop speed setting.
@@ -260,26 +259,6 @@ static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
* controlled.
*/
-static ssize_t fan1_target_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct max6650_data *data = max6650_update_device(dev);
- int kscale, ktach, rpm;
-
- /*
- * Use the datasheet equation:
- *
- * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)]
- *
- * then multiply by 60 to give rpm.
- */
-
- kscale = DIV_FROM_REG(data->config);
- ktach = data->speed;
- rpm = 60 * kscale * clock / (256 * (ktach + 1));
- return sprintf(buf, "%d\n", rpm);
-}
-
static int max6650_set_target(struct max6650_data *data, unsigned long rpm)
{
int kscale, ktach;
@@ -308,197 +287,8 @@ static int max6650_set_target(struct max6650_data *data, unsigned long rpm)
data->speed);
}
-static ssize_t fan1_target_store(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct max6650_data *data = dev_get_drvdata(dev);
- unsigned long rpm;
- int err;
-
- err = kstrtoul(buf, 10, &rpm);
- if (err)
- return err;
-
- mutex_lock(&data->update_lock);
-
- err = max6650_set_target(data, rpm);
-
- mutex_unlock(&data->update_lock);
-
- if (err < 0)
- return err;
-
- return count;
-}
-
-/*
- * Get/set the fan speed in open loop mode using pwm1 sysfs file.
- * Speed is given as a relative value from 0 to 255, where 255 is maximum
- * speed. Note that this is done by writing directly to the chip's DAC,
- * it won't change the closed loop speed set by fan1_target.
- * Also note that due to rounding errors it is possible that you don't read
- * back exactly the value you have set.
- */
-
-static ssize_t pwm1_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- int pwm;
- struct max6650_data *data = max6650_update_device(dev);
-
- /*
- * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans.
- * Lower DAC values mean higher speeds.
- */
- if (data->config & MAX6650_CFG_V12)
- pwm = 255 - (255 * (int)data->dac)/180;
- else
- pwm = 255 - (255 * (int)data->dac)/76;
-
- if (pwm < 0)
- pwm = 0;
-
- return sprintf(buf, "%d\n", pwm);
-}
-
-static ssize_t pwm1_store(struct device *dev,
- struct device_attribute *devattr, const char *buf,
- size_t count)
-{
- struct max6650_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- unsigned long pwm;
- int err;
-
- err = kstrtoul(buf, 10, &pwm);
- if (err)
- return err;
-
- pwm = clamp_val(pwm, 0, 255);
-
- mutex_lock(&data->update_lock);
-
- if (data->config & MAX6650_CFG_V12)
- data->dac = 180 - (180 * pwm)/255;
- else
- data->dac = 76 - (76 * pwm)/255;
- err = i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac);
-
- mutex_unlock(&data->update_lock);
-
- return err < 0 ? err : count;
-}
-
/*
- * Get/Set controller mode:
- * Possible values:
- * 0 = Fan always on
- * 1 = Open loop, Voltage is set according to speed, not regulated.
- * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer
- * 3 = Fan off
- */
-static ssize_t pwm1_enable_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct max6650_data *data = max6650_update_device(dev);
- int mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4;
- int sysfs_modes[4] = {0, 3, 2, 1};
-
- return sprintf(buf, "%d\n", sysfs_modes[mode]);
-}
-
-static ssize_t pwm1_enable_store(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct max6650_data *data = dev_get_drvdata(dev);
- unsigned long mode;
- int err;
- const u8 max6650_modes[] = {
- MAX6650_CFG_MODE_ON,
- MAX6650_CFG_MODE_OPEN_LOOP,
- MAX6650_CFG_MODE_CLOSED_LOOP,
- MAX6650_CFG_MODE_OFF,
- };
-
- err = kstrtoul(buf, 10, &mode);
- if (err)
- return err;
-
- if (mode >= ARRAY_SIZE(max6650_modes))
- return -EINVAL;
-
- mutex_lock(&data->update_lock);
-
- max6650_set_operating_mode(data, max6650_modes[mode]);
-
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-/*
- * Read/write functions for fan1_div sysfs file. The MAX6650 has no such
- * divider. We handle this by converting between divider and counttime:
- *
- * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, or 3
- *
- * Lower values of k allow to connect a faster fan without the risk of
- * counter overflow. The price is lower resolution. You can also set counttime
- * using the module parameter. Note that the module parameter "prescaler" also
- * influences the behaviour. Unfortunately, there's no sysfs attribute
- * defined for that. See the data sheet for details.
- */
-
-static ssize_t fan1_div_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct max6650_data *data = max6650_update_device(dev);
-
- return sprintf(buf, "%d\n", DIV_FROM_REG(data->count));
-}
-
-static ssize_t fan1_div_store(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct max6650_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- unsigned long div;
- int err;
-
- err = kstrtoul(buf, 10, &div);
- if (err)
- return err;
-
- mutex_lock(&data->update_lock);
- switch (div) {
- case 1:
- data->count = 0;
- break;
- case 2:
- data->count = 1;
- break;
- case 4:
- data->count = 2;
- break;
- case 8:
- data->count = 3;
- break;
- default:
- mutex_unlock(&data->update_lock);
- return -EINVAL;
- }
-
- i2c_smbus_write_byte_data(client, MAX6650_REG_COUNT, data->count);
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-/*
- * Get alarm stati:
+ * Get gpio alarm status:
* Possible values:
* 0 = no alarm
* 1 = alarm
@@ -509,42 +299,30 @@ static ssize_t alarm_show(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct max6650_data *data = max6650_update_device(dev);
- struct i2c_client *client = data->client;
- int alarm = 0;
+ bool alarm;
- if (data->alarm & attr->index) {
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ alarm = data->alarm & attr->index;
+ if (alarm) {
mutex_lock(&data->update_lock);
- alarm = 1;
data->alarm &= ~attr->index;
- data->alarm |= i2c_smbus_read_byte_data(client,
- MAX6650_REG_ALARM);
+ data->valid = false;
mutex_unlock(&data->update_lock);
}
return sprintf(buf, "%d\n", alarm);
}
-static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
-static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
-static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2);
-static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3);
-static DEVICE_ATTR_RW(fan1_target);
-static DEVICE_ATTR_RW(fan1_div);
-static DEVICE_ATTR_RW(pwm1_enable);
-static DEVICE_ATTR_RW(pwm1);
-static SENSOR_DEVICE_ATTR_RO(fan1_max_alarm, alarm, MAX6650_ALRM_MAX);
-static SENSOR_DEVICE_ATTR_RO(fan1_min_alarm, alarm, MAX6650_ALRM_MIN);
-static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, MAX6650_ALRM_TACH);
static SENSOR_DEVICE_ATTR_RO(gpio1_alarm, alarm, MAX6650_ALRM_GPIO1);
static SENSOR_DEVICE_ATTR_RO(gpio2_alarm, alarm, MAX6650_ALRM_GPIO2);
static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
- int n)
+ int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct max6650_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- u8 alarm_en = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN);
struct device_attribute *devattr;
/*
@@ -552,12 +330,9 @@ static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
*/
devattr = container_of(a, struct device_attribute, attr);
- if (devattr == &sensor_dev_attr_fan1_max_alarm.dev_attr
- || devattr == &sensor_dev_attr_fan1_min_alarm.dev_attr
- || devattr == &sensor_dev_attr_fan1_fault.dev_attr
- || devattr == &sensor_dev_attr_gpio1_alarm.dev_attr
- || devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) {
- if (!(alarm_en & to_sensor_dev_attr(devattr)->index))
+ if (devattr == &sensor_dev_attr_gpio1_alarm.dev_attr ||
+ devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) {
+ if (!(data->alarm_en & to_sensor_dev_attr(devattr)->index))
return 0;
}
@@ -565,14 +340,6 @@ static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
}
static struct attribute *max6650_attrs[] = {
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &dev_attr_fan1_target.attr,
- &dev_attr_fan1_div.attr,
- &dev_attr_pwm1_enable.attr,
- &dev_attr_pwm1.attr,
- &sensor_dev_attr_fan1_max_alarm.dev_attr.attr,
- &sensor_dev_attr_fan1_min_alarm.dev_attr.attr,
- &sensor_dev_attr_fan1_fault.dev_attr.attr,
&sensor_dev_attr_gpio1_alarm.dev_attr.attr,
&sensor_dev_attr_gpio2_alarm.dev_attr.attr,
NULL
@@ -583,27 +350,17 @@ static const struct attribute_group max6650_group = {
.is_visible = max6650_attrs_visible,
};
-static struct attribute *max6651_attrs[] = {
- &sensor_dev_attr_fan2_input.dev_attr.attr,
- &sensor_dev_attr_fan3_input.dev_attr.attr,
- &sensor_dev_attr_fan4_input.dev_attr.attr,
+static const struct attribute_group *max6650_groups[] = {
+ &max6650_group,
NULL
};
-static const struct attribute_group max6651_group = {
- .attrs = max6651_attrs,
-};
-
-/*
- * Real code
- */
-
static int max6650_init_client(struct max6650_data *data,
struct i2c_client *client)
{
struct device *dev = &client->dev;
- int config;
- int err = -EIO;
+ int reg;
+ int err;
u32 voltage;
u32 prescale;
u32 target_rpm;
@@ -617,21 +374,20 @@ static int max6650_init_client(struct max6650_data *data,
&prescale))
prescale = prescaler;
- config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG);
-
- if (config < 0) {
- dev_err(dev, "Error reading config, aborting.\n");
- return err;
+ reg = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG);
+ if (reg < 0) {
+ dev_err(dev, "Error reading config register, aborting.\n");
+ return reg;
}
switch (voltage) {
case 0:
break;
case 5:
- config &= ~MAX6650_CFG_V12;
+ reg &= ~MAX6650_CFG_V12;
break;
case 12:
- config |= MAX6650_CFG_V12;
+ reg |= MAX6650_CFG_V12;
break;
default:
dev_err(dev, "illegal value for fan_voltage (%d)\n", voltage);
@@ -641,22 +397,22 @@ static int max6650_init_client(struct max6650_data *data,
case 0:
break;
case 1:
- config &= ~MAX6650_CFG_PRESCALER_MASK;
+ reg &= ~MAX6650_CFG_PRESCALER_MASK;
break;
case 2:
- config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+ reg = (reg & ~MAX6650_CFG_PRESCALER_MASK)
| MAX6650_CFG_PRESCALER_2;
break;
case 4:
- config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+ reg = (reg & ~MAX6650_CFG_PRESCALER_MASK)
| MAX6650_CFG_PRESCALER_4;
break;
case 8:
- config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+ reg = (reg & ~MAX6650_CFG_PRESCALER_MASK)
| MAX6650_CFG_PRESCALER_8;
break;
case 16:
- config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+ reg = (reg & ~MAX6650_CFG_PRESCALER_MASK)
| MAX6650_CFG_PRESCALER_16;
break;