Commit 2ecff397 authored by Logan Shaw's avatar Logan Shaw Committed by Guenter Roeck
Browse files

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: default avatarLogan Shaw <logan.shaw@alliedtelesis.co.nz>
Signed-off-by: default avatarChris Packham <chris.packham@alliedtelesis.co.nz>
[groeck: Continuation line formatting; dev_err -> dev_warn]
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent ed39ff50
Loading
Loading
Loading
Loading
+58 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/util_macros.h>

/* Indexes for the sysfs hooks */
@@ -193,6 +194,7 @@ struct adt7475_data {
	unsigned long measure_updated;
	bool valid;

	u8 config2;
	u8 config4;
	u8 config5;
	u8 has_voltage;
@@ -1458,6 +1460,55 @@ static int adt7475_update_limits(struct i2c_client *client)
	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,
			 const struct i2c_device_id *id)
{
@@ -1472,7 +1523,7 @@ static int adt7475_probe(struct i2c_client *client,
	struct adt7475_data *data;
	struct device *hwmon_dev;
	int i, ret = 0, revision, group_num = 0;
	u8 config2, config3;
	u8 config3;

	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
	if (data == NULL)
@@ -1546,8 +1597,12 @@ static int adt7475_probe(struct i2c_client *client,
	}

	/* Voltage attenuators can be bypassed, globally or individually */
	config2 = adt7475_read(REG_CONFIG2);
	if (config2 & CONFIG2_ATTN) {
	data->config2 = adt7475_read(REG_CONFIG2);
	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;
	} else {
		data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) |