hwmon: (adt7475) Add attenuator bypass support

Added support for reading DTS properties to set attenuators on
device probe for the ADT7473, ADT7475, ADT7476, and ADT7490.

Signed-off-by: Logan Shaw <logan.shaw@alliedtelesis.co.nz>
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
[groeck: Continuation line formatting; dev_err -> dev_warn]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Logan Shaw 2020-02-27 21:46:41 +13:00 committed by Guenter Roeck
parent ed39ff506a
commit 2ecff39791

View File

@ -19,6 +19,7 @@
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/util_macros.h> #include <linux/util_macros.h>
/* Indexes for the sysfs hooks */ /* Indexes for the sysfs hooks */
@ -193,6 +194,7 @@ struct adt7475_data {
unsigned long measure_updated; unsigned long measure_updated;
bool valid; bool valid;
u8 config2;
u8 config4; u8 config4;
u8 config5; u8 config5;
u8 has_voltage; u8 has_voltage;
@ -1458,6 +1460,55 @@ static int adt7475_update_limits(struct i2c_client *client)
return 0; return 0;
} }
static int set_property_bit(const struct i2c_client *client, char *property,
u8 *config, u8 bit_index)
{
u32 prop_value = 0;
int ret = of_property_read_u32(client->dev.of_node, property,
&prop_value);
if (!ret) {
if (prop_value)
*config |= (1 << bit_index);
else
*config &= ~(1 << bit_index);
}
return ret;
}
static int load_attenuators(const struct i2c_client *client, int chip,
struct adt7475_data *data)
{
int ret;
if (chip == adt7476 || chip == adt7490) {
set_property_bit(client, "adi,bypass-attenuator-in0",
&data->config4, 4);
set_property_bit(client, "adi,bypass-attenuator-in1",
&data->config4, 5);
set_property_bit(client, "adi,bypass-attenuator-in3",
&data->config4, 6);
set_property_bit(client, "adi,bypass-attenuator-in4",
&data->config4, 7);
ret = i2c_smbus_write_byte_data(client, REG_CONFIG4,
data->config4);
if (ret < 0)
return ret;
} else if (chip == adt7473 || chip == adt7475) {
set_property_bit(client, "adi,bypass-attenuator-in1",
&data->config2, 5);
ret = i2c_smbus_write_byte_data(client, REG_CONFIG2,
data->config2);
if (ret < 0)
return ret;
}
return 0;
}
static int adt7475_probe(struct i2c_client *client, static int adt7475_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
@ -1472,7 +1523,7 @@ static int adt7475_probe(struct i2c_client *client,
struct adt7475_data *data; struct adt7475_data *data;
struct device *hwmon_dev; struct device *hwmon_dev;
int i, ret = 0, revision, group_num = 0; int i, ret = 0, revision, group_num = 0;
u8 config2, config3; u8 config3;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (data == NULL) if (data == NULL)
@ -1546,8 +1597,12 @@ static int adt7475_probe(struct i2c_client *client,
} }
/* Voltage attenuators can be bypassed, globally or individually */ /* Voltage attenuators can be bypassed, globally or individually */
config2 = adt7475_read(REG_CONFIG2); data->config2 = adt7475_read(REG_CONFIG2);
if (config2 & CONFIG2_ATTN) { ret = load_attenuators(client, chip, data);
if (ret)
dev_warn(&client->dev, "Error configuring attenuator bypass\n");
if (data->config2 & CONFIG2_ATTN) {
data->bypass_attn = (0x3 << 3) | 0x3; data->bypass_attn = (0x3 << 3) | 0x3;
} else { } else {
data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) | data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) |