diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/ads1015.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/adt7475.c | 184 | ||||
-rw-r--r-- | drivers/hwmon/aspeed-pwm-tacho.c | 50 | ||||
-rw-r--r-- | drivers/hwmon/ds620.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/ibmpowernv.c | 96 | ||||
-rw-r--r-- | drivers/hwmon/ltc4245.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/max6639.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/nct6775.c | 325 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ir35221.c | 337 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9000.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9200.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/pwm-fan.c | 68 | ||||
-rw-r--r-- | drivers/hwmon/scpi-hwmon.c | 54 | ||||
-rw-r--r-- | drivers/iio/adc/ti-ads1015.c | 2 |
18 files changed, 924 insertions, 219 deletions
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 5140c27d16dd..357b42607164 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -34,7 +34,7 @@ #include <linux/of_device.h> #include <linux/of.h> -#include <linux/i2c/ads1015.h> +#include <linux/platform_data/ads1015.h> /* ADS1015 registers */ enum { diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index c803e3c5fcd4..1baa213a60bd 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -22,6 +22,7 @@ #include <linux/hwmon-vid.h> #include <linux/err.h> #include <linux/jiffies.h> +#include <linux/util_macros.h> /* Indexes for the sysfs hooks */ @@ -78,6 +79,9 @@ #define REG_TEMP_TRANGE_BASE 0x5F +#define REG_ENHANCE_ACOUSTICS1 0x62 +#define REG_ENHANCE_ACOUSTICS2 0x63 + #define REG_PWM_MIN_BASE 0x64 #define REG_TEMP_TMIN_BASE 0x67 @@ -208,6 +212,7 @@ struct adt7475_data { u8 range[3]; u8 pwmctl[3]; u8 pwmchan[3]; + u8 enh_acoustics[2]; u8 vid; u8 vrm; @@ -314,35 +319,6 @@ static void adt7475_write_word(struct i2c_client *client, int reg, u16 val) i2c_smbus_write_byte_data(client, reg, val & 0xFF); } -/* - * Find the nearest value in a table - used for pwm frequency and - * auto temp range - */ -static int find_nearest(long val, const int *array, int size) -{ - int i; - - if (val < array[0]) - return 0; - - if (val > array[size - 1]) - return size - 1; - - for (i = 0; i < size - 1; i++) { - int a, b; - - if (val > array[i + 1]) - continue; - - a = val - array[i]; - b = array[i + 1] - val; - - return (a <= b) ? i : i + 1; - } - - return 0; -} - static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, char *buf) { @@ -550,6 +526,88 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, return count; } +/* Assuming CONFIG6[SLOW] is 0 */ +static const int ad7475_st_map[] = { + 37500, 18800, 12500, 7500, 4700, 3100, 1600, 800, +}; + +static ssize_t show_temp_st(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + long val; + + switch (sattr->index) { + case 0: + val = data->enh_acoustics[0] & 0xf; + break; + case 1: + val = (data->enh_acoustics[1] >> 4) & 0xf; + break; + case 2: + default: + val = data->enh_acoustics[1] & 0xf; + break; + } + + if (val & 0x8) + return sprintf(buf, "%d\n", ad7475_st_map[val & 0x7]); + else + return sprintf(buf, "0\n"); +} + +static ssize_t set_temp_st(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + unsigned char reg; + int shift, idx; + ulong val; + + if (kstrtoul(buf, 10, &val)) + return -EINVAL; + + switch (sattr->index) { + case 0: + reg = REG_ENHANCE_ACOUSTICS1; + shift = 0; + idx = 0; + break; + case 1: + reg = REG_ENHANCE_ACOUSTICS2; + shift = 0; + idx = 1; + break; + case 2: + default: + reg = REG_ENHANCE_ACOUSTICS2; + shift = 4; + idx = 1; + break; + } + + if (val > 0) { + val = find_closest_descending(val, ad7475_st_map, + ARRAY_SIZE(ad7475_st_map)); + val |= 0x8; + } + + mutex_lock(&data->lock); + + data->enh_acoustics[idx] &= ~(0xf << shift); + data->enh_acoustics[idx] |= (val << shift); + + i2c_smbus_write_byte_data(client, reg, data->enh_acoustics[idx]); + + mutex_unlock(&data->lock); + + return count; +} + /* * Table of autorange values - the user will write the value in millidegrees, * and we'll convert it @@ -606,7 +664,7 @@ static ssize_t set_point2(struct device *dev, struct device_attribute *attr, val -= temp; /* Find the nearest table entry to what the user wrote */ - val = find_nearest(val, autorange_table, ARRAY_SIZE(autorange_table)); + val = find_closest(val, autorange_table, ARRAY_SIZE(autorange_table)); data->range[sattr->index] &= ~0xF0; data->range[sattr->index] |= val << 4; @@ -728,6 +786,43 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm[sattr->nr][sattr->index] = clamp_val(val, 0, 0xFF); i2c_smbus_write_byte_data(client, reg, data->pwm[sattr->nr][sattr->index]); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_stall_disable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + u8 mask = BIT(5 + sattr->index); + + return sprintf(buf, "%d\n", !!(data->enh_acoustics[0] & mask)); +} + +static ssize_t set_stall_disable(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + long val; + u8 mask = BIT(5 + sattr->index); + + if (kstrtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + + data->enh_acoustics[0] &= ~mask; + if (val) + data->enh_acoustics[0] |= mask; + + i2c_smbus_write_byte_data(client, REG_ENHANCE_ACOUSTICS1, + data->enh_acoustics[0]); mutex_unlock(&data->lock); @@ -839,7 +934,7 @@ static ssize_t set_pwmctrl(struct device *dev, struct device_attribute *attr, /* List of frequencies for the PWM */ static const int pwmfreq_table[] = { - 11, 14, 22, 29, 35, 44, 58, 88 + 11, 14, 22, 29, 35, 44, 58, 88, 22500 }; static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr, @@ -847,9 +942,10 @@ static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr, { struct adt7475_data *data = adt7475_update_device(dev); struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int i = clamp_val(data->range[sattr->index] & 0xf, 0, + ARRAY_SIZE(pwmfreq_table) - 1); - return sprintf(buf, "%d\n", - pwmfreq_table[data->range[sattr->index] & 7]); + return sprintf(buf, "%d\n", pwmfreq_table[i]); } static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr, @@ -864,13 +960,13 @@ static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr, if (kstrtol(buf, 10, &val)) return -EINVAL; - out = find_nearest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table)); + out = find_closest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table)); mutex_lock(&data->lock); data->range[sattr->index] = adt7475_read(TEMP_TRANGE_REG(sattr->index)); - data->range[sattr->index] &= ~7; + data->range[sattr->index] &= ~0xf; data->range[sattr->index] |= out; i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index), @@ -995,6 +1091,8 @@ static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, THERM, 0); static SENSOR_DEVICE_ATTR_2(temp1_crit_hyst, S_IRUGO | S_IWUSR, show_temp, set_temp, HYSTERSIS, 0); +static SENSOR_DEVICE_ATTR_2(temp1_smoothing, S_IRUGO | S_IWUSR, show_temp_st, + set_temp_st, 0, 0); static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, INPUT, 1); static SENSOR_DEVICE_ATTR_2(temp2_alarm, S_IRUGO, show_temp, NULL, ALARM, 1); static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, @@ -1011,6 +1109,8 @@ static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, THERM, 1); static SENSOR_DEVICE_ATTR_2(temp2_crit_hyst, S_IRUGO | S_IWUSR, show_temp, set_temp, HYSTERSIS, 1); +static SENSOR_DEVICE_ATTR_2(temp2_smoothing, S_IRUGO | S_IWUSR, show_temp_st, + set_temp_st, 0, 1); static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, INPUT, 2); static SENSOR_DEVICE_ATTR_2(temp3_alarm, S_IRUGO, show_temp, NULL, ALARM, 2); static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_temp, NULL, FAULT, 2); @@ -1028,6 +1128,8 @@ static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, THERM, 2); static SENSOR_DEVICE_ATTR_2(temp3_crit_hyst, S_IRUGO | S_IWUSR, show_temp, set_temp, HYSTERSIS, 2); +static SENSOR_DEVICE_ATTR_2(temp3_smoothing, S_IRUGO | S_IWUSR, show_temp_st, + set_temp_st, 0, 2); static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_tach, NULL, INPUT, 0); static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_tach, set_tach, MIN, 0); @@ -1056,6 +1158,8 @@ static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, MIN, 0); static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, MAX, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_stall_disable, S_IRUGO | S_IWUSR, + show_stall_disable, set_stall_disable, 0, 0); static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, 1); static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq, @@ -1068,6 +1172,8 @@ static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, MIN, 1); static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, MAX, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_stall_disable, S_IRUGO | S_IWUSR, + show_stall_disable, set_stall_disable, 0, 1); static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, 2); static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq, @@ -1080,6 +1186,8 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, MIN, 2); static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, MAX, 2); +static SENSOR_DEVICE_ATTR_2(pwm3_stall_disable, S_IRUGO | S_IWUSR, + show_stall_disable, set_stall_disable, 0, 2); /* Non-standard name, might need revisiting */ static DEVICE_ATTR_RW(pwm_use_point2_pwm_at_crit); @@ -1106,6 +1214,7 @@ static struct attribute *adt7475_attrs[] = { &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_smoothing.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, @@ -1115,6 +1224,7 @@ static struct attribute *adt7475_attrs[] = { &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_temp2_crit.dev_attr.attr, &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_smoothing.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_fault.dev_attr.attr, &sensor_dev_attr_temp3_alarm.dev_attr.attr, @@ -1125,6 +1235,7 @@ static struct attribute *adt7475_attrs[] = { &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_temp3_crit.dev_attr.attr, &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_smoothing.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_alarm.dev_attr.attr, @@ -1140,12 +1251,14 @@ static struct attribute *adt7475_attrs[] = { &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_stall_disable.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, &sensor_dev_attr_pwm3_freq.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_stall_disable.dev_attr.attr, &dev_attr_pwm_use_point2_pwm_at_crit.attr, NULL, }; @@ -1164,6 +1277,7 @@ static struct attribute *pwm2_attrs[] = { &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_stall_disable.dev_attr.attr, NULL }; diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index 9de13d626c68..ddfe66bdff86 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -146,14 +146,26 @@ #define PWM_MAX 255 +#define BOTH_EDGES 0x02 /* 10b */ + #define M_PWM_DIV_H 0x00 #define M_PWM_DIV_L 0x05 #define M_PWM_PERIOD 0x5F #define M_TACH_CLK_DIV 0x00 -#define M_TACH_MODE 0x00 -#define M_TACH_UNIT 0x1000 +/* + * 5:4 Type N fan tach mode selection bit: + * 00: falling + * 01: rising + * 10: both + * 11: reserved. + */ +#define M_TACH_MODE 0x02 /* 10b */ +#define M_TACH_UNIT 0x00c0 #define INIT_FAN_CTRL 0xFF +/* How long we sleep in us while waiting for an RPM result. */ +#define ASPEED_RPM_STATUS_SLEEP_USEC 500 + struct aspeed_pwm_tacho_data { struct regmap *regmap; unsigned long clk_freq; @@ -163,6 +175,7 @@ struct aspeed_pwm_tacho_data { u8 type_pwm_clock_division_h[3]; u8 type_pwm_clock_division_l[3]; u8 type_fan_tach_clock_division[3]; + u8 type_fan_tach_mode[3]; u16 type_fan_tach_unit[3]; u8 pwm_port_type[8]; u8 pwm_port_fan_ctrl[8]; @@ -498,8 +511,9 @@ static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, u8 fan_tach_ch) { - u32 raw_data, tach_div, clk_source, sec, val; - u8 fan_tach_ch_source, type; + u32 raw_data, tach_div, clk_source, msec, usec, val; + u8 fan_tach_ch_source, type, mode, both; + int ret; regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); @@ -507,16 +521,31 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch]; type = priv->pwm_port_type[fan_tach_ch_source]; - sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type)); - msleep(sec); + msec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type)); + usec = msec * 1000; + + ret = regmap_read_poll_timeout( + priv->regmap, + ASPEED_PTCR_RESULT, + val, + (val & RESULT_STATUS_MASK), + ASPEED_RPM_STATUS_SLEEP_USEC, + usec); - regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val); - if (!(val & RESULT_STATUS_MASK)) - return -ETIMEDOUT; + /* return -ETIMEDOUT if we didn't get an answer. */ + if (ret) + return ret; raw_data = val & RESULT_VALUE_MASK; tach_div = priv->type_fan_tach_clock_division[type]; - tach_div = 0x4 << (tach_div * 2); + /* + * We need the mode to determine if the raw_data is double (from + * counting both edges). + */ + mode = priv->type_fan_tach_mode[type]; + both = (mode & BOTH_EDGES) ? 1 : 0; + + tach_div = (0x4 << both) << (tach_div * 2); clk_source = priv->clk_freq; if (raw_data == 0) @@ -702,6 +731,7 @@ static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv) aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true); priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV; priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT; + priv->type_fan_tach_mode[TYPEM] = M_TACH_MODE; aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE, M_TACH_UNIT, M_TACH_CLK_DIV); } diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 0043a4c02b85..57d6958c74b8 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -30,7 +30,7 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/sysfs.h> -#include <linux/i2c/ds620.h> +#include <linux/platform_data/ds620.h> /* * Many DS620 constants specified below diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c index 6d2e6605751c..5ccdd0b52650 100644 --- a/drivers/hwmon/ibmpowernv.c +++ b/drivers/hwmon/ibmpowernv.c @@ -50,22 +50,34 @@ enum sensors { TEMP, POWER_SUPPLY, POWER_INPUT, + CURRENT, MAX_SENSOR_TYPE, }; #define INVALID_INDEX (-1U) +/* + * 'compatible' string properties for sensor types as defined in old + * PowerNV firmware (skiboot). These are ordered as 'enum sensors'. + */ +static const char * const legacy_compatibles[] = { + "ibm,opal-sensor-cooling-fan", + "ibm,opal-sensor-amb-temp", + "ibm,opal-sensor-power-supply", + "ibm,opal-sensor-power" +}; + static struct sensor_group { - const char *name; - const char *compatible; + const char *name; /* matches property 'sensor-type' */ struct attribute_group group; u32 attr_count; u32 hwmon_index; } sensor_groups[] = { - {"fan", "ibm,opal-sensor-cooling-fan"}, - {"temp", "ibm,opal-sensor-amb-temp"}, - {"in", "ibm,opal-sensor-power-supply"}, - {"power", "ibm,opal-sensor-power"} + { "fan" }, + { "temp" }, + { "in" }, + { "power" }, + { "curr" }, }; struct sensor_data { @@ -239,8 +251,8 @@ static int get_sensor_type(struct device_node *np) enum sensors type; const char *str; - for (type = 0; type < MAX_SENSOR_TYPE; type++) { - if (of_device_is_compatible(np, sensor_groups[type].compatible)) + for (type = 0; type < ARRAY_SIZE(legacy_compatibles); type++) { + if (of_device_is_compatible(np, legacy_compatibles[type])) return type; } @@ -298,10 +310,14 @@ static int populate_attr_groups(struct platform_device *pdev) sensor_groups[type].attr_count++; /* - * add a new attribute for labels + * add attributes for labels, min and max */ if (!of_property_read_string(np, "label", &label)) sensor_groups[type].attr_count++; + if (of_find_property(np, "sensor-data-min", NULL)) + sensor_groups[type].attr_count++; + if (of_find_property(np, "sensor-data-max", NULL)) + sensor_groups[type].attr_count++; } of_node_put(opal); @@ -337,6 +353,41 @@ static void create_hwmon_attr(struct sensor_data *sdata, const char *attr_name, sdata->dev_attr.show = show; } +static void populate_sensor(struct sensor_data *sdata, int od, int hd, int sid, + const char *attr_name, enum sensors type, + const struct attribute_group *pgroup, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf)) +{ + sdata->id = sid; + sdata->type = type; + sdata->opal_index = od; + sdata->hwmon_index = hd; + create_hwmon_attr(sdata, attr_name, show); + pgroup->attrs[sensor_groups[type].attr_count++] = &sdata->dev_attr.attr; +} + +static char *get_max_attr(enum sensors type) +{ + switch (type) { + case POWER_INPUT: + return "input_highest"; + default: + return "highest"; + } +} + +static char *get_min_attr(enum sensors type) +{ + switch (type) { + case POWER_INPUT: + return "input_lowest"; + default: + return "lowest"; + } +} + /* * Iterate through the device tree for each child of 'sensors' node, create * a sysfs attribute file, the file is named by translating the DT node name @@ -417,16 +468,31 @@ static int create_device_attrs(struct platform_device *pdev) * attribute. They are related to the same * sensor. */ - sdata[count].type = type; - sdata[count].opal_index = sdata[count - 1].opal_index; - sdata[count].hwmon_index = sdata[count - 1].hwmon_index; make_sensor_label(np, &sdata[count], label); + populate_sensor(&sdata[count], opal_index, + sdata[count - 1].hwmon_index, + sensor_id, "label", type, pgroups[type], + show_label); + count++; + } - create_hwmon_attr(&sdata[count], "label", show_label); + if (!of_property_read_u32(np, "sensor-data-max", &sensor_id)) { + attr_name = get_max_attr(type); + populate_sensor(&sdata[count], opal_index, + sdata[count - 1].hwmon_index, + sensor_id, attr_name, type, + pgroups[type], show_sensor); + count++; + } - pgroups[type]->attrs[sensor_groups[type].attr_count++] = - &sdata[count++].dev_attr.attr; + if (!of_property_read_u32(np, "sensor-data-min", &sensor_id)) { + attr_name = get_min_attr(type); + populate_sensor(&sdata[count], opal_index, + sdata[count - 1].hwmon_index, + sensor_id, attr_name, type, + pgroups[type], show_sensor); + count++; } } diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index 4680d89556ce..082f0a0bd8a0 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c @@ -23,7 +23,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/jiffies.h> -#include <linux/i2c/ltc4245.h> +#include <linux/platform_data/ltc4245.h> /* Here are names of the chip's registers (a.k.a. commands) */ enum ltc4245_cmd { diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index dac6d85f2fd9..f98a83c79ff1 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -32,7 +32,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> -#include <linux/i2c/max6639.h> +#include <linux/platform_data/max6639.h> /* Addresses to scan */ static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 2458b406f6aa..c219e43b8f02 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -40,6 +40,8 @@ * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3 * nct6792d 15 6 6 2+6 0xc910 0xc1 0x5ca3 * nct6793d 15 6 6 2+6 0xd120 0xc1 0x5ca3 + * nct6795d 14 6 6 2+6 0xd350 0xc1 0x5ca3 + * * * #temp lists the number of monitored temperature sources (first value) plus * the number of directly connectable temperature sensors (second value). @@ -58,13 +60,15 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/acpi.h> +#include <linux/bitops.h> #include <linux/dmi.h> #include <linux/io.h> #include "lm75.h" #define USE_ALTERNATE -enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793 }; +enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793, + nct6795 }; /* used to set data->name = nct6775_device_names[data->sio_kind] */ static const char * const nct6775_device_names[] = { @@ -75,6 +79,7 @@ static const char * const nct6775_device_names[] = { "nct6791", "nct6792", "nct6793", + "nct6795", }; static const char * const nct6775_sio_names[] __initconst = { @@ -85,6 +90,7 @@ static const char * const nct6775_sio_names[] __initconst = { "NCT6791D", "NCT6792D", "NCT6793D", + "NCT6795D", }; static unsigned short force_id; @@ -104,6 +110,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define NCT6775_LD_ACPI 0x0a #define NCT6775_LD_HWM 0x0b #define NCT6775_LD_VID 0x0d +#define NCT6775_LD_12 0x12 #define SIO_REG_LDSEL 0x07 /* Logical device select */ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ @@ -117,6 +124,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define SIO_NCT6791_ID 0xc800 #define SIO_NCT6792_ID 0xc910 #define SIO_NCT6793_ID 0xd120 +#define SIO_NCT6795_ID 0xd350 #define SIO_ID_MASK 0xFFF0 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; @@ -360,12 +368,24 @@ static const char *const nct6775_temp_label[] = { "PCH_DIM3_TEMP" }; -static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 }; +#define NCT6775_TEMP_MASK 0x001ffffe + +static const u16 NCT6775_REG_TEMP_ALTERNATE[32] = { + [13] = 0x661, + [14] = 0x662, + [15] = 0x664, +}; -static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1] - = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06, - 0xa07 }; +static const u16 NCT6775_REG_TEMP_CRIT[32] = { + [4] = 0xa00, + [5] = 0xa01, + [6] = 0xa02, + [7] = 0xa03, + [8] = 0xa04, + [9] = 0xa05, + [10] = 0xa06, + [11] = 0xa07 +}; /* NCT6776 specific data */ @@ -434,11 +454,18 @@ static const char *const nct6776_temp_label[] = { "BYTE_TEMP" }; -static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 }; +#define NCT6776_TEMP_MASK 0x007ffffe -static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; +static const u16 NCT6776_REG_TEMP_ALTERNATE[32] = { + [14] = 0x401, + [15] = 0x402, + [16] = 0x404, +}; + +static const u16 NCT6776_REG_TEMP_CRIT[32] = { + [11] = 0x709, + [12] = 0x70a, +}; /* NCT6779 specific data */ @@ -525,17 +552,19 @@ static const char *const nct6779_temp_label[] = { "Virtual_TEMP" }; -#define NCT6779_NUM_LABELS (ARRAY_SIZE(nct6779_temp_label) - 5) -#define NCT6791_NUM_LABELS ARRAY_SIZE(nct6779_temp_label) +#define NCT6779_TEMP_MASK 0x07ffff7e +#define NCT6791_TEMP_MASK 0x87ffff7e -static const u16 NCT6779_REG_TEMP_ALTERNATE[NCT6791_NUM_LABELS - 1] +static const u16 NCT6779_REG_TEMP_ALTERNATE[32] = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407, 0x408, 0 }; -static const u16 NCT6779_REG_TEMP_CRIT[NCT6791_NUM_LABELS - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; +static const u16 NCT6779_REG_TEMP_CRIT[32] = { + [15] = 0x709, + [16] = 0x70a, +}; /* NCT6791 specific data */ @@ -602,6 +631,8 @@ static const char *const nct6792_temp_label[] = { "Virtual_TEMP" }; +#define NCT6792_TEMP_MASK 0x9fffff7e + static const char *const nct6793_temp_label[] = { "", "SYSTIN", @@ -637,6 +668,45 @@ static const char *const nct6793_temp_label[] = { "Virtual_TEMP" }; +#define NCT6793_TEMP_MASK 0xbfff037e + +static const char *const nct6795_temp_label[] = { + "", + "SYSTIN", + "CPUTIN", + "AUXTIN0", + "AUXTIN1", + "AUXTIN2", + "AUXTIN3", + "", + "SMBUSMASTER 0", + "SMBUSMASTER 1", + "SMBUSMASTER 2", + "SMBUSMASTER 3", + "SMBUSMASTER 4", + "SMBUSMASTER 5", + "SMBUSMASTER 6", + "SMBUSMASTER 7", + "PECI Agent 0", + "PECI Agent 1", + "PCH_CHIP_CPU_MAX_TEMP", + "PCH_CHIP_TEMP", + "PCH_CPU_TEMP", + "PCH_MCH_TEMP", + "PCH_DIM0_TEMP", + "PCH_DIM1_TEMP", + "PCH_DIM2_TEMP", + "PCH_DIM3_TEMP", + "BYTE_TEMP0", + "BYTE_TEMP1", + "PECI Agent 0 Calibration", + "PECI Agent 1 Calibration", + "", + "Virtual_TEMP" +}; + +#define NCT6795_TEMP_MASK 0xbfffff7e + /* NCT6102D/NCT6106D specific data */ #define NCT6106_REG_VBAT 0x318 @@ -731,11 +801,16 @@ static const s8 NCT6106_BEEP_BITS[] = { 34, -1 /* intrusion0, intrusion1 */ }; -static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 }; +static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = { + [14] = 0x51, + [15] = 0x52, + [16] = 0x54, +}; -static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 }; +static const u16 NCT6106_REG_TEMP_CRIT[32] = { + [11] = 0x204, + [12] = 0x205, +}; static enum pwm_enable reg_to_pwm_enable(int pwm, int mode) { @@ -810,7 +885,7 @@ static u16 fan_to_reg(u32 fan, unsigned int divreg) static inline unsigned int div_from_reg(u8 reg) { - return 1 << reg; + return BIT(reg); } /* @@ -850,7 +925,7 @@ struct nct6775_data { u8 temp_src[NUM_TEMP]; u16 reg_temp_config[NUM_TEMP]; const char * const *temp_label; - int temp_label_num; + u32 temp_mask; u16 REG_CONFIG; u16 REG_VBAT; @@ -1155,6 +1230,7 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg) case nct6791: case nct6792: case nct6793: + case nct6795: return reg == 0x150 || reg == 0x153 || reg == 0x155 || ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) || reg == 0x402 || @@ -1276,7 +1352,7 @@ static void nct6775_update_fan_div(struct nct6775_data *data) data->fan_div[1] = (i & 0x70) >> 4; i = nct6775_read_value(data, NCT6775_REG_FANDIV2); data->fan_div[2] = i & 0x7; - if (data->has_fan & (1 << 3)) + if (data->has_fan & BIT(3)) data->fan_div[3] = (i & 0x70) >> 4; } @@ -1298,7 +1374,7 @@ static void nct6775_init_fan_div(struct nct6775_data *data) * We'll compute a better divider later on. */ for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) { - if (!(data->has_fan & (1 << i))) + if (!(data->has_fan & BIT(i))) continue; if (data->fan_div[i] == 0) { data->fan_div[i] = 7; @@ -1321,7 +1397,7 @@ static void nct6775_init_fan_common(struct device *dev, * prevents the unnecessary warning when fanX_min is reported as 0. */ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { - if (data->has_fan_min & (1 << i)) { + if (data->has_fan_min & BIT(i)) { reg = nct6775_read_value(data, data->REG_FAN_MIN[i]); if (!reg) nct6775_write_value(data, data->REG_FAN_MIN[i], @@ -1356,7 +1432,7 @@ static void nct6775_select_fan_div(struct device *dev, div_from_reg(fan_div)); /* Preserve min limit if possible */ - if (data->has_fan_min & (1 << nr)) { + if (data->has_fan_min & BIT(nr)) { fan_min = data->fan_min[nr]; if (fan_div > data->fan_div[nr]) { if (fan_min != 255 && fan_min > 1) @@ -1387,7 +1463,7 @@ static void nct6775_update_pwm(struct device *dev) bool duty_is_dc; for (i = 0; i < data->pwm_num; i++) { - if (!(data->has_pwm & (1 << i))) + if (!(data->has_pwm & BIT(i))) continue; duty_is_dc = data->REG_PWM_MODE[i] && |