diff options
Diffstat (limited to 'drivers/hwmon/tmp401.c')
| -rw-r--r-- | drivers/hwmon/tmp401.c | 863 | 
1 files changed, 431 insertions, 432 deletions
| diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index b31f4964f852..b86d9df7105d 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c @@ -18,17 +18,15 @@   * and thus has 16 bits registers for its value and limit instead of 8 bits.   */ -#include <linux/module.h> -#include <linux/init.h>  #include <linux/bitops.h> -#include <linux/slab.h> -#include <linux/jiffies.h> +#include <linux/err.h>  #include <linux/i2c.h>  #include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> -#include <linux/err.h> +#include <linux/init.h> +#include <linux/module.h>  #include <linux/mutex.h> -#include <linux/sysfs.h> +#include <linux/regmap.h> +#include <linux/slab.h>  /* Addresses to scan */  static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, 0x4d, @@ -41,44 +39,19 @@ enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 };   * reading and writing   */  #define TMP401_STATUS				0x02 -#define TMP401_CONFIG_READ			0x03 -#define TMP401_CONFIG_WRITE			0x09 -#define TMP401_CONVERSION_RATE_READ		0x04 -#define TMP401_CONVERSION_RATE_WRITE		0x0A +#define TMP401_CONFIG				0x03 +#define TMP401_CONVERSION_RATE			0x04  #define TMP401_TEMP_CRIT_HYST			0x21  #define TMP401_MANUFACTURER_ID_REG		0xFE  #define TMP401_DEVICE_ID_REG			0xFF -static const u8 TMP401_TEMP_MSB_READ[7][2] = { -	{ 0x00, 0x01 },	/* temp */ -	{ 0x06, 0x08 },	/* low limit */ -	{ 0x05, 0x07 },	/* high limit */ -	{ 0x20, 0x19 },	/* therm (crit) limit */ -	{ 0x30, 0x34 },	/* lowest */ -	{ 0x32, 0x36 },	/* highest */ -}; - -static const u8 TMP401_TEMP_MSB_WRITE[7][2] = { -	{ 0, 0 },	/* temp (unused) */ -	{ 0x0C, 0x0E },	/* low limit */ -	{ 0x0B, 0x0D },	/* high limit */ -	{ 0x20, 0x19 },	/* therm (crit) limit */ -	{ 0x30, 0x34 },	/* lowest */ -	{ 0x32, 0x36 },	/* highest */ -}; - -static const u8 TMP432_TEMP_MSB_READ[4][3] = { +static const u8 TMP401_TEMP_MSB[7][3] = {  	{ 0x00, 0x01, 0x23 },	/* temp */  	{ 0x06, 0x08, 0x16 },	/* low limit */  	{ 0x05, 0x07, 0x15 },	/* high limit */ -	{ 0x20, 0x19, 0x1A },	/* therm (crit) limit */ -}; - -static const u8 TMP432_TEMP_MSB_WRITE[4][3] = { -	{ 0, 0, 0 },		/* temp  - unused */ -	{ 0x0C, 0x0E, 0x16 },	/* low limit */ -	{ 0x0B, 0x0D, 0x15 },	/* high limit */ -	{ 0x20, 0x19, 0x1A },	/* therm (crit) limit */ +	{ 0x20, 0x19, 0x1a },	/* therm (crit) limit */ +	{ 0x30, 0x34, 0x00 },	/* lowest */ +	{ 0x32, 0xf6, 0x00 },	/* highest */  };  /* [0] = fault, [1] = low, [2] = high, [3] = therm/crit */ @@ -131,311 +104,323 @@ MODULE_DEVICE_TABLE(i2c, tmp401_id);  struct tmp401_data {  	struct i2c_client *client; -	const struct attribute_group *groups[3]; +	struct regmap *regmap;  	struct mutex update_lock; -	bool valid; /* false until following fields are valid */ -	unsigned long last_updated; /* in jiffies */  	enum chips kind; -	unsigned int update_interval;	/* in milliseconds */ +	bool extended_range; -	/* register values */ -	u8 status[4]; -	u8 config; -	u16 temp[7][3]; -	u8 temp_crit_hyst; +	/* hwmon API configuration data */ +	u32 chip_channel_config[4]; +	struct hwmon_channel_info chip_info; +	u32 temp_channel_config[4]; +	struct hwmon_channel_info temp_info; +	const struct hwmon_channel_info *info[3]; +	struct hwmon_chip_info chip;  }; -/* - * Sysfs attr show / store functions - */ - -static int tmp401_register_to_temp(u16 reg, u8 config) -{ -	int temp = reg; - -	if (config & TMP401_CONFIG_RANGE) -		temp -= 64 * 256; - -	return DIV_ROUND_CLOSEST(temp * 125, 32); -} +/* regmap */ -static u16 tmp401_temp_to_register(long temp, u8 config, int zbits) +static bool tmp401_regmap_is_volatile(struct device *dev, unsigned int reg)  { -	if (config & TMP401_CONFIG_RANGE) { -		temp = clamp_val(temp, -64000, 191000); -		temp += 64000; -	} else -		temp = clamp_val(temp, 0, 127000); - -	return DIV_ROUND_CLOSEST(temp * (1 << (8 - zbits)), 1000) << zbits; -} - -static int tmp401_update_device_reg16(struct i2c_client *client, -				      struct tmp401_data *data) -{ -	int i, j, val; -	int num_regs = data->kind == tmp411 ? 6 : 4; -	int num_sensors = data->kind == tmp432 ? 3 : 2; - -	for (i = 0; i < num_sensors; i++) {		/* local / r1 / r2 */ -		for (j = 0; j < num_regs; j++) {	/* temp / low / ... */ -			u8 regaddr; - -			regaddr = data->kind == tmp432 ? -						TMP432_TEMP_MSB_READ[j][i] : -						TMP401_TEMP_MSB_READ[j][i]; -			if (j == 3) { /* crit is msb only */ -				val = i2c_smbus_read_byte_data(client, regaddr); -			} else { -				val = i2c_smbus_read_word_swapped(client, -								  regaddr); -			} -			if (val < 0) -				return val; - -			data->temp[j][i] = j == 3 ? val << 8 : val; -		} +	switch (reg) { +	case 0:			/* local temp msb */ +	case 1:			/* remote temp msb */ +	case 2:			/* status */ +	case 0x10:		/* remote temp lsb */ +	case 0x15:		/* local temp lsb */ +	case 0x1b:		/* status (tmp432) */ +	case 0x23 ... 0x24:	/* remote temp 2 msb / lsb */ +	case 0x30 ... 0x37:	/* lowest/highest temp; status (tmp432) */ +		return true; +	default: +		return false;  	} -	return 0;  } -static struct tmp401_data *tmp401_update_device(struct device *dev) +static int tmp401_reg_read(void *context, unsigned int reg, unsigned int *val)  { -	struct tmp401_data *data = dev_get_drvdata(dev); +	struct tmp401_data *data = context;  	struct i2c_client *client = data->client; -	struct tmp401_data *ret = data; -	int i, val; -	unsigned long next_update; - -	mutex_lock(&data->update_lock); +	int regval; -	next_update = data->last_updated + -		      msecs_to_jiffies(data->update_interval); -	if (time_after(jiffies, next_update) || !data->valid) { -		if (data->kind != tmp432) { -			/* -			 * The driver uses the TMP432 status format internally. -			 * Convert status to TMP432 format for other chips. -			 */ -			val = i2c_smbus_read_byte_data(client, TMP401_STATUS); -			if (val < 0) { -				ret = ERR_PTR(val); -				goto abort; -			} -			data->status[0] = -			  (val & TMP401_STATUS_REMOTE_OPEN) >> 1; -			data->status[1] = -			  ((val & TMP401_STATUS_REMOTE_LOW) >> 2) | -			  ((val & TMP401_STATUS_LOCAL_LOW) >> 5); -			data->status[2] = -			  ((val & TMP401_STATUS_REMOTE_HIGH) >> 3) | -			  ((val & TMP401_STATUS_LOCAL_HIGH) >> 6); -			data->status[3] = val & (TMP401_STATUS_LOCAL_CRIT -						| TMP401_STATUS_REMOTE_CRIT); -		} else { -			for (i = 0; i < ARRAY_SIZE(data->status); i++) { -				val = i2c_smbus_read_byte_data(client, -							TMP432_STATUS_REG[i]); -				if (val < 0) { -					ret = ERR_PTR(val); -					goto abort; -				} -				data->status[i] = val; -			} -		} - -		val = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); -		if (val < 0) { -			ret = ERR_PTR(val); -			goto abort; -		} -		data->config = val; -		val = tmp401_update_device_reg16(client, data); -		if (val < 0) { -			ret = ERR_PTR(val); -			goto abort; +	switch (reg) { +	case 0:			/* local temp msb */ +	case 1:			/* remote temp msb */ +	case 5:			/* local temp high limit msb */ +	case 6:			/* local temp low limit msb */ +	case 7:			/* remote temp ligh limit msb */ +	case 8:			/* remote temp low limit msb */ +	case 0x15:		/* remote temp 2 high limit msb */ +	case 0x16:		/* remote temp 2 low limit msb */ +	case 0x23:		/* remote temp 2 msb */ +	case 0x30:		/* local temp minimum, tmp411 */ +	case 0x32:		/* local temp maximum, tmp411 */ +	case 0x34:		/* remote temp minimum, tmp411 */ +	case 0xf6:		/* remote temp maximum, tmp411 (really 0x36) */ +		/* work around register overlap between TMP411 and TMP432 */ +		if (reg == 0xf6) +			reg = 0x36; +		regval = i2c_smbus_read_word_swapped(client, reg); +		if (regval < 0) +			return regval; +		*val = regval; +		break; +	case 0x19:		/* critical limits, 8-bit registers */ +	case 0x1a: +	case 0x20: +		regval = i2c_smbus_read_byte_data(client, reg); +		if (regval < 0) +			return regval; +		*val = regval << 8; +		break; +	case 0x1b: +	case 0x35 ... 0x37: +		if (data->kind == tmp432) { +			regval = i2c_smbus_read_byte_data(client, reg); +			if (regval < 0) +				return regval; +			*val = regval; +			break;  		} -		val = i2c_smbus_read_byte_data(client, TMP401_TEMP_CRIT_HYST); -		if (val < 0) { -			ret = ERR_PTR(val); -			goto abort; +		/* simulate TMP432 status registers */ +		regval = i2c_smbus_read_byte_data(client, TMP401_STATUS); +		if (regval < 0) +			return regval; +		*val = 0; +		switch (reg) { +		case 0x1b:	/* open / fault */ +			if (regval & TMP401_STATUS_REMOTE_OPEN) +				*val |= BIT(1); +			break; +		case 0x35:	/* high limit */ +			if (regval & TMP401_STATUS_LOCAL_HIGH) +				*val |= BIT(0); +			if (regval & TMP401_STATUS_REMOTE_HIGH) +				*val |= BIT(1); +			break; +		case 0x36:	/* low limit */ +			if (regval & TMP401_STATUS_LOCAL_LOW) +				*val |= BIT(0); +			if (regval & TMP401_STATUS_REMOTE_LOW) +				*val |= BIT(1); +			break; +		case 0x37:	/* therm / crit limit */ +			if (regval & TMP401_STATUS_LOCAL_CRIT) +				*val |= BIT(0); +			if (regval & TMP401_STATUS_REMOTE_CRIT) +				*val |= BIT(1); +			break;  		} -		data->temp_crit_hyst = val; - -		data->last_updated = jiffies; -		data->valid = true; +		break; +	default: +		regval = i2c_smbus_read_byte_data(client, reg); +		if (regval < 0) +			return regval; +		*val = regval; +		break;  	} - -abort: -	mutex_unlock(&data->update_lock); -	return ret; +	return 0;  } -static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, -			 char *buf) +static int tmp401_reg_write(void *context, unsigned int reg, unsigned int val)  { -	int nr = to_sensor_dev_attr_2(devattr)->nr; -	int index = to_sensor_dev_attr_2(devattr)->index; -	struct tmp401_data *data = tmp401_update_device(dev); - -	if (IS_ERR(data)) -		return PTR_ERR(data); +	struct tmp401_data *data = context; +	struct i2c_client *client = data->client; -	return sprintf(buf, "%d\n", -		tmp401_register_to_temp(data->temp[nr][index], data->config)); +	switch (reg) { +	case 0x05:		/* local temp high limit msb */ +	case 0x06:		/* local temp low limit msb */ +	case 0x07:		/* remote temp ligh limit msb */ +	case 0x08:		/* remote temp low limit msb */ +		reg += 6;	/* adjust for register write address */ +		fallthrough; +	case 0x15:		/* remote temp 2 high limit msb */ +	case 0x16:		/* remote temp 2 low limit msb */ +		return i2c_smbus_write_word_swapped(client, reg, val); +	case 0x19:		/* critical limits, 8-bit registers */ +	case 0x1a: +	case 0x20: +		return i2c_smbus_write_byte_data(client, reg, val >> 8); +	case TMP401_CONVERSION_RATE: +	case TMP401_CONFIG: +		reg += 6;	/* adjust for register write address */ +		fallthrough; +	default: +		return i2c_smbus_write_byte_data(client, reg, val); +	}  } -static ssize_t temp_crit_hyst_show(struct device *dev, -				   struct device_attribute *devattr, -				   char *buf) -{ -	int temp, index = to_sensor_dev_attr(devattr)->index; -	struct tmp401_data *data = tmp401_update_device(dev); - -	if (IS_ERR(data)) -		return PTR_ERR(data); - -	mutex_lock(&data->update_lock); -	temp = tmp401_register_to_temp(data->temp[3][index], data->config); -	temp -= data->temp_crit_hyst * 1000; -	mutex_unlock(&data->update_lock); +static const struct regmap_config tmp401_regmap_config = { +	.reg_bits = 8, +	.val_bits = 16, +	.cache_type = REGCACHE_RBTREE, +	.volatile_reg = tmp401_regmap_is_volatile, +	.reg_read = tmp401_reg_read, +	.reg_write = tmp401_reg_write, +}; -	return sprintf(buf, "%d\n", temp); -} +/* temperature conversion */ -static ssize_t status_show(struct device *dev, -			   struct device_attribute *devattr, char *buf) +static int tmp401_register_to_temp(u16 reg, bool extended)  { -	int nr = to_sensor_dev_attr_2(devattr)->nr; -	int mask = to_sensor_dev_attr_2(devattr)->index; -	struct tmp401_data *data = tmp401_update_device(dev); +	int temp = reg; -	if (IS_ERR(data)) -		return PTR_ERR(data); +	if (extended) +		temp -= 64 * 256; -	return sprintf(buf, "%d\n", !!(data->status[nr] & mask)); +	return DIV_ROUND_CLOSEST(temp * 125, 32);  } -static ssize_t temp_store(struct device *dev, -			  struct device_attribute *devattr, const char *buf, -			  size_t count) +static u16 tmp401_temp_to_register(long temp, bool extended, int zbits)  { -	int nr = to_sensor_dev_attr_2(devattr)->nr; -	int index = to_sensor_dev_attr_2(devattr)->index; -	struct tmp401_data *data = dev_get_drvdata(dev); -	struct i2c_client *client = data->client; -	long val; -	u16 reg; -	u8 regaddr; - -	if (kstrtol(buf, 10, &val)) -		return -EINVAL; - -	reg = tmp401_temp_to_register(val, data->config, nr == 3 ? 8 : 4); - -	mutex_lock(&data->update_lock); - -	regaddr = data->kind == tmp432 ? TMP432_TEMP_MSB_WRITE[nr][index] -				       : TMP401_TEMP_MSB_WRITE[nr][index]; -	if (nr == 3) { /* crit is msb only */ -		i2c_smbus_write_byte_data(client, regaddr, reg >> 8); +	if (extended) { +		temp = clamp_val(temp, -64000, 191000); +		temp += 64000;  	} else { -		/* Hardware expects big endian data --> use _swapped */ -		i2c_smbus_write_word_swapped(client, regaddr, reg); +		temp = clamp_val(temp, 0, 127000);  	} -	data->temp[nr][index] = reg; - -	mutex_unlock(&data->update_lock); -	return count; +	return DIV_ROUND_CLOSEST(temp * (1 << (8 - zbits)), 1000) << zbits;  } -static ssize_t temp_crit_hyst_store(struct device *dev, -				    struct device_attribute *devattr, -				    const char *buf, size_t count) -{ -	int temp, index = to_sensor_dev_attr(devattr)->index; -	struct tmp401_data *data = tmp401_update_device(dev); -	long val; -	u8 reg; - -	if (IS_ERR(data)) -		return PTR_ERR(data); - -	if (kstrtol(buf, 10, &val)) -		return -EINVAL; - -	if (data->config & TMP401_CONFIG_RANGE) -		val = clamp_val(val, -64000, 191000); -	else -		val = clamp_val(val, 0, 127000); - -	mutex_lock(&data->update_lock); -	temp = tmp401_register_to_temp(data->temp[3][index], data->config); -	val = clamp_val(val, temp - 255000, temp); -	reg = ((temp - val) + 500) / 1000; - -	i2c_smbus_write_byte_data(data->client, TMP401_TEMP_CRIT_HYST, -				  reg); +/* hwmon API functions */ -	data->temp_crit_hyst = reg; +static const u8 tmp401_temp_reg_index[] = { +	[hwmon_temp_input] = 0, +	[hwmon_temp_min] = 1, +	[hwmon_temp_max] = 2, +	[hwmon_temp_crit] = 3, +	[hwmon_temp_lowest] = 4, +	[hwmon_temp_highest] = 5, +}; -	mutex_unlock(&data->update_lock); +static const u8 tmp401_status_reg_index[] = { +	[hwmon_temp_fault] = 0, +	[hwmon_temp_min_alarm] = 1, +	[hwmon_temp_max_alarm] = 2, +	[hwmon_temp_crit_alarm] = 3, +}; -	return count; +static int tmp401_temp_read(struct device *dev, u32 attr, int channel, long *val) +{ +	struct tmp401_data *data = dev_get_drvdata(dev); +	struct regmap *regmap = data->regmap; +	unsigned int regval; +	int reg, ret; + +	switch (attr) { +	case hwmon_temp_input: +	case hwmon_temp_min: +	case hwmon_temp_max: +	case hwmon_temp_crit: +	case hwmon_temp_lowest: +	case hwmon_temp_highest: +		reg = TMP401_TEMP_MSB[tmp401_temp_reg_index[attr]][channel]; +		ret = regmap_read(regmap, reg, ®val); +		if (ret < 0) +			return ret; +		*val = tmp401_register_to_temp(regval, data->extended_range); +		break; +	case hwmon_temp_crit_hyst: +		mutex_lock(&data->update_lock); +		reg = TMP401_TEMP_MSB[3][channel]; +		ret = regmap_read(regmap, reg, ®val); +		if (ret < 0) +			goto unlock; +		*val = tmp401_register_to_temp(regval, data->extended_range); +		ret = regmap_read(regmap, TMP401_TEMP_CRIT_HYST, ®val); +		if (ret < 0) +			goto unlock; +		*val -= regval * 1000; +unlock: +		mutex_unlock(&data->update_lock); +		if (ret < 0) +			return ret; +		break; +	case hwmon_temp_fault: +	case hwmon_temp_min_alarm: +	case hwmon_temp_max_alarm: +	case hwmon_temp_crit_alarm: +		reg = TMP432_STATUS_REG[tmp401_status_reg_index[attr]]; +		ret = regmap_read(regmap, reg, ®val); +		if (ret < 0) +			return ret; +		*val = !!(regval & BIT(channel)); +		break; +	default: +		return -EOPNOTSUPP; +	} +	return 0;  } -/* - * Resets the historical measurements of minimum and maximum temperatures. - * This is done by writing any value to any of the minimum/maximum registers - * (0x30-0x37). - */ -static ssize_t reset_temp_history_store(struct device *dev, -					struct device_attribute *devattr, -					const char *buf, size_t count) +static int tmp401_temp_write(struct device *dev, u32 attr, int channel, +			     long val)  {  	struct tmp401_data *data = dev_get_drvdata(dev); -	struct i2c_client *client = data->client; -	long val; - -	if (kstrtol(buf, 10, &val)) -		return -EINVAL; +	struct regmap *regmap = data->regmap; +	unsigned int regval; +	int reg, ret, temp; -	if (val != 1) { -		dev_err(dev, -			"temp_reset_history value %ld not supported. Use 1 to reset the history!\n", -			val); -		return -EINVAL; -	}  	mutex_lock(&data->update_lock); -	i2c_smbus_write_byte_data(client, TMP401_TEMP_MSB_WRITE[5][0], val); -	data->valid = false; +	switch (attr) { +	case hwmon_temp_min: +	case hwmon_temp_max: +	case hwmon_temp_crit: +		reg = TMP401_TEMP_MSB[tmp401_temp_reg_index[attr]][channel]; +		regval = tmp401_temp_to_register(val, data->extended_range, +						 attr == hwmon_temp_crit ? 8 : 4); +		ret = regmap_write(regmap, reg, regval); +		break; +	case hwmon_temp_crit_hyst: +		if (data->extended_range) +			val = clamp_val(val, -64000, 191000); +		else +			val = clamp_val(val, 0, 127000); + +		reg = TMP401_TEMP_MSB[3][channel]; +		ret = regmap_read(regmap, reg, ®val); +		if (ret < 0) +			break; +		temp = tmp401_register_to_temp(regval, data->extended_range); +		val = clamp_val(val, temp - 255000, temp); +		regval = ((temp - val) + 500) / 1000; +		ret = regmap_write(regmap, TMP401_TEMP_CRIT_HYST, regval); +		break; +	default: +		ret = -EOPNOTSUPP; +		break; +	}  	mutex_unlock(&data->update_lock); - -	return count; +	return ret;  } -static ssize_t update_interval_show(struct device *dev, -				    struct device_attribute *attr, char *buf) +static int tmp401_chip_read(struct device *dev, u32 attr, int channel, long *val)  {  	struct tmp401_data *data = dev_get_drvdata(dev); +	u32 regval; +	int ret; + +	switch (attr) { +	case hwmon_chip_update_interval: +		ret = regmap_read(data->regmap, TMP401_CONVERSION_RATE, ®val); +		if (ret < 0) +			return ret; +		*val = (1 << (7 - regval)) * 125; +		break; +	case hwmon_chip_temp_reset_history: +		*val = 0; +		break; +	default: +		return -EOPNOTSUPP; +	} -	return sprintf(buf, "%u\n", data->update_interval); +	return 0;  } -static ssize_t update_interval_store(struct device *dev, -				     struct device_attribute *attr, -				     const char *buf, size_t count) +static int tmp401_set_convrate(struct regmap *regmap, long val)  { -	struct tmp401_data *data = dev_get_drvdata(dev); -	struct i2c_client *client = data->client; -	unsigned long val; -	int err, rate; - -	err = kstrtoul(buf, 10, &val); -	if (err) -		return err; +	int rate;  	/*  	 * For valid rates, interval can be calculated as @@ -447,153 +432,137 @@ static ssize_t update_interval_store(struct device *dev,  	 */  	val = clamp_val(val, 125, 16000);  	rate = 7 - __fls(val * 4 / (125 * 3)); +	return regmap_write(regmap, TMP401_CONVERSION_RATE, rate); +} + +static int tmp401_chip_write(struct device *dev, u32 attr, int channel, long val) +{ +	struct tmp401_data *data = dev_get_drvdata(dev); +	struct regmap *regmap = data->regmap; +	int err; +  	mutex_lock(&data->update_lock); -	i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, rate); -	data->update_interval = (1 << (7 - rate)) * 125; +	switch (attr) { +	case hwmon_chip_update_interval: +		err = tmp401_set_convrate(regmap, val); +		break; +	case hwmon_chip_temp_reset_history: +		if (val != 1) { +			err = -EINVAL; +			break; +		} +		/* +		 * Reset history by writing any value to any of the +		 * minimum/maximum registers (0x30-0x37). +		 */ +		err = regmap_write(regmap, 0x30, 0); +		break; +	default: +		err = -EOPNOTSUPP; +		break; +	}  	mutex_unlock(&data->update_lock); -	return count; +	return err;  } -static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, 0, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_min, temp, 1, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, 2, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, 3, 0); -static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_crit_hyst, 0); -static SENSOR_DEVICE_ATTR_2_RO(temp1_min_alarm, status, 1, -			       TMP432_STATUS_LOCAL); -static SENSOR_DEVICE_ATTR_2_RO(temp1_max_alarm, status, 2, -			       TMP432_STATUS_LOCAL); -static SENSOR_DEVICE_ATTR_2_RO(temp1_crit_alarm, status, 3, -			       TMP432_STATUS_LOCAL); -static SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, 0, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_min, temp, 1, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp, 2, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_crit, temp, 3, 1); -static SENSOR_DEVICE_ATTR_RO(temp2_crit_hyst, temp_crit_hyst, 1); -static SENSOR_DEVICE_ATTR_2_RO(temp2_fault, status, 0, TMP432_STATUS_REMOTE1); -static SENSOR_DEVICE_ATTR_2_RO(temp2_min_alarm, status, 1, -			       TMP432_STATUS_REMOTE1); -static SENSOR_DEVICE_ATTR_2_RO(temp2_max_alarm, status, 2, -			       TMP432_STATUS_REMOTE1); -static SENSOR_DEVICE_ATTR_2_RO(temp2_crit_alarm, status, 3, -			       TMP432_STATUS_REMOTE1); - -static DEVICE_ATTR_RW(update_interval); - -static struct attribute *tmp401_attributes[] = { -	&sensor_dev_attr_temp1_input.dev_attr.attr, -	&sensor_dev_attr_temp1_min.dev_attr.attr, -	&sensor_dev_attr_temp1_max.dev_attr.attr, -	&sensor_dev_attr_temp1_crit.dev_attr.attr, -	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, -	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr, -	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr, -	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - -	&sensor_dev_attr_temp2_input.dev_attr.attr, -	&sensor_dev_attr_temp2_min.dev_attr.attr, -	&sensor_dev_attr_temp2_max.dev_attr.attr, -	&sensor_dev_attr_temp2_crit.dev_attr.attr, -	&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, -	&sensor_dev_attr_temp2_fault.dev_attr.attr, -	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr, -	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr, -	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - -	&dev_attr_update_interval.attr, - -	NULL -}; - -static const struct attribute_group tmp401_group = { -	.attrs = tmp401_attributes, -}; - -/* - * Additional features of the TMP411 chip. - * The TMP411 stores the minimum and maximum - * temperature measured since power-on, chip-reset, or - * minimum and maximum register reset for both the local - * and remote channels. - */ -static SENSOR_DEVICE_ATTR_2_RO(temp1_lowest, temp, 4, 0); -static SENSOR_DEVICE_ATTR_2_RO(temp1_highest, temp, 5, 0); -static SENSOR_DEVICE_ATTR_2_RO(temp2_lowest, temp, 4, 1); -static SENSOR_DEVICE_ATTR_2_RO(temp2_highest, temp, 5, 1); -static SENSOR_DEVICE_ATTR_WO(temp_reset_history, reset_temp_history, 0); - -static struct attribute *tmp411_attributes[] = { -	&sensor_dev_attr_temp1_highest.dev_attr.attr, -	&sensor_dev_attr_temp1_lowest.dev_attr.attr, -	&sensor_dev_attr_temp2_highest.dev_attr.attr, -	&sensor_dev_attr_temp2_lowest.dev_attr.attr, -	&sensor_dev_attr_temp_reset_history.dev_attr.attr, -	NULL -}; +static int tmp401_read(struct device *dev, enum hwmon_sensor_types type, +		       u32 attr, int channel, long *val) +{ +	switch (type) { +	case hwmon_chip: +		return tmp401_chip_read(dev, attr, channel, val); +	case hwmon_temp: +		return tmp401_temp_read(dev, attr, channel, val); +	default: +		return -EOPNOTSUPP; +	} +} -static const struct attribute_group tmp411_group = { -	.attrs = tmp411_attributes, -}; +static int tmp401_write(struct device *dev, enum hwmon_sensor_types type, +			u32 attr, int channel, long val) +{ +	switch (type) { +	case hwmon_chip: +		return tmp401_chip_write(dev, attr, channel, val); +	case hwmon_temp: +		return tmp401_temp_write(dev, attr, channel, val); +	default: +		return -EOPNOTSUPP; +	} +} -static SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, 0, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_min, temp, 1, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_max, temp, 2, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_crit, temp, 3, 2); -static SENSOR_DEVICE_ATTR_RO(temp3_crit_hyst, temp_crit_hyst, 2); -static SENSOR_DEVICE_ATTR_2_RO(temp3_fault, status, 0, TMP432_STATUS_REMOTE2); -static SENSOR_DEVICE_ATTR_2_RO(temp3_min_alarm, status, 1, -			       TMP432_STATUS_REMOTE2); -static SENSOR_DEVICE_ATTR_2_RO(temp3_max_alarm, status, 2, -			       TMP432_STATUS_REMOTE2); -static SENSOR_DEVICE_ATTR_2_RO(temp3_crit_alarm, status, 3, -			       TMP432_STATUS_REMOTE2); - -static struct attribute *tmp432_attributes[] = { -	&sensor_dev_attr_temp3_input.dev_attr.attr, -	&sensor_dev_attr_temp3_min.dev_attr.attr, -	&sensor_dev_attr_temp3_max.dev_attr.attr, -	&sensor_dev_attr_temp3_crit.dev_attr.attr, -	&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, -	&sensor_dev_attr_temp3_fault.dev_attr.attr, -	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr, -	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr, -	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - -	NULL -}; +static umode_t tmp401_is_visible(const void *data, enum hwmon_sensor_types type, +				 u32 attr, int channel) +{ +	switch (type) { +	case hwmon_chip: +		switch (attr) { +		case hwmon_chip_update_interval: +		case hwmon_chip_temp_reset_history: +			return 0644; +		default: +			break; +		} +		break; +	case hwmon_temp: +		switch (attr) { +		case hwmon_temp_input: +		case hwmon_temp_min_alarm: +		case hwmon_temp_max_alarm: +		case hwmon_temp_crit_alarm: +		case hwmon_temp_fault: +		case hwmon_temp_lowest: +		case hwmon_temp_highest: +			return 0444; +		case hwmon_temp_min: +		case hwmon_temp_max: +		case hwmon_temp_crit: +		case hwmon_temp_crit_hyst: +			return 0644; +		default: +			break; +		} +		break; +	default: +		break; +	} +	return 0; +} -static const struct attribute_group tmp432_group = { -	.attrs = tmp432_attributes, +static const struct hwmon_ops tmp401_ops = { +	.is_visible = tmp401_is_visible, +	.read = tmp401_read, +	.write = tmp401_write,  }; -/* - * Begin non sysfs callback code (aka Real code) - */ +/* chip initialization, detect, probe */ -static int tmp401_init_client(struct tmp401_data *data, -			      struct i2c_client *client) +static int tmp401_init_client(struct tmp401_data *data)  { -	int config, config_orig, status = 0; +	struct regmap *regmap = data->regmap; +	u32 config, config_orig; +	int ret; -	/* Set the conversion rate to 2 Hz */ -	i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5); -	data->update_interval = 500; +	/* Set conversion rate to 2 Hz */ +	ret = regmap_write(regmap, TMP401_CONVERSION_RATE, 5); +	if (ret < 0) +		return ret;  	/* Start conversions (disable shutdown if necessary) */ -	config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); -	if (config < 0) -		return config; +	ret = regmap_read(regmap, TMP401_CONFIG, &config); +	if (ret < 0) +		return ret;  	config_orig = config;  	config &= ~TMP401_CONFIG_SHUTDOWN; +	data->extended_range = !!(config & TMP401_CONFIG_RANGE); +  	if (config != config_orig) -		status = i2c_smbus_write_byte_data(client, -						   TMP401_CONFIG_WRITE, -						   config); +		ret = regmap_write(regmap, TMP401_CONFIG, config); -	return status; +	return ret;  }  static int tmp401_detect(struct i2c_client *client, @@ -651,11 +620,11 @@ static int tmp401_detect(struct i2c_client *client,  		return -ENODEV;  	} -	reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); +	reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG);  	if (reg & 0x1b)  		return -ENODEV; -	reg = i2c_smbus_read_byte_data(client, TMP401_CONVERSION_RATE_READ); +	reg = i2c_smbus_read_byte_data(client, TMP401_CONVERSION_RATE);  	/* Datasheet says: 0x1-0x6 */  	if (reg > 15)  		return -ENODEV; @@ -671,9 +640,10 @@ static int tmp401_probe(struct i2c_client *client)  		"TMP401", "TMP411", "TMP431", "TMP432", "TMP435"  	};  	struct device *dev = &client->dev; +	struct hwmon_channel_info *info;  	struct device *hwmon_dev;  	struct tmp401_data *data; -	int groups = 0, status; +	int status;  	data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);  	if (!data) @@ -683,24 +653,53 @@ static int tmp401_probe(struct i2c_client *client)  	mutex_init(&data->update_lock);  	data->kind = i2c_match_id(tmp401_id, client)->driver_data; -	/* Initialize the TMP401 chip */ -	status = tmp401_init_client(data, client); -	if (status < 0) -		return status; +	data->regmap = devm_regmap_init(dev, NULL, data, &tmp401_regmap_config); +	if (IS_ERR(data->regmap)) +		return PTR_ERR(data->regmap); -	/* Register sysfs hooks */ -	data->groups[groups++] = &tmp401_group; +	/* initialize configuration data */ +	data->chip.ops = &tmp401_ops; +	data->chip.info = data->info; -	/* Register additional tmp411 sysfs hooks */ -	if (data->kind == tmp411) -		data->groups[groups++] = &tmp411_group; +	data->info[0] = &data->chip_info; +	data->info[1] = &data->temp_info; -	/* Register additional tmp432 sysfs hooks */ -	if (data->kind == tmp432) -		data->groups[groups++] = &tmp432_group; +	info = &data->chip_info; +	info->type = hwmon_chip; +	info->config = data->chip_channel_config; + +	data->chip_channel_config[0] = HWMON_C_UPDATE_INTERVAL; + +	info = &data->temp_info; +	info->type = hwmon_temp; +	info->config = data->temp_channel_config; + +	data->temp_channel_config[0] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | +		HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | +		HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM; +	data->temp_channel_config[1] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | +		HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | +		HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT; + +	if (data->kind == tmp411) { +		data->temp_channel_config[0] |= HWMON_T_HIGHEST | HWMON_T_LOWEST; +		data->temp_channel_config[1] |= HWMON_T_HIGHEST | HWMON_T_LOWEST; +		data->chip_channel_config[0] |= HWMON_C_TEMP_RESET_HISTORY; +	} + +	if (data->kind == tmp432) { +		data->temp_channel_config[2] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | +			HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | +			HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT; +	} + +	/* Initialize the TMP401 chip */ +	status = tmp401_init_client(data); +	if (status < 0) +		return status; -	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, -							   data, data->groups); +	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, +							 &data->chip, NULL);  	if (IS_ERR(hwmon_dev))  		return PTR_ERR(hwmon_dev); |