diff options
Diffstat (limited to 'drivers/hwmon/max6697.c')
-rw-r--r-- | drivers/hwmon/max6697.c | 114 |
1 files changed, 104 insertions, 10 deletions
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c index 743752a2467a..2895cea54193 100644 --- a/drivers/hwmon/max6697.c +++ b/drivers/hwmon/max6697.c @@ -38,8 +38,9 @@ static const u8 MAX6697_REG_CRIT[] = { * Map device tree / platform data register bit map to chip bit map. * Applies to alert register and over-temperature register. */ -#define MAX6697_MAP_BITS(reg) ((((reg) & 0x7e) >> 1) | \ +#define MAX6697_ALERT_MAP_BITS(reg) ((((reg) & 0x7e) >> 1) | \ (((reg) & 0x01) << 6) | ((reg) & 0x80)) +#define MAX6697_OVERT_MAP_BITS(reg) (((reg) >> 1) | (((reg) & 0x01) << 7)) #define MAX6697_REG_STAT(n) (0x44 + (n)) @@ -56,6 +57,8 @@ static const u8 MAX6697_REG_CRIT[] = { #define MAX6581_REG_IDEALITY_SELECT 0x4c #define MAX6581_REG_OFFSET 0x4d #define MAX6581_REG_OFFSET_SELECT 0x4e +#define MAX6581_OFFSET_MIN -31750 +#define MAX6581_OFFSET_MAX 31750 #define MAX6697_CONV_TIME 156 /* ms per channel, worst case */ @@ -171,6 +174,11 @@ static const struct max6697_chip_data max6697_chip_data[] = { }, }; +static inline int max6581_offset_to_millic(int val) +{ + return sign_extend32(val, 7) * 250; +} + static struct max6697_data *max6697_update_device(struct device *dev) { struct max6697_data *data = dev_get_drvdata(dev); @@ -316,6 +324,70 @@ static ssize_t temp_store(struct device *dev, return ret < 0 ? ret : count; } +static ssize_t offset_store(struct device *dev, struct device_attribute *devattr, const char *buf, + size_t count) +{ + int val, ret, index, select; + struct max6697_data *data; + bool channel_enabled; + long temp; + + index = to_sensor_dev_attr(devattr)->index; + data = dev_get_drvdata(dev); + ret = kstrtol(buf, 10, &temp); + if (ret < 0) + return ret; + + mutex_lock(&data->update_lock); + select = i2c_smbus_read_byte_data(data->client, MAX6581_REG_OFFSET_SELECT); + if (select < 0) { + ret = select; + goto abort; + } + channel_enabled = (select & (1 << (index - 1))); + temp = clamp_val(temp, MAX6581_OFFSET_MIN, MAX6581_OFFSET_MAX); + val = DIV_ROUND_CLOSEST(temp, 250); + /* disable the offset for channel if the new offset is 0 */ + if (val == 0) { + if (channel_enabled) + ret = i2c_smbus_write_byte_data(data->client, MAX6581_REG_OFFSET_SELECT, + select & ~(1 << (index - 1))); + ret = ret < 0 ? ret : count; + goto abort; + } + if (!channel_enabled) { + ret = i2c_smbus_write_byte_data(data->client, MAX6581_REG_OFFSET_SELECT, + select | (1 << (index - 1))); + if (ret < 0) + goto abort; + } + ret = i2c_smbus_write_byte_data(data->client, MAX6581_REG_OFFSET, val); + ret = ret < 0 ? ret : count; + +abort: + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t offset_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct max6697_data *data; + int select, ret, index; + + index = to_sensor_dev_attr(devattr)->index; + data = dev_get_drvdata(dev); + mutex_lock(&data->update_lock); + select = i2c_smbus_read_byte_data(data->client, MAX6581_REG_OFFSET_SELECT); + if (select < 0) + ret = select; + else if (select & (1 << (index - 1))) + ret = i2c_smbus_read_byte_data(data->client, MAX6581_REG_OFFSET); + else + ret = 0; + mutex_unlock(&data->update_lock); + return ret < 0 ? ret : sprintf(buf, "%d\n", max6581_offset_to_millic(ret)); +} + static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, 0, MAX6697_TEMP_MAX); static SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, 0, MAX6697_TEMP_CRIT); @@ -374,16 +446,25 @@ static SENSOR_DEVICE_ATTR_RO(temp6_fault, alarm, 5); static SENSOR_DEVICE_ATTR_RO(temp7_fault, alarm, 6); static SENSOR_DEVICE_ATTR_RO(temp8_fault, alarm, 7); +/* There is no offset for local temperature so starting from temp2 */ +static SENSOR_DEVICE_ATTR_RW(temp2_offset, offset, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_offset, offset, 2); +static SENSOR_DEVICE_ATTR_RW(temp4_offset, offset, 3); +static SENSOR_DEVICE_ATTR_RW(temp5_offset, offset, 4); +static SENSOR_DEVICE_ATTR_RW(temp6_offset, offset, 5); +static SENSOR_DEVICE_ATTR_RW(temp7_offset, offset, 6); +static SENSOR_DEVICE_ATTR_RW(temp8_offset, offset, 7); + static DEVICE_ATTR(dummy, 0, NULL, NULL); static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr, int index) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct max6697_data *data = dev_get_drvdata(dev); const struct max6697_chip_data *chip = data->chip; - int channel = index / 6; /* channel number */ - int nr = index % 6; /* attribute index within channel */ + int channel = index / 7; /* channel number */ + int nr = index % 7; /* attribute index within channel */ if (channel >= chip->channels) return 0; @@ -392,6 +473,10 @@ static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr, return 0; if (nr == 5 && !(chip->have_fault & (1 << channel))) return 0; + /* offset reg is only supported on max6581 remote channels */ + if (nr == 6) + if (data->type != max6581 || channel == 0) + return 0; return attr->mode; } @@ -408,6 +493,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, &dev_attr_dummy.attr, + &dev_attr_dummy.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, @@ -415,6 +501,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp2_crit.dev_attr.attr, &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp2_fault.dev_attr.attr, + &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, @@ -422,6 +509,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp3_crit.dev_attr.attr, &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp3_fault.dev_attr.attr, + &sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp4_input.dev_attr.attr, &sensor_dev_attr_temp4_max.dev_attr.attr, @@ -429,6 +517,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp4_crit.dev_attr.attr, &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp4_fault.dev_attr.attr, + &sensor_dev_attr_temp4_offset.dev_attr.attr, &sensor_dev_attr_temp5_input.dev_attr.attr, &sensor_dev_attr_temp5_max.dev_attr.attr, @@ -436,6 +525,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp5_crit.dev_attr.attr, &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp5_fault.dev_attr.attr, + &sensor_dev_attr_temp5_offset.dev_attr.attr, &sensor_dev_attr_temp6_input.dev_attr.attr, &sensor_dev_attr_temp6_max.dev_attr.attr, @@ -443,6 +533,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp6_crit.dev_attr.attr, &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp6_fault.dev_attr.attr, + &sensor_dev_attr_temp6_offset.dev_attr.attr, &sensor_dev_attr_temp7_input.dev_attr.attr, &sensor_dev_attr_temp7_max.dev_attr.attr, @@ -450,6 +541,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp7_crit.dev_attr.attr, &sensor_dev_attr_temp7_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp7_fault.dev_attr.attr, + &sensor_dev_attr_temp7_offset.dev_attr.attr, &sensor_dev_attr_temp8_input.dev_attr.attr, &sensor_dev_attr_temp8_max.dev_attr.attr, @@ -457,6 +549,7 @@ static struct attribute *max6697_attributes[] = { &sensor_dev_attr_temp8_crit.dev_attr.attr, &sensor_dev_attr_temp8_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp8_fault.dev_attr.attr, + &sensor_dev_attr_temp8_offset.dev_attr.attr, NULL }; @@ -562,12 +655,12 @@ static int max6697_init_chip(struct max6697_data *data, return ret; ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK, - MAX6697_MAP_BITS(pdata->alert_mask)); + MAX6697_ALERT_MAP_BITS(pdata->alert_mask)); if (ret < 0) return ret; ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK, - MAX6697_MAP_BITS(pdata->over_temperature_mask)); + MAX6697_OVERT_MAP_BITS(pdata->over_temperature_mask)); if (ret < 0) return ret; @@ -592,8 +685,9 @@ done: return 0; } -static int max6697_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct i2c_device_id max6697_id[]; + +static int max6697_probe(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; struct device *dev = &client->dev; @@ -611,7 +705,7 @@ static int max6697_probe(struct i2c_client *client, if (client->dev.of_node) data->type = (enum chips)of_device_get_match_data(&client->dev); else - data->type = id->driver_data; + data->type = i2c_match_id(max6697_id, client)->driver_data; data->chip = &max6697_chip_data[data->type]; data->client = client; mutex_init(&data->update_lock); @@ -692,7 +786,7 @@ static struct i2c_driver max6697_driver = { .name = "max6697", .of_match_table = of_match_ptr(max6697_of_match), }, - .probe = max6697_probe, + .probe_new = max6697_probe, .id_table = max6697_id, }; |