diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-03 18:43:20 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-03 18:43:20 -0700 |
commit | fe91f28138e730790db014812623cfaadd318fa6 (patch) | |
tree | ce8fb5cb94539235db9b7c4be564c2b7b7659317 /drivers | |
parent | aa9d4648c2fbb455df7750ade1b73dd9ad9b3690 (diff) | |
parent | 7074d0a92758603369655ef5d4f49e6caaae0b4e (diff) |
Merge tag 'hwmon-for-linus-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
- new drivers:
- Lantiq CPU temperature sensor
- IBM CFF power supply
- TPS53679 PMBus driver
- new support:
- LM5066I (lm25066 PMBus driver)
- Intel VID protocol VR13 (PMBus drivers)
- CAT34TS02C, GT30TS00, GT34TS02, and CAT34TS04 (jc42 driver)
- cleanup and minor improvements in several drivers
* tag 'hwmon-for-linus-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (36 commits)
hwmon: (ltq-cputemp) add cpu temp sensor driver
hwmon: (ltq-cputemp) add devicetree bindings documentation
hwmon: (pmbus) Add support for Texas Instruments tps53679 device
hwmon: (asc7621) make several arrays static const
hwmon: (pmbus/lm25066) Add support for TI LM5066I
hwmon: (pmbus/lm25066) Offset coefficient depends on CL
hwmon: (pmbus) Add support for Intel VID protocol VR13
Documentation: hwmon: Document the IBM CFF power supply
hwmon: (pmbus) Add IBM Common Form Factor (CFF) power supply driver
dt-bindings: hwmon: Document the IBM CCF power supply version 1
hwmon: (ftsteutates) constify i2c_device_id
hwmon: da9052: Add support for TSI channel
mfd: da9052: Make touchscreen registration optional
hwmon: da9052: Replace S_IRUGO with 0444
mfd: da9052: Add register details for TSI
hwmon: (aspeed-pwm) add THERMAL dependency
hwmon: (pmbus) Add debugfs for status registers
hwmon: (aspeed-pwm-tacho) cooling device support.
Documentation: dt-bindings: aspeed-pwm-tacho cooling device.
hwmon: (pmbus): Add generic alarm bit for iin and pin
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/Kconfig | 8 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/adc128d818.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/ads1015.c | 14 | ||||
-rw-r--r-- | drivers/hwmon/adt7475.c | 16 | ||||
-rw-r--r-- | drivers/hwmon/asc7621.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/aspeed-pwm-tacho.c | 116 | ||||
-rw-r--r-- | drivers/hwmon/da9052-hwmon.c | 285 | ||||
-rw-r--r-- | drivers/hwmon/ftsteutates.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/hwmon.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/i5k_amb.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 214 | ||||
-rw-r--r-- | drivers/hwmon/jc42.c | 19 | ||||
-rw-r--r-- | drivers/hwmon/ltq-cputemp.c | 163 | ||||
-rw-r--r-- | drivers/hwmon/nct7802.c | 10 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 18 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Makefile | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ibm-cffps.c | 151 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/lm25066.c | 47 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.h | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 292 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/tps53679.c | 113 | ||||
-rw-r--r-- | drivers/hwmon/scpi-hwmon.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/stts751.c | 4 | ||||
-rw-r--r-- | drivers/mfd/da9052-core.c | 26 |
25 files changed, 1384 insertions, 135 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5ef2814345ef..d65431417b17 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -343,6 +343,7 @@ config SENSORS_ASB100 config SENSORS_ASPEED tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver" + depends on THERMAL || THERMAL=n select REGMAP help This driver provides support for ASPEED AST2400/AST2500 PWM @@ -790,6 +791,13 @@ config SENSORS_LTC4261 This driver can also be built as a module. If so, the module will be called ltc4261. +config SENSORS_LTQ_CPUTEMP + bool "Lantiq cpu temperature sensor driver" + depends on LANTIQ + help + If you say yes here you get support for the temperature + sensor inside your CPU. + config SENSORS_MAX1111 tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles" depends on SPI_MASTER diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d4641a9f16c1..c84d9784be98 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o obj-$(CONFIG_SENSORS_LTC4260) += ltc4260.o obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o +obj-$(CONFIG_SENSORS_LTQ_CPUTEMP) += ltq-cputemp.o obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX16065) += max16065.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index a557b46dbe8e..bd2ca315c9d8 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -384,7 +384,7 @@ static struct attribute *adc128_attrs[] = { NULL }; -static struct attribute_group adc128_group = { +static const struct attribute_group adc128_group = { .attrs = adc128_attrs, .is_visible = adc128_is_visible, }; diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 357b42607164..98c704d3366a 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -191,24 +191,23 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; if (of_property_read_u32(node, "reg", &pval)) { - dev_err(&client->dev, "invalid reg on %s\n", - node->full_name); + dev_err(&client->dev, "invalid reg on %pOF\n", node); continue; } channel = pval; if (channel >= ADS1015_CHANNELS) { dev_err(&client->dev, - "invalid channel index %d on %s\n", - channel, node->full_name); + "invalid channel index %d on %pOF\n", + channel, node); continue; } if (!of_property_read_u32(node, "ti,gain", &pval)) { pga = pval; if (pga > 6) { - dev_err(&client->dev, "invalid gain on %s\n", - node->full_name); + dev_err(&client->dev, "invalid gain on %pOF\n", + node); return -EINVAL; } } @@ -217,8 +216,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) data_rate = pval; if (data_rate > 7) { dev_err(&client->dev, - "invalid data_rate on %s\n", - node->full_name); + "invalid data_rate on %pOF\n", node); return -EINVAL; } } diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 1baa213a60bd..9ef84998c7f3 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -1319,14 +1319,14 @@ static struct attribute *vid_attrs[] = { NULL }; -static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; -static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; -static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; -static struct attribute_group in0_attr_group = { .attrs = in0_attrs }; -static struct attribute_group in3_attr_group = { .attrs = in3_attrs }; -static struct attribute_group in4_attr_group = { .attrs = in4_attrs }; -static struct attribute_group in5_attr_group = { .attrs = in5_attrs }; -static struct attribute_group vid_attr_group = { .attrs = vid_attrs }; +static const struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; +static const struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; +static const struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; +static const struct attribute_group in0_attr_group = { .attrs = in0_attrs }; +static const struct attribute_group in3_attr_group = { .attrs = in3_attrs }; +static const struct attribute_group in4_attr_group = { .attrs = in4_attrs }; +static const struct attribute_group in5_attr_group = { .attrs = in5_attrs }; +static const struct attribute_group vid_attr_group = { .attrs = vid_attrs }; static int adt7475_detect(struct i2c_client *client, struct i2c_board_info *info) diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index c77644d45a02..4875e99b59c9 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -512,7 +512,7 @@ static ssize_t show_pwm_ac(struct device *dev, { SETUP_SHOW_DATA_PARAM(dev, attr); u8 config, altbit, regval; - const u8 map[] = { + static const u8 map[] = { 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10, 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; @@ -533,7 +533,7 @@ static ssize_t store_pwm_ac(struct device *dev, SETUP_STORE_DATA_PARAM(dev, attr); unsigned long reqval; u8 currval, config, altbit, newval; - const u16 map[] = { + static const u16 map[] = { 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index ddfe66bdff86..69b97d45e3cb 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -20,6 +20,7 @@ #include <linux/platform_device.h> #include <linux/sysfs.h> #include <linux/regmap.h> +#include <linux/thermal.h> /* ASPEED PWM & FAN Tach Register Definition */ #define ASPEED_PTCR_CTRL 0x00 @@ -166,6 +167,18 @@ /* How long we sleep in us while waiting for an RPM result. */ #define ASPEED_RPM_STATUS_SLEEP_USEC 500 +#define MAX_CDEV_NAME_LEN 16 + +struct aspeed_cooling_device { + char name[16]; + struct aspeed_pwm_tacho_data *priv; + struct thermal_cooling_device *tcdev; + int pwm_port; + u8 *cooling_levels; + u8 max_state; + u8 cur_state; +}; + struct aspeed_pwm_tacho_data { struct regmap *regmap; unsigned long clk_freq; @@ -180,6 +193,7 @@ struct aspeed_pwm_tacho_data { u8 pwm_port_type[8]; u8 pwm_port_fan_ctrl[8]; u8 fan_tach_ch_source[16]; + struct aspeed_cooling_device *cdev[8]; const struct attribute_group *groups[3]; }; @@ -765,6 +779,94 @@ static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv, } } +static int +aspeed_pwm_cz_get_max_state(struct thermal_cooling_device *tcdev, + unsigned long *state) +{ + struct aspeed_cooling_device *cdev = tcdev->devdata; + + *state = cdev->max_state; + + return 0; +} + +static int +aspeed_pwm_cz_get_cur_state(struct thermal_cooling_device *tcdev, + unsigned long *state) +{ + struct aspeed_cooling_device *cdev = tcdev->devdata; + + *state = cdev->cur_state; + + return 0; +} + +static int +aspeed_pwm_cz_set_cur_state(struct thermal_cooling_device *tcdev, + unsigned long state) +{ + struct aspeed_cooling_device *cdev = tcdev->devdata; + + if (state > cdev->max_state) + return -EINVAL; + + cdev->cur_state = state; + cdev->priv->pwm_port_fan_ctrl[cdev->pwm_port] = + cdev->cooling_levels[cdev->cur_state]; + aspeed_set_pwm_port_fan_ctrl(cdev->priv, cdev->pwm_port, + cdev->cooling_levels[cdev->cur_state]); + + return 0; +} + +static const struct thermal_cooling_device_ops aspeed_pwm_cool_ops = { + .get_max_state = aspeed_pwm_cz_get_max_state, + .get_cur_state = aspeed_pwm_cz_get_cur_state, + .set_cur_state = aspeed_pwm_cz_set_cur_state, +}; + +static int aspeed_create_pwm_cooling(struct device *dev, + struct device_node *child, + struct aspeed_pwm_tacho_data *priv, + u32 pwm_port, u8 num_levels) +{ + int ret; + struct aspeed_cooling_device *cdev; + + cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); + + if (!cdev) + return -ENOMEM; + + cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL); + if (!cdev->cooling_levels) + return -ENOMEM; + + cdev->max_state = num_levels - 1; + ret = of_property_read_u8_array(child, "cooling-levels", + cdev->cooling_levels, + num_levels); + if (ret) { + dev_err(dev, "Property 'cooling-levels' cannot be read.\n"); + return ret; + } + snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%s%d", child->name, pwm_port); + + cdev->tcdev = thermal_of_cooling_device_register(child, + cdev->name, + cdev, + &aspeed_pwm_cool_ops); + if (IS_ERR(cdev->tcdev)) + return PTR_ERR(cdev->tcdev); + + cdev->priv = priv; + cdev->pwm_port = pwm_port; + + priv->cdev[pwm_port] = cdev; + + return 0; +} + static int aspeed_create_fan(struct device *dev, struct device_node *child, struct aspeed_pwm_tacho_data *priv) @@ -778,6 +880,15 @@ static int aspeed_create_fan(struct device *dev, return ret; aspeed_create_pwm_port(priv, (u8)pwm_port); + ret = of_property_count_u8_elems(child, "cooling-levels"); + + if (ret > 0) { + ret = aspeed_create_pwm_cooling(dev, child, priv, pwm_port, + ret); + if (ret) + return ret; + } + count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); if (count < 1) return -EINVAL; @@ -834,9 +945,10 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev) for_each_child_of_node(np, child) { ret = aspeed_create_fan(dev, child, priv); - of_node_put(child); - if (ret) + if (ret) { + of_node_put(child); return ret; + } } priv->groups[0] = &pwm_dev_group; diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c index c9832bfacfe5..97a62f5b9ea4 100644 --- a/drivers/hwmon/da9052-hwmon.c +++ b/drivers/hwmon/da9052-hwmon.c @@ -20,13 +20,19 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/mfd/da9052/da9052.h> #include <linux/mfd/da9052/reg.h> +#include <linux/regulator/consumer.h> struct da9052_hwmon { - struct da9052 *da9052; - struct mutex hwmon_lock; + struct da9052 *da9052; + struct mutex hwmon_lock; + bool tsi_as_adc; + int tsiref_mv; + struct regulator *tsiref; + struct completion tsidone; }; static const char * const input_names[] = { @@ -37,6 +43,10 @@ static const char * const input_names[] = { [DA9052_ADC_IN4] = "ADC IN4", [DA9052_ADC_IN5] = "ADC IN5", [DA9052_ADC_IN6] = "ADC IN6", + [DA9052_ADC_TSI_XP] = "ADC TS X+", + [DA9052_ADC_TSI_YP] = "ADC TS Y+", + [DA9052_ADC_TSI_XN] = "ADC TS X-", + [DA9052_ADC_TSI_YN] = "ADC TS Y-", [DA9052_ADC_TJUNC] = "BATTERY JUNCTION TEMP", [DA9052_ADC_VBBAT] = "BACK-UP BATTERY VOLTAGE", }; @@ -59,6 +69,11 @@ static inline int vbbat_reg_to_mv(int value) return DIV_ROUND_CLOSEST(value * 5000, 1023); } +static inline int input_tsireg_to_mv(struct da9052_hwmon *hwmon, int value) +{ + return DIV_ROUND_CLOSEST(value * hwmon->tsiref_mv, 1023); +} + static inline int da9052_enable_vddout_channel(struct da9052 *da9052) { return da9052_reg_update(da9052, DA9052_ADC_CONT_REG, @@ -154,6 +169,97 @@ static ssize_t da9052_read_misc_channel(struct device *dev, return sprintf(buf, "%d\n", input_reg_to_mv(ret)); } +static int da9052_request_tsi_read(struct da9052_hwmon *hwmon, int channel) +{ + u8 val = DA9052_TSICONTB_TSIMAN; + + switch (channel) { + case DA9052_ADC_TSI_XP: + val |= DA9052_TSICONTB_TSIMUX_XP; + break; + case DA9052_ADC_TSI_YP: + val |= DA9052_TSICONTB_TSIMUX_YP; + break; + case DA9052_ADC_TSI_XN: + val |= DA9052_TSICONTB_TSIMUX_XN; + break; + case DA9052_ADC_TSI_YN: + val |= DA9052_TSICONTB_TSIMUX_YN; + break; + } + + return da9052_reg_write(hwmon->da9052, DA9052_TSI_CONT_B_REG, val); +} + +static int da9052_get_tsi_result(struct da9052_hwmon *hwmon, int channel) +{ + u8 regs[3]; + int msb, lsb, err; + + /* block read to avoid separation of MSB and LSB */ + err = da9052_group_read(hwmon->da9052, DA9052_TSI_X_MSB_REG, + ARRAY_SIZE(regs), regs); + if (err) + return err; + + switch (channel) { + case DA9052_ADC_TSI_XP: + case DA9052_ADC_TSI_XN: + msb = regs[0] << DA9052_TSILSB_TSIXL_BITS; + lsb = regs[2] & DA9052_TSILSB_TSIXL; + lsb >>= DA9052_TSILSB_TSIXL_SHIFT; + break; + case DA9052_ADC_TSI_YP: + case DA9052_ADC_TSI_YN: + msb = regs[1] << DA9052_TSILSB_TSIYL_BITS; + lsb = regs[2] & DA9052_TSILSB_TSIYL; + lsb >>= DA9052_TSILSB_TSIYL_SHIFT; + break; + default: + return -EINVAL; + } + + return msb | lsb; +} + + +static ssize_t __da9052_read_tsi(struct device *dev, int channel) +{ + struct da9052_hwmon *hwmon = dev_get_drvdata(dev); + int ret; + + reinit_completion(&hwmon->tsidone); + + ret = da9052_request_tsi_read(hwmon, channel); + if (ret < 0) + return ret; + + /* Wait for an conversion done interrupt */ + if (!wait_for_completion_timeout(&hwmon->tsidone, + msecs_to_jiffies(500))) + return -ETIMEDOUT; + + return da9052_get_tsi_result(hwmon, channel); +} + +static ssize_t da9052_read_tsi(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct da9052_hwmon *hwmon = dev_get_drvdata(dev); + int channel = to_sensor_dev_attr(devattr)->index; + int ret; + + mutex_lock(&hwmon->hwmon_lock); + ret = __da9052_read_tsi(dev, channel); + mutex_unlock(&hwmon->hwmon_lock); + + if (ret < 0) + return ret; + else + return sprintf(buf, "%d\n", input_tsireg_to_mv(hwmon, ret)); +} + static ssize_t da9052_read_tjunc(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -196,43 +302,82 @@ static ssize_t show_label(struct device *dev, input_names[to_sensor_dev_attr(devattr)->index]); } -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, da9052_read_vddout, NULL, +static umode_t da9052_channel_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct da9052_hwmon *hwmon = dev_get_drvdata(dev); + struct device_attribute *dattr = container_of(attr, + struct device_attribute, attr); + struct sensor_device_attribute *sattr = to_sensor_dev_attr(dattr); + + if (!hwmon->tsi_as_adc) { + switch (sattr->index) { + case DA9052_ADC_TSI_XP: + case DA9052_ADC_TSI_YP: + case DA9052_ADC_TSI_XN: + case DA9052_ADC_TSI_YN: + return 0; + } + } + + return attr->mode; +} + +static SENSOR_DEVICE_ATTR(in0_input, 0444, da9052_read_vddout, NULL, DA9052_ADC_VDDOUT); -static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(in0_label, 0444, show_label, NULL, DA9052_ADC_VDDOUT); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, da9052_read_vbat, NULL, +static SENSOR_DEVICE_ATTR(in3_input, 0444, da9052_read_vbat, NULL, DA9052_ADC_VBAT); -static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(in3_label, 0444, show_label, NULL, DA9052_ADC_VBAT); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, da9052_read_misc_channel, NULL, +static SENSOR_DEVICE_ATTR(in4_input, 0444, da9052_read_misc_channel, NULL, DA9052_ADC_IN4); -static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(in4_label, 0444, show_label, NULL, DA9052_ADC_IN4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, da9052_read_misc_channel, NULL, +static SENSOR_DEVICE_ATTR(in5_input, 0444, da9052_read_misc_channel, NULL, DA9052_ADC_IN5); -static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(in5_label, 0444, show_label, NULL, DA9052_ADC_IN5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, da9052_read_misc_channel, NULL, +static SENSOR_DEVICE_ATTR(in6_input, 0444, da9052_read_misc_channel, NULL, DA9052_ADC_IN6); -static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(in6_label, 0444, show_label, NULL, DA9052_ADC_IN6); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, da9052_read_vbbat, NULL, +static SENSOR_DEVICE_ATTR(in9_input, 0444, da9052_read_vbbat, NULL, DA9052_ADC_VBBAT); -static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(in9_label, 0444, show_label, NULL, DA9052_ADC_VBBAT); -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, da9052_read_ich, NULL, +static SENSOR_DEVICE_ATTR(in70_input, 0444, da9052_read_tsi, NULL, + DA9052_ADC_TSI_XP); +static SENSOR_DEVICE_ATTR(in70_label, 0444, show_label, NULL, + DA9052_ADC_TSI_XP); +static SENSOR_DEVICE_ATTR(in71_input, 0444, da9052_read_tsi, NULL, + DA9052_ADC_TSI_XN); +static SENSOR_DEVICE_ATTR(in71_label, 0444, show_label, NULL, + DA9052_ADC_TSI_XN); +static SENSOR_DEVICE_ATTR(in72_input, 0444, da9052_read_tsi, NULL, + DA9052_ADC_TSI_YP); +static SENSOR_DEVICE_ATTR(in72_label, 0444, show_label, NULL, + DA9052_ADC_TSI_YP); +static SENSOR_DEVICE_ATTR(in73_input, 0444, da9052_read_tsi, NULL, + DA9052_ADC_TSI_YN); +static SENSOR_DEVICE_ATTR(in73_label, 0444, show_label, NULL, + DA9052_ADC_TSI_YN); + +static SENSOR_DEVICE_ATTR(curr1_input, 0444, da9052_read_ich, NULL, DA9052_ADC_ICH); -static SENSOR_DEVICE_ATTR(curr1_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(curr1_label, 0444, show_label, NULL, DA9052_ADC_ICH); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, da9052_read_tbat, NULL, +static SENSOR_DEVICE_ATTR(temp2_input, 0444, da9052_read_tbat, NULL, DA9052_ADC_TBAT); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(temp2_label, 0444, show_label, NULL, DA9052_ADC_TBAT); -static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, da9052_read_tjunc, NULL, +static SENSOR_DEVICE_ATTR(temp8_input, 0444, da9052_read_tjunc, NULL, DA9052_ADC_TJUNC); -static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_label, NULL, +static SENSOR_DEVICE_ATTR(temp8_label, 0444, show_label, NULL, DA9052_ADC_TJUNC); static struct attribute *da9052_attrs[] = { @@ -246,6 +391,14 @@ static struct attribute *da9052_attrs[] = { &sensor_dev_attr_in5_label.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in6_label.dev_attr.attr, + &sensor_dev_attr_in70_input.dev_attr.attr, + &sensor_dev_attr_in70_label.dev_attr.attr, + &sensor_dev_attr_in71_input.dev_attr.attr, + &sensor_dev_attr_in71_label.dev_attr.attr, + &sensor_dev_attr_in72_input.dev_attr.attr, + &sensor_dev_attr_in72_label.dev_attr.attr, + &sensor_dev_attr_in73_input.dev_attr.attr, + &sensor_dev_attr_in73_label.dev_attr.attr, &sensor_dev_attr_in9_input.dev_attr.attr, &sensor_dev_attr_in9_label.dev_attr.attr, &sensor_dev_attr_curr1_input.dev_attr.attr, @@ -257,29 +410,117 @@ static struct attribute *da9052_attrs[] = { NULL }; -ATTRIBUTE_GROUPS(da9052); +static const struct attribute_group da9052_group = { + .attrs = da9052_attrs, + .is_visible = da9052_channel_is_visible, +}; +__ATTRIBUTE_GROUPS(da9052); + +static irqreturn_t da9052_tsi_datardy_irq(int irq, void *data) +{ + struct da9052_hwmon *hwmon = data; + + complete(&hwmon->tsidone); + return IRQ_HANDLED; +} static int da9052_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct da9052_hwmon *hwmon; struct device *hwmon_dev; + int err; hwmon = devm_kzalloc(dev, sizeof(struct da9052_hwmon), GFP_KERNEL); if (!hwmon) return -ENOMEM; + platform_set_drvdata(pdev, hwmon); + mutex_init(&hwmon->hwmon_lock); hwmon->da9052 = dev_get_drvdata(pdev->dev.parent); + init_completion(&hwmon->tsidone); + + hwmon->tsi_as_adc = + device_property_read_bool(pdev->dev.parent, "dlg,tsi-as-adc"); + + if (hwmon->tsi_as_adc) { + hwmon->tsiref = devm_regulator_get(pdev->dev.parent, "tsiref"); + if (IS_ERR(hwmon->tsiref)) { + err = PTR_ERR(hwmon->tsiref); + dev_err(&pdev->dev, "failed to get tsiref: %d", err); + return err; + } + + err = regulator_enable(hwmon->tsiref); + if (err) + return err; + + hwmon->tsiref_mv = regulator_get_voltage(hwmon->tsiref); + if (hwmon->tsiref_mv < 0) { + err = hwmon->tsiref_mv; + goto exit_regulator; + } + + /* convert from microvolt (DT) to millivolt (hwmon) */ + hwmon->tsiref_mv /= 1000; + + /* TSIREF limits from datasheet */ + if (hwmon->tsiref_mv < 1800 || hwmon->tsiref_mv > 2600) { + dev_err(hwmon->da9052->dev, "invalid TSIREF voltage: %d", + hwmon->tsiref_mv); + err = -ENXIO; + goto exit_regulator; + } + + /* disable touchscreen features */ + da9052_reg_write(hwmon->da9052, DA9052_TSI_CONT_A_REG, 0x00); + + err = da9052_request_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, + "tsiready-irq", da9052_tsi_datardy_irq, + hwmon); + if (err) { + dev_err(&pdev->dev, "Failed to register TSIRDY IRQ: %d", + err); + goto exit_regulator; + } + } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, "da9052", hwmon, da9052_groups); - return PTR_ERR_OR_ZERO(hwmon_dev); + err = PTR_ERR_OR_ZERO(hwmon_dev); + if (err) + goto exit_irq; + + return 0; + +exit_irq: + if (hwmon->tsi_as_adc) + da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon); +exit_regulator: + if (hwmon->tsiref) + regulator_disable(hwmon->tsiref); + + return err; +} + +static int da9052_hwmon_remove(struct platform_device *pdev) +{ + struct da9052_hwmon *hwmon = platform_get_drvdata(pdev); + + if (hwmon->tsi_as_adc) { + da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon); + regulator_disable(hwmon->tsiref); + } + + return 0; } static struct platform_driver da9052_hwmon_driver = { .probe = da9052_hwmon_probe, + .remove = da9052_hwmon_remove, .driver = { .name = "da9052-hwmon", }, diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c index 0f0277e7aae5..0801f48a41f7 100644 --- a/drivers/hwmon/ftsteutates.c +++ b/drivers/hwmon/ftsteutates.c @@ -60,7 +60,7 @@ static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; -static struct i2c_device_id fts_id[] = { +static const struct i2c_device_id fts_id[] = { { "ftsteutates", 0 }, { } }; @@ -435,6 +435,7 @@ clear_temp_alarm(struct device *dev, struct device_attribute *devattr, goto error; data->valid = false; + ret = count; error: mutex_unlock(&data->update_lock); return ret; @@ -508,6 +509,7 @@ clear_fan_alarm(struct device *dev, struct device_attribute *devattr, goto error; data->valid = false; + ret = count; error: mutex_unlock(&data->update_lock); return ret; diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index dd6e17c1076b..c9790e2c3440 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -85,7 +85,7 @@ static umode_t hwmon_dev_name_is_visible(struct kobject *kobj, return attr->mode; } -static struct attribute_group hwmon_dev_attr_group = { +static const struct attribute_group hwmon_dev_attr_group = { .attrs = hwmon_dev_attrs, .is_visible = hwmon_dev_name_is_visible, }; @@ -135,7 +135,7 @@ static int hwmon_thermal_get_temp(void *data, int *temp) return 0; } -static struct thermal_zone_of_device_ops hwmon_thermal_ops = { +static const struct thermal_zone_of_device_ops hwmon_thermal_ops = { .get_temp = hwmon_thermal_get_temp, }; diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index a5a9f457b7f7..9397d2f0e79a 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -495,7 +495,7 @@ static struct { }; #ifdef MODULE -static struct pci_device_id i5k_amb_ids[] = { +static const struct pci_device_id i5k_amb_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) }, { 0, } diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 4dfc7238313e..f8499cb95fec 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -497,12 +497,14 @@ static const struct it87_devices it87_devices[] = { #define has_vin3_5v(data) ((data)->features & FEAT_VIN3_5V) struct it87_sio_data { + int sioaddr; enum chips type; /* Values read from Super-I/O config space */ u8 revision; u8 vid_value; u8 beep_pin; u8 internal; /* Internal sensors can be labeled */ + bool need_in7_reroute; /* Features skipped based on config or DMI */ u16 skip_in; u8 skip_vid; @@ -517,6 +519,7 @@ struct it87_sio_data { */ struct it87_data { const struct attribute_group *groups[7]; + int sioaddr; enum chips type; u32 features; u8 peci_mask; @@ -532,6 +535,7 @@ struct it87_data { u16 in_internal; /* Bitfield, internal sensors (for labels) */ u16 has_in; /* Bitfield, voltage sensors enabled */ u8 in[NUM_VIN][3]; /* [nr][0]=in, [1]=min, [2]=max */ + bool need_in7_reroute; u8 has_fan; /* Bitfield, fans enabled */ u16 fan[NUM_FAN][2]; /* Register values, [nr][0]=fan, [1]=min */ u8 has_temp; /* Bitfield, temp sensors enabled */ @@ -2487,6 +2491,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, } err = 0; + sio_data->sioaddr = sioaddr; sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f; pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type, it87_devices[sio_data->type].suffix, @@ -2575,6 +2580,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, reg2c |= BIT(1); superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg2c); + sio_data->need_in7_reroute = true; pr_notice("Routing internal VCCH5V to in7.\n"); } pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n"); @@ -2761,13 +2767,13 @@ static int __init it87_find(int sioaddr, unsigned short *address, uart6 = sio_data->type == it8782 && (reg & BIT(2)); /* - * The IT8720F has no VIN7 pin, so VCCH should always be + * The IT8720F has no VIN7 pin, so VCCH5V should always be * routed internally to VIN7 with an internal divider. * Curiously, there still is a configuration bit to control * this, which means it can be set incorrectly. And even * more curiously, many boards out there are improperly * configured, even though the IT8720F datasheet claims - * that the internal routing of VCCH to VIN7 is the default + * that the internal routing of VCCH5V to VIN7 is the default * setting. So we force the internal routing in this case. * * On IT8782F, VIN7 is multiplexed with one of the UART6 pins. @@ -2777,7 +2783,8 @@ static int __init it87_find(int sioaddr, unsigned short *address, if ((sio_data->type == it8720 || uart6) && !(reg & BIT(1))) { reg |= BIT(1); superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg); - pr_notice("Routing internal VCCH to in7\n"); + sio_data->need_in7_reroute = true; + pr_notice("Routing internal VCCH5V to in7\n"); } if (reg & BIT(0)) sio_data->internal |= BIT(0); @@ -2828,13 +2835,89 @@ exit: return err; } +/* |