@@ -68,5 +68,3 @@ is performed to match that target value. The fan speed value is computed
based on the parameters associated with the physical characteristics of the
system: a reference clock source frequency, a number of pulses per fan
revolution, etc.
-
-Note that the driver will update its values at most once per second.
@@ -36,11 +36,11 @@
#include <linux/init.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/regmap.h>
#define DRVNAME "g762"
@@ -68,19 +68,6 @@ enum g762_regs {
#define G762_REG_FAN_STA_FAIL BIT(1) /* fan fail */
#define G762_REG_FAN_STA_OOC BIT(0) /* fan out of control */
-/* Config register values */
-#define G762_OUT_MODE_PWM 1
-#define G762_OUT_MODE_DC 0
-
-#define G762_FAN_MODE_CLOSED_LOOP 2
-#define G762_FAN_MODE_OPEN_LOOP 1
-
-#define G762_PWM_POLARITY_NEGATIVE 1
-#define G762_PWM_POLARITY_POSITIVE 0
-
-/* Register data is read (and cached) at most once per second. */
-#define G762_UPDATE_INTERVAL HZ
-
/*
* Extract pulse count per fan revolution value (2 or 4) from given
* FAN_CMD1 register value.
@@ -103,48 +90,13 @@ enum g762_regs {
BIT(FIELD_GET(G762_REG_FAN_CMD2_GEAR_MASK, reg))
struct g762_data {
- struct i2c_client *client;
+ struct regmap *regmap;
/* update mutex */
struct mutex update_lock;
/* board specific parameters. */
u32 clk_freq;
-
- /* g762 register cache */
- bool valid;
- unsigned long last_updated; /* in jiffies */
-
- u8 set_cnt; /* controls fan rotation speed in closed-loop mode */
- u8 act_cnt; /* provides access to current fan RPM value */
- u8 fan_sta; /* bit 0: set when actual fan speed is more than
- * 25% outside requested fan speed
- * bit 1: set when no transition occurs on fan
- * pin for 0.7s
- */
- u8 set_out; /* controls fan rotation speed in open-loop mode */
- u8 fan_cmd1; /* 0: FG_PLS_ID0 FG pulses count per revolution
- * 0: 2 counts per revolution
- * 1: 4 counts per revolution
- * 1: PWM_POLARITY 1: negative_duty
- * 0: positive_duty
- * 2,3: [FG_CLOCK_ID0, FG_CLK_ID1]
- * 00: Divide fan clock by 1
- * 01: Divide fan clock by 2
- * 10: Divide fan clock by 4
- * 11: Divide fan clock by 8
- * 4: FAN_MODE 1:closed-loop, 0:open-loop
- * 5: OUT_MODE 1:PWM, 0:DC
- * 6: DET_FAN_OOC enable "fan ooc" status
- * 7: DET_FAN_FAIL enable "fan fail" status
- */
- u8 fan_cmd2; /* 0,1: FAN_STARTV 0,1,2,3 -> 0,32,64,96 dac_code
- * 2,3: FG_GEAR_MODE
- * 00: multiplier = 1
- * 01: multiplier = 2
- * 10: multiplier = 4
- * 4: Mask ALERT# (g763 only)
- */
};
/*
@@ -179,59 +131,6 @@ static inline unsigned char cnt_from_rpm(unsigned long rpm, u32 clk_freq, u16 p,
return DIV_ROUND_CLOSEST(f1, rpm * f2);
}
-/* helper to grab and cache data, at most one time per second */
-static struct g762_data *g762_update_client(struct device *dev)
-{
- struct g762_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int ret = 0;
-
- mutex_lock(&data->update_lock);
- if (time_before(jiffies, data->last_updated + G762_UPDATE_INTERVAL) &&
- likely(data->valid))
- goto out;
-
- ret = i2c_smbus_read_byte_data(client, G762_REG_SET_CNT);
- if (ret < 0)
- goto out;
- data->set_cnt = ret;
-
- ret = i2c_smbus_read_byte_data(client, G762_REG_ACT_CNT);
- if (ret < 0)
- goto out;
- data->act_cnt = ret;
-
- ret = i2c_smbus_read_byte_data(client, G762_REG_FAN_STA);
- if (ret < 0)
- goto out;
- data->fan_sta = ret;
-
- ret = i2c_smbus_read_byte_data(client, G762_REG_SET_OUT);
- if (ret < 0)
- goto out;
- data->set_out = ret;
-
- ret = i2c_smbus_read_byte_data(client, G762_REG_FAN_CMD1);
- if (ret < 0)
- goto out;
- data->fan_cmd1 = ret;
-
- ret = i2c_smbus_read_byte_data(client, G762_REG_FAN_CMD2);
- if (ret < 0)
- goto out;
- data->fan_cmd2 = ret;
-
- data->last_updated = jiffies;
- data->valid = true;
- out:
- mutex_unlock(&data->update_lock);
-
- if (ret < 0) /* upon error, encode it in return value */
- data = ERR_PTR(ret);
-
- return data;
-}
-
/* helpers for writing hardware parameters */
/*
@@ -257,125 +156,72 @@ static int do_set_clk_freq(struct device *dev, unsigned long val)
/* Set pwm mode. Accepts either 0 (PWM mode) or 1 (DC mode) */
static int do_set_pwm_mode(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
- int ret;
+ struct g762_data *data = dev_get_drvdata(dev);
- if (IS_ERR(data))
- return PTR_ERR(data);
+ if (val && val != 1)
+ return -EINVAL;
- mutex_lock(&data->update_lock);
- switch (val) {
- case G762_OUT_MODE_PWM:
- data->fan_cmd1 |= G762_REG_FAN_CMD1_OUT_MODE;
- break;
- case G762_OUT_MODE_DC:
- data->fan_cmd1 &= ~G762_REG_FAN_CMD1_OUT_MODE;
- break;
- default:
- ret = -EINVAL;
- goto out;
- }
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
- data->valid = false;
- out:
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_update_bits(data->regmap, G762_REG_FAN_CMD1,
+ G762_REG_FAN_CMD1_OUT_MODE,
+ val ? G762_REG_FAN_CMD1_OUT_MODE : 0);
}
/* Set fan clock divisor. Accepts either 1, 2, 4 or 8. */
static int do_set_fan_div(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
- int ret;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
+ struct g762_data *data = dev_get_drvdata(dev);
if (hweight_long(val) != 1 || val > 8)
return -EINVAL;
- mutex_lock(&data->update_lock);
- data->fan_cmd1 &= ~G762_REG_FAN_CMD1_CLK_DIV_MASK;
- data->fan_cmd1 |= FIELD_PREP(G762_REG_FAN_CMD1_CLK_DIV_MASK, __ffs(val));
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
- data->valid = false;
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_update_bits(data->regmap, G762_REG_FAN_CMD1,
+ G762_REG_FAN_CMD1_CLK_DIV_MASK,
+ FIELD_PREP(G762_REG_FAN_CMD1_CLK_DIV_MASK, __ffs(val)));
}
/* Set fan gear mode. Accepts either 0, 1 or 2. */
static int do_set_fan_gear_mode(struct device *dev, u32 val)
{
- struct g762_data *data = g762_update_client(dev);
- int ret;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
+ struct g762_data *data = dev_get_drvdata(dev);
if (val > 2)
return -EINVAL;
- mutex_lock(&data->update_lock);
- data->fan_cmd2 &= ~G762_REG_FAN_CMD2_GEAR_MASK;
- data->fan_cmd2 |= FIELD_PREP(G762_REG_FAN_CMD2_GEAR_MASK, val);
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
- data->fan_cmd2);
- data->valid = false;
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_update_bits(data->regmap, G762_REG_FAN_CMD2,
+ G762_REG_FAN_CMD2_GEAR_MASK,
+ FIELD_PREP(G762_REG_FAN_CMD2_GEAR_MASK, val));
}
/* Set number of fan pulses per revolution. Accepts either 2 or 4. */
static int do_set_fan_pulses(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
- int ret;
+ struct g762_data *data = dev_get_drvdata(dev);
- if (IS_ERR(data))
- return PTR_ERR(data);
+ if (val != 2 && val != 4)
+ return -EINVAL;
- mutex_lock(&data->update_lock);
- switch (val) {
- case 2:
- data->fan_cmd1 &= ~G762_REG_FAN_CMD1_PULSE_PER_REV;
- break;
- case 4:
- data->fan_cmd1 |= G762_REG_FAN_CMD1_PULSE_PER_REV;
- break;
- default:
- ret = -EINVAL;
- goto out;
- }
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
- data->valid = false;
- out:
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_update_bits(data->regmap, G762_REG_FAN_CMD1,
+ G762_REG_FAN_CMD1_PULSE_PER_REV,
+ val == 4 ? G762_REG_FAN_CMD1_PULSE_PER_REV : 0);
}
/* Set fan mode. Accepts either 1 (open-loop) or 2 (closed-loop). */
static int do_set_pwm_enable(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ struct regmap *regmap = data->regmap;
int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ if (val != 1 && val != 2)
+ return -EINVAL;
mutex_lock(&data->update_lock);
- switch (val) {
- case G762_FAN_MODE_CLOSED_LOOP:
- data->fan_cmd1 |= G762_REG_FAN_CMD1_FAN_MODE;
- break;
- case G762_FAN_MODE_OPEN_LOOP:
- data->fan_cmd1 &= ~G762_REG_FAN_CMD1_FAN_MODE;
+ if (val == 1) {
+ u32 regval;
+
+ ret = regmap_read(regmap, G762_REG_SET_CNT, ®val);
+ if (ret)
+ goto unlock;
/*
* BUG FIX: if SET_CNT register value is 255 then, for some
* unknown reason, fan will not rotate as expected, no matter
@@ -383,52 +229,26 @@ static int do_set_pwm_enable(struct device *dev, unsigned long val)
* only in PWM mode). To workaround this bug, we give SET_CNT
* value of 254 if it is 255 when switching to open-loop.
*/
- if (data->set_cnt == 0xff)
- i2c_smbus_write_byte_data(data->client,
- G762_REG_SET_CNT, 254);
- break;
- default:
- ret = -EINVAL;
- goto out;
+ if (regval == 0xff)
+ regmap_write(regmap, G762_REG_SET_CNT, 254);
}
-
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
- data->valid = false;
- out:
+ ret = regmap_update_bits(regmap, G762_REG_FAN_CMD1, G762_REG_FAN_CMD1_FAN_MODE,
+ val == 2 ? G762_REG_FAN_CMD1_FAN_MODE : 0);
+unlock:
mutex_unlock(&data->update_lock);
-
return ret;
}
/* Set PWM polarity. Accepts either 0 (positive duty) or 1 (negative duty) */
static int do_set_pwm_polarity(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
- int ret;
+ struct g762_data *data = dev_get_drvdata(dev);
- if (IS_ERR(data))
- return PTR_ERR(data);
+ if (val && val != 1)
+ return -EINVAL;
- mutex_lock(&data->update_lock);
- switch (val) {
- case G762_PWM_POLARITY_POSITIVE:
- data->fan_cmd1 &= ~G762_REG_FAN_CMD1_PWM_POLARITY;
- break;
- case G762_PWM_POLARITY_NEGATIVE:
- data->fan_cmd1 |= G762_REG_FAN_CMD1_PWM_POLARITY;
- break;
- default:
- ret = -EINVAL;
- goto out;
- }
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
- data->valid = false;
- out:
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_update_bits(data->regmap, G762_REG_FAN_CMD1, G762_REG_FAN_CMD1_PWM_POLARITY,
+ val ? G762_REG_FAN_CMD1_PWM_POLARITY : 0);
}
/*
@@ -438,18 +258,11 @@ static int do_set_pwm_polarity(struct device *dev, unsigned long val)
static int do_set_pwm(struct device *dev, unsigned long val)
{
struct g762_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int ret;
if (val > 255)
return -EINVAL;
- mutex_lock(&data->update_lock);
- ret = i2c_smbus_write_byte_data(client, G762_REG_SET_OUT, val);
- data->valid = false;
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_write(data->regmap, G762_REG_SET_OUT, val);
}
/*
@@ -458,52 +271,81 @@ static int do_set_pwm(struct device *dev, unsigned long val)
*/
static int do_set_fan_target(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ struct regmap *regmap = data->regmap;
+ u32 cmd1, cmd2;
+ u8 set_cnt;
int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
-
mutex_lock(&data->update_lock);
- data->set_cnt = cnt_from_rpm(val, data->clk_freq,
- G762_PULSE_FROM_REG(data->fan_cmd1),
- G762_CLKDIV_FROM_REG(data->fan_cmd1),
- G762_GEARMULT_FROM_REG(data->fan_cmd2));
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_SET_CNT,
- data->set_cnt);
- data->valid = false;
- mutex_unlock(&data->update_lock);
+ ret = regmap_read(regmap, G762_REG_FAN_CMD1, &cmd1);
+ if (ret)
+ goto unlock;
+ ret = regmap_read(regmap, G762_REG_FAN_CMD2, &cmd2);
+ if (ret)
+ goto unlock;
+
+ set_cnt = cnt_from_rpm(val, data->clk_freq,
+ G762_PULSE_FROM_REG(cmd1),
+ G762_CLKDIV_FROM_REG(cmd1),
+ G762_GEARMULT_FROM_REG(cmd2));
+ ret = regmap_write(regmap, G762_REG_SET_CNT, set_cnt);
+unlock:
+ mutex_unlock(&data->update_lock);
return ret;
}
/* Set fan startup voltage. Accepted values are either 0, 1, 2 or 3. */
static int do_set_fan_startv(struct device *dev, unsigned long val)
{
- struct g762_data *data = g762_update_client(dev);
- int ret;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
+ struct g762_data *data = dev_get_drvdata(dev);
if (val > 3)
return -EINVAL;
- mutex_lock(&data->update_lock);
- data->fan_cmd2 &= ~G762_REG_FAN_CMD2_FAN_STARTV_MASK;
- data->fan_cmd2 |= FIELD_PREP(G762_REG_FAN_CMD2_FAN_STARTV_MASK, val);
- ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
- data->fan_cmd2);
- data->valid = false;
- mutex_unlock(&data->update_lock);
-
- return ret;
+ return regmap_update_bits(data->regmap, G762_REG_FAN_CMD2,
+ G762_REG_FAN_CMD2_FAN_STARTV_MASK,
+ FIELD_PREP(G762_REG_FAN_CMD2_FAN_STARTV_MASK, val));
}
/*
* sysfs attributes
*/
+static int get_fan_rpm_locked(struct g762_data *data, int reg)
+{
+ struct regmap *regmap = data->regmap;
+ u32 cmd1, cmd2, count;
+ int ret;
+
+ ret = regmap_read(regmap, reg, &count);
+ if (ret)
+ return ret;
+ ret = regmap_read(regmap, G762_REG_FAN_CMD1, &cmd1);
+ if (ret)
+ return ret;
+ ret = regmap_read(regmap, G762_REG_FAN_CMD2, &cmd2);
+ if (ret)
+ return ret;
+
+ return rpm_from_cnt(count, data->clk_freq,
+ G762_PULSE_FROM_REG(cmd1),
+ G762_CLKDIV_FROM_REG(cmd1),
+ G762_GEARMULT_FROM_REG(cmd2));
+}
+
+static int get_fan_rpm(struct g762_data *data, int reg)
+{
+ int ret;
+
+ mutex_lock(&data->update_lock);
+ ret = get_fan_rpm_locked(data, reg);
+ mutex_unlock(&data->update_lock);
+
+ return ret;
+}
+
/*
* Read function for fan1_input sysfs file. Return current fan RPM value, or
* 0 if fan is out of control.
@@ -511,23 +353,24 @@ static int do_set_fan_startv(struct device *dev, unsigned long val)
static ssize_t fan1_input_show(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct g762_data *data = g762_update_client(dev);
- unsigned int rpm = 0;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 status;
+ int ret;
mutex_lock(&data->update_lock);
+ ret = regmap_read(data->regmap, G762_REG_FAN_STA, &status);
/* reverse logic: fan out of control reporting is enabled low */
- if (data->fan_sta & G762_REG_FAN_STA_OOC) {
- rpm = rpm_from_cnt(data->act_cnt, data->clk_freq,
- G762_PULSE_FROM_REG(data->fan_cmd1),
- G762_CLKDIV_FROM_REG(data->fan_cmd1),
- G762_GEARMULT_FROM_REG(data->fan_cmd2));
- }
- mutex_unlock(&data->update_lock);
+ if (ret || !(status & G762_REG_FAN_STA_OOC))
+ goto unlock;
- return sprintf(buf, "%u\n", rpm);
+ ret = get_fan_rpm_locked(data, G762_REG_ACT_CNT);
+ if (ret < 0)
+ goto unlock;
+
+ ret = sprintf(buf, "%u\n", ret);
+unlock:
+ mutex_unlock(&data->update_lock);
+ return ret;
}
/*
@@ -537,13 +380,15 @@ static ssize_t fan1_input_show(struct device *dev,
static ssize_t pwm1_mode_show(struct device *dev, struct device_attribute *da,
char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 cmd1;
+ int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1);
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%d\n",
- !!(data->fan_cmd1 & G762_REG_FAN_CMD1_OUT_MODE));
+ return sprintf(buf, "%d\n", !!(cmd1 & G762_REG_FAN_CMD1_OUT_MODE));
}
static ssize_t pwm1_mode_store(struct device *dev,
@@ -570,12 +415,15 @@ static ssize_t pwm1_mode_store(struct device *dev,
static ssize_t fan1_div_show(struct device *dev, struct device_attribute *da,
char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 cmd1;
+ int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1);
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%ld\n", G762_CLKDIV_FROM_REG(data->fan_cmd1));
+ return sprintf(buf, "%ld\n", G762_CLKDIV_FROM_REG(cmd1));
}
static ssize_t fan1_div_store(struct device *dev, struct device_attribute *da,
@@ -601,12 +449,15 @@ static ssize_t fan1_div_store(struct device *dev, struct device_attribute *da,
static ssize_t fan1_pulses_show(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 cmd1;
+ int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1);
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%ld\n", G762_PULSE_FROM_REG(data->fan_cmd1));
+ return sprintf(buf, "%ld\n", G762_PULSE_FROM_REG(cmd1));
}
static ssize_t fan1_pulses_store(struct device *dev,
@@ -643,13 +494,16 @@ static ssize_t fan1_pulses_store(struct device *dev,
static ssize_t pwm1_enable_show(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 cmd1;
+ int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_FAN_CMD1, &cmd1);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n",
- (!!(data->fan_cmd1 & G762_REG_FAN_CMD1_FAN_MODE)) + 1);
+ !!(cmd1 & G762_REG_FAN_CMD1_FAN_MODE) + 1);
}
static ssize_t pwm1_enable_store(struct device *dev,
@@ -677,12 +531,15 @@ static ssize_t pwm1_enable_store(struct device *dev,
static ssize_t pwm1_show(struct device *dev, struct device_attribute *da,
char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ int ret;
+ u32 pwm;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_SET_OUT, &pwm);
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%d\n", data->set_out);
+ return sprintf(buf, "%u\n", pwm);
}
static ssize_t pwm1_store(struct device *dev, struct device_attribute *da,
@@ -715,20 +572,14 @@ static ssize_t pwm1_store(struct device *dev, struct device_attribute *da,
static ssize_t fan1_target_show(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct g762_data *data = g762_update_client(dev);
- unsigned int rpm;
+ struct g762_data *data = dev_get_drvdata(dev);
+ int rpm;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ rpm = get_fan_rpm(data, G762_REG_SET_CNT);
+ if (rpm < 0)
+ return rpm;
- mutex_lock(&data->update_lock);
- rpm = rpm_from_cnt(data->set_cnt, data->clk_freq,
- G762_PULSE_FROM_REG(data->fan_cmd1),
- G762_CLKDIV_FROM_REG(data->fan_cmd1),
- G762_GEARMULT_FROM_REG(data->fan_cmd2));
- mutex_unlock(&data->update_lock);
-
- return sprintf(buf, "%u\n", rpm);
+ return sprintf(buf, "%d\n", rpm);
}
static ssize_t fan1_target_store(struct device *dev,
@@ -752,12 +603,15 @@ static ssize_t fan1_target_store(struct device *dev,
static ssize_t fan1_fault_show(struct device *dev, struct device_attribute *da,
char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 status;
+ int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_FAN_STA, &status);
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%u\n", !!(data->fan_sta & G762_REG_FAN_STA_FAIL));
+ return sprintf(buf, "%u\n", !!(status & G762_REG_FAN_STA_FAIL));
}
/*
@@ -767,12 +621,15 @@ static ssize_t fan1_fault_show(struct device *dev, struct device_attribute *da,
static ssize_t fan1_alarm_show(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
+ u32 status;
+ int ret;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ ret = regmap_read(data->regmap, G762_REG_FAN_STA, &status);
+ if (ret < 0)
+ return ret;
- return sprintf(buf, "%u\n", !(data->fan_sta & G762_REG_FAN_STA_OOC));
+ return sprintf(buf, "%u\n", !(status & G762_REG_FAN_STA_OOC));
}
static DEVICE_ATTR_RW(pwm1);
@@ -802,23 +659,14 @@ static struct attribute *g762_attrs[] = {
ATTRIBUTE_GROUPS(g762);
/*
- * Enable both fan failure detection and fan out of control protection. The
- * function does not protect change/access to data structure; it must thus
- * only be called during initialization.
+ * Enable both fan failure detection and fan out of control protection.
*/
static inline int g762_fan_init(struct device *dev)
{
- struct g762_data *data = g762_update_client(dev);
+ struct g762_data *data = dev_get_drvdata(dev);
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_FAIL;
- data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC;
- data->valid = false;
-
- return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
+ return regmap_set_bits(data->regmap, G762_REG_FAN_CMD1,
+ G762_REG_FAN_CMD1_DET_FAN_FAIL | G762_REG_FAN_CMD1_DET_FAN_OOC);
}
/*
@@ -880,6 +728,26 @@ static int g762_configure(struct device *dev)
return 0;
}
+static bool g762_writeable_reg(struct device *dev, unsigned int reg)
+{
+ return reg == G762_REG_SET_CNT || reg == G762_REG_SET_OUT ||
+ reg == G762_REG_FAN_CMD1 || reg == G762_REG_FAN_CMD2;
+}
+
+static bool g762_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return reg == G762_REG_ACT_CNT || reg == G762_REG_FAN_STA;
+}
+
+static const struct regmap_config g762_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = G762_REG_FAN_CMD2,
+ .writeable_reg = g762_writeable_reg,
+ .volatile_reg = g762_volatile_reg,
+ .cache_type = REGCACHE_MAPLE,
+};
+
static int g762_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -887,16 +755,15 @@ static int g762_probe(struct i2c_client *client)
struct g762_data *data;
int ret;
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_BYTE_DATA))
- return -ENODEV;
-
data = devm_kzalloc(dev, sizeof(struct g762_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ data->regmap = devm_regmap_init_i2c(client, &g762_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
dev_set_drvdata(dev, data);
- data->client = client;
mutex_init(&data->update_lock);
ret = g762_configure(dev);
Use regmap for caching and regmap operations for register bit manipulations to simplify the code. No functional change intended. Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Documentation/hwmon/g762.rst | 2 - drivers/hwmon/g762.c | 523 +++++++++++++---------------------- 2 files changed, 195 insertions(+), 330 deletions(-)