diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-08-31 14:37:41 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-08-31 14:37:41 -0700 |
| commit | e7c1bbcf0c315c56cd970642214aa1df3d8cf61d (patch) | |
| tree | 45a5242c87fbe418b98cebf81659b809e21ed313 | |
| parent | 871dda463c6f2c2a4a660937e2f57616146f42de (diff) | |
| parent | 0e35f63f7f4eebd268ec236fd1bbf4e561ce8de5 (diff) | |
| download | linux-e7c1bbcf0c315c56cd970642214aa1df3d8cf61d.tar.gz linux-e7c1bbcf0c315c56cd970642214aa1df3d8cf61d.tar.bz2 linux-e7c1bbcf0c315c56cd970642214aa1df3d8cf61d.zip | |
Merge tag 'hwmon-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
"New drivers for:
- Aquacomputer D5 Next
- SB-RMI power module
Added chip support to existing drivers:
- Support for various Zen2 and Zen3 APUs and for Yellow Carp (SMU
v13) added to k10temp driver
- Support for Silicom n5010 PAC added to intel-m10-bmc driver
- Support for BPD-RS600 added to pmbus/bpa-rs600 driver
Other notable changes:
- In k10temp, do not display Tdie on Zen CPUs if there is no
difference between Tdie and Tctl
- Converted adt7470 and dell-smm drivers to use
devm_hwmon_device_register_with_info API
- Support for temperature/pwm tables added to axi-fan-control driver
- Enabled fan control for Dell Precision 7510 in dell-smm driver
Various other minor improvements and fixes in several drivers"
* tag 'hwmon-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (41 commits)
hwmon: add driver for Aquacomputer D5 Next
hwmon: (adt7470) Convert to devm_hwmon_device_register_with_info API
hwmon: (adt7470) Convert to use regmap
hwmon: (adt7470) Fix some style issues
hwmon: (k10temp) Add support for yellow carp
hwmon: (k10temp) Rework the temperature offset calculation
hwmon: (k10temp) Don't show Tdie for all Zen/Zen2/Zen3 CPU/APU
hwmon: (k10temp) Add additional missing Zen2 and Zen3 APUs
hwmon: remove amd_energy driver in Makefile
hwmon: (dell-smm) Rework SMM function debugging
hwmon: (dell-smm) Mark i8k_get_fan_nominal_speed as __init
hwmon: (dell-smm) Mark tables as __initconst
hwmon: (pmbus/bpa-rs600) Add workaround for incorrect Pin max
hwmon: (pmbus/bpa-rs600) Don't use rated limits as warn limits
hwmon: (axi-fan-control) Support temperature vs pwm points
hwmon: (axi-fan-control) Handle irqs in natural order
hwmon: (axi-fan-control) Make sure the clock is enabled
hwmon: (pmbus/ibm-cffps) Fix write bits for LED control
hwmon: (w83781d) Match on device tree compatibles
dt-bindings: hwmon: Add bindings for Winbond W83781D
...
25 files changed, 2276 insertions, 1177 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/amd,sbrmi.yaml b/Documentation/devicetree/bindings/hwmon/amd,sbrmi.yaml new file mode 100644 index 000000000000..7598b083979c --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/amd,sbrmi.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/amd,sbrmi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: > + Sideband Remote Management Interface (SB-RMI) compliant + AMD SoC power device. + +maintainers: + - Akshay Gupta <Akshay.Gupta@amd.com> + +description: | + SB Remote Management Interface (SB-RMI) is an SMBus compatible + interface that reports AMD SoC's Power (normalized Power) using, + Mailbox Service Request and resembles a typical 8-pin remote power + sensor's I2C interface to BMC. The power attributes in hwmon + reports power in microwatts. + +properties: + compatible: + enum: + - amd,sbrmi + + reg: + maxItems: 1 + description: | + I2C bus address of the device as specified in Section SBI SMBus Address + of the SoC register reference. The SB-RMI address is normally 78h for + socket 0 and 70h for socket 1, but it could vary based on hardware + address select pins. + \[open source SoC register reference\] + https://www.amd.com/en/support/tech-docs?keyword=55898 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + sbrmi@3c { + compatible = "amd,sbrmi"; + reg = <0x3c>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml b/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml new file mode 100644 index 000000000000..31ce77a4b087 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/hwmon/winbond,w83781d.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Winbond W83781 and compatible hardware monitor IC + +maintainers: + - Linus Walleij <linus.walleij@linaro.org> + +properties: + compatible: + enum: + - winbond,w83781d + - winbond,w83781g + - winbond,w83782d + - winbond,w83783s + - asus,as99127f + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + temperature-sensor@28 { + compatible = "winbond,w83781d"; + reg = <0x28>; + }; + }; diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst new file mode 100644 index 000000000000..1f4bb4ba2e4b --- /dev/null +++ b/Documentation/hwmon/aquacomputer_d5next.rst @@ -0,0 +1,61 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +Kernel driver aquacomputer-d5next +================================= + +Supported devices: + +* Aquacomputer D5 Next watercooling pump + +Author: Aleksa Savic + +Description +----------- + +This driver exposes hardware sensors of the Aquacomputer D5 Next watercooling +pump, which communicates through a proprietary USB HID protocol. + +Available sensors are pump and fan speed, power, voltage and current, as +well as coolant temperature. Also available through debugfs are the serial +number, firmware version and power-on count. + +Attaching a fan is optional and allows it to be controlled using temperature +curves directly from the pump. If it's not connected, the fan-related sensors +will report zeroes. + +The pump can be configured either through software or via its physical +interface. Configuring the pump through this driver is not implemented, as it +seems to require sending it a complete configuration. That includes addressable +RGB LEDs, for which there is no standard sysfs interface. Thus, that task is +better suited for userspace tools. + +Usage notes +----------- + +The pump communicates via HID reports. The driver is loaded automatically by +the kernel and supports hotswapping. + +Sysfs entries +------------- + +============ ============================================= +temp1_input Coolant temperature (in millidegrees Celsius) +fan1_input Pump speed (in RPM) +fan2_input Fan speed (in RPM) +power1_input Pump power (in micro Watts) +power2_input Fan power (in micro Watts) +in0_input Pump voltage (in milli Volts) +in1_input Fan voltage (in milli Volts) +in2_input +5V rail voltage (in milli Volts) +curr1_input Pump current (in milli Amperes) +curr2_input Fan current (in milli Amperes) +============ ============================================= + +Debugfs entries +--------------- + +================ =============================================== +serial_number Serial number of the pump +firmware_version Version of installed firmware +power_cycles Count of how many times the pump was powered on +================ =============================================== diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index bc01601ea81a..f790f1260c33 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -39,6 +39,7 @@ Hardware Monitoring Kernel Drivers adt7475 aht10 amc6821 + aquacomputer_d5next asb100 asc7621 aspeed-pwm-tacho @@ -160,6 +161,7 @@ Hardware Monitoring Kernel Drivers pwm-fan q54sj108a2 raspberrypi-hwmon + sbrmi sbtsi_temp sch5627 sch5636 diff --git a/Documentation/hwmon/sbrmi.rst b/Documentation/hwmon/sbrmi.rst new file mode 100644 index 000000000000..296049e13ac9 --- /dev/null +++ b/Documentation/hwmon/sbrmi.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +Kernel driver sbrmi +=================== + +Supported hardware: + + * Sideband Remote Management Interface (SB-RMI) compliant AMD SoC + device connected to the BMC via the APML. + + Prefix: 'sbrmi' + + Addresses scanned: This driver doesn't support address scanning. + + To instantiate this driver on an AMD CPU with SB-RMI + support, the i2c bus number would be the bus connected from the board + management controller (BMC) to the CPU. + The SMBus address is really 7 bits. Some vendors and the SMBus + specification show the address as 8 bits, left justified with the R/W + bit as a write (0) making bit 0. Some vendors use only the 7 bits + to describe the address. + As mentioned in AMD's APML specification, The SB-RMI address is + normally 78h(0111 100W) or 3Ch(011 1100) for socket 0 and 70h(0111 000W) + or 38h(011 1000) for socket 1, but it could vary based on hardware + address select pins. + + Datasheet: The SB-RMI interface and protocol along with the Advanced + Platform Management Link (APML) Specification is available + as part of the open source SoC register reference at: + + https://www.amd.com/en/support/tech-docs?keyword=55898 + +Author: Akshay Gupta <akshay.gupta@amd.com> + +Description +----------- + +The APML provides a way to communicate with the SB Remote Management interface +(SB-RMI) module from the external SMBus master that can be used to report socket +power on AMD platforms using mailbox command and resembles a typical 8-pin remote +power sensor's I2C interface to BMC. + +This driver implements current power with power cap and power cap max. + +sysfs-Interface +--------------- +Power sensors can be queried and set via the standard ``hwmon`` interface +on ``sysfs``, under the directory ``/sys/class/hwmon/hwmonX`` for some value +of ``X`` (search for the ``X`` such that ``/sys/class/hwmon/hwmonX/name`` has +content ``sbrmi``) + +================ ===== ======================================================== +Name Perm Description +================ ===== ======================================================== +power1_input RO Current Power consumed +power1_cap RW Power limit can be set between 0 and power1_cap_max +power1_cap_max RO Maximum powerlimit calculated and reported by the SMU FW +================ ===== ======================================================== + +The following example show how the 'Power' attribute from the i2c-addresses +can be monitored using the userspace utilities like ``sensors`` binary:: + + # sensors + sbrmi-i2c-1-38 + Adapter: bcm2835 I2C adapter + power1: 61.00 W (cap = 225.00 W) + + sbrmi-i2c-1-3c + Adapter: bcm2835 I2C adapter + power1: 28.39 W (cap = 224.77 W) + # + +Also, Below shows how get and set the values from sysfs entries individually:: + # cat /sys/class/hwmon/hwmon1/power1_cap_max + 225000000 + + # echo 180000000 > /sys/class/hwmon/hwmon1/power1_cap + # cat /sys/class/hwmon/hwmon1/power1_cap + 180000000 diff --git a/Documentation/hwmon/scpi-hwmon.rst b/Documentation/hwmon/scpi-hwmon.rst index eee7022b44db..1e3f83ec0658 100644 --- a/Documentation/hwmon/scpi-hwmon.rst +++ b/Documentation/hwmon/scpi-hwmon.rst @@ -32,5 +32,5 @@ Usage Notes The driver relies on device tree node to indicate the presence of SCPI support in the kernel. See -Documentation/devicetree/bindings/arm/arm,scpi.txt for details of the +Documentation/devicetree/bindings/firmware/arm,scpi.yaml for details of the devicetree node. diff --git a/Documentation/hwmon/sht4x.rst b/Documentation/hwmon/sht4x.rst index 3b37abcd4a46..c318e5582ead 100644 --- a/Documentation/hwmon/sht4x.rst +++ b/Documentation/hwmon/sht4x.rst @@ -42,4 +42,4 @@ humidity1_input Measured humidity in %H update_interval The minimum interval for polling the sensor, in milliseconds. Writable. Must be at least 2000. -============== ============================================= +=============== ============================================ diff --git a/MAINTAINERS b/MAINTAINERS index 629a011a38b8..142e27504f4d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1316,6 +1316,13 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/aptina-pll.* +AQUACOMPUTER D5 NEXT PUMP SENSOR DRIVER +M: Aleksa Savic <savicaleksa83@gmail.com> +L: linux-hwmon@vger.kernel.org +S: Maintained +F: Documentation/hwmon/aquacomputer_d5next.rst +F: drivers/hwmon/aquacomputer_d5next.c + AQUANTIA ETHERNET DRIVER (atlantic) M: Igor Russkikh <irusskikh@marvell.com> L: netdev@vger.kernel.org diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 23dda362dc0f..c92c9c774c0e 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -25,6 +25,8 @@ #define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444 #define PCI_DEVICE_ID_AMD_19H_DF_F4 0x1654 +#define PCI_DEVICE_ID_AMD_19H_M40H_ROOT 0x14b5 +#define PCI_DEVICE_ID_AMD_19H_M40H_DF_F4 0x167d #define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4 0x166e /* Protect the PCI config register pairs used for SMN and DF indirect access. */ @@ -37,6 +39,7 @@ static const struct pci_device_id amd_root_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_ROOT) }, {} }; @@ -58,6 +61,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) }, {} }; @@ -74,6 +78,7 @@ static const struct pci_device_id amd_nb_link_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, {} diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e3675377bc5d..c4578e8f34bb 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -254,6 +254,16 @@ config SENSORS_AHT10 This driver can also be built as a module. If so, the module will be called aht10. +config SENSORS_AQUACOMPUTER_D5NEXT + tristate "Aquacomputer D5 Next watercooling pump" + depends on USB_HID + help + If you say yes here you get support for the Aquacomputer D5 Next + watercooling pump sensors. + + This driver can also be built as a module. If so, the module + will be called aquacomputer_d5next. + config SENSORS_AS370 tristate "Synaptics AS370 SoC hardware monitoring driver" help @@ -1551,6 +1561,16 @@ config SENSORS_SBTSI This driver can also be built as a module. If so, the module will be called sbtsi_temp. +config SENSORS_SBRMI + tristate "Emulated SB-RMI sensor" + depends on I2C + help + If you say yes here you get support for emulated RMI + sensors on AMD SoCs with APML interface connected to a BMC device. + + This driver can also be built as a module. If so, the module will + be called sbrmi. + config SENSORS_SHT15 tristate "Sensiron humidity and temperature sensors. SHT15 and compat." depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d712c61c1f5e..162940270661 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -45,8 +45,8 @@ obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o obj-$(CONFIG_SENSORS_AHT10) += aht10.o -obj-$(CONFIG_SENSORS_AMD_ENERGY) += amd_energy.o obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o +obj-$(CONFIG_SENSORS_AQUACOMPUTER_D5NEXT) += aquacomputer_d5next.o obj-$(CONFIG_SENSORS_ARM_SCMI) += scmi-hwmon.o obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o obj-$(CONFIG_SENSORS_AS370) += as370-hwmon.o @@ -164,6 +164,7 @@ obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o +obj-$(CONFIG_SENSORS_SBRMI) += sbrmi.o obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 2e8feacccf84..d519aca4a9d6 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/log2.h> #include <linux/kthread.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <linux/util_macros.h> @@ -35,7 +36,10 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; #define ADT7470_REG_PWM_MAX_BASE_ADDR 0x38 #define ADT7470_REG_PWM_MAX_MAX_ADDR 0x3B #define ADT7470_REG_CFG 0x40 +#define ADT7470_STRT_MASK 0x01 +#define ADT7470_TEST_MASK 0x02 #define ADT7470_FSPD_MASK 0x04 +#define ADT7470_T05_STB_MASK 0x80 #define ADT7470_REG_ALARM1 0x41 #define ADT7470_R1T_ALARM 0x01 #define ADT7470_R2T_ALARM 0x02 @@ -137,7 +141,7 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; #define ADT7470_FREQ_SHIFT 4 struct adt7470_data { - struct i2c_client *client; + struct regmap *regmap; struct mutex lock; char sensors_valid; char limits_valid; @@ -171,51 +175,76 @@ struct adt7470_data { * 16-bit registers on the ADT7470 are low-byte first. The data sheet says * that the low byte must be read before the high byte. */ -static inline int adt7470_read_word_data(struct i2c_client *client, u8 reg) +static inline int adt7470_read_word_data(struct adt7470_data *data, unsigned int reg, + unsigned int *val) { - u16 foo; - foo = i2c_smbus_read_byte_data(client, reg); - foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); - return foo; + u8 regval[2]; + int err; + + err = regmap_bulk_read(data->regmap, reg, ®val, 2); + if (err < 0) + return err; + + *val = regval[0] | (regval[1] << 8); + + return 0; } -static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg, - u16 value) +static inline int adt7470_write_word_data(struct adt7470_data *data, unsigned int reg, + unsigned int val) { - return i2c_smbus_write_byte_data(client, reg, value & 0xFF) - || i2c_smbus_write_byte_data(client, reg + 1, value >> 8); + u8 regval[2]; + + regval[0] = val & 0xFF; + regval[1] = val >> 8; + + return regmap_bulk_write(data->regmap, reg, ®val, 2); } /* Probe for temperature sensors. Assumes lock is held */ -static int adt7470_read_temperatures(struct i2c_client *client, - struct adt7470_data *data) +static int adt7470_read_temperatures(struct adt7470_data *data) { unsigned long res; + unsigned int pwm_cfg[2]; + int err; int i; - u8 cfg, pwm[4], pwm_cfg[2]; + u8 pwm[ADT7470_FAN_COUNT]; /* save pwm[1-4] config register */ - pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0)); - pwm_cfg[1] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(2)); + err = regmap_read(data->regmap, ADT7470_REG_PWM_CFG(0), &pwm_cfg[0]); + if (err < 0) + return err; + err = regmap_read(data->regmap, ADT7470_REG_PWM_CFG(2), &pwm_cfg[1]); + if (err < 0) + return err; /* set manual pwm to whatever it is set to now */ - for (i = 0; i < ADT7470_FAN_COUNT; i++) - pwm[i] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM(i)); + err = regmap_bulk_read(data->regmap, ADT7470_REG_PWM(0), &pwm[0], + ADT7470_PWM_COUNT); + if (err < 0) + return err; /* put pwm in manual mode */ - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), - pwm_cfg[0] & ~(ADT7470_PWM_AUTO_MASK)); - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), - pwm_cfg[1] & ~(ADT7470_PWM_AUTO_MASK)); + err = regmap_update_bits(data->regmap, ADT7470_REG_PWM_CFG(0), + ADT7470_PWM_AUTO_MASK, 0); + if (err < 0) + return err; + err = regmap_update_bits(data->regmap, ADT7470_REG_PWM_CFG(2), + ADT7470_PWM_AUTO_MASK, 0); + if (err < 0) + return err; /* write pwm control to whatever it was */ - for (i = 0; i < ADT7470_FAN_COUNT; i++) - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(i), pwm[i]); + err = regmap_bulk_write(data->regmap, ADT7470_REG_PWM(0), &pwm[0], + ADT7470_PWM_COUNT); + if (err < 0) + return err; /* start reading temperature sensors */ - cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - cfg |= 0x80; - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); + err = regmap_update_bits(data->regmap, ADT7470_REG_CFG, + ADT7470_T05_STB_MASK, ADT7470_T05_STB_MASK); + if (err < 0) + return err; /* Delay is 200ms * number of temp sensors. */ res = msleep_interruptible((data->num_temp_sensors >= 0 ? @@ -223,26 +252,31 @@ static int adt7470_read_temperatures(struct i2c_client *client, TEMP_COLLECTION_TIME)); /* done reading temperature sensors */ - cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - cfg &= ~0x80; - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); + err = regmap_update_bits(data->regmap, ADT7470_REG_CFG, + ADT7470_T05_STB_MASK, 0); + if (err < 0) + return err; /* restore pwm[1-4] config registers */ - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]); - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]); - - if (res) { - pr_err("ha ha, interrupted\n"); + err = regmap_write(data->regmap, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]); + if (err < 0) + return err; + err = regmap_write(data->regmap, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]); + if (err < 0) + return err; + + if (res) return -EAGAIN; - } /* Only count fans if we have to */ if (data->num_temp_sensors >= 0) return 0; + err = regmap_bulk_read(data->regmap, ADT7470_TEMP_REG(0), &data->temp[0], + ADT7470_TEMP_COUNT); + if (err < 0) + return err; for (i = 0; i < ADT7470_TEMP_COUNT; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_REG(i)); if (data->temp[i]) data->num_temp_sensors = i + 1; } @@ -257,7 +291,7 @@ static int adt7470_update_thread(void *p) while (!kthread_should_stop()) { mutex_lock(&data->lock); - adt7470_read_temperatures(client, data); + adt7470_read_temperatures(data); mutex_unlock(&data->lock); set_current_state(TASK_INTERRUPTIBLE); @@ -272,89 +306,116 @@ static int adt7470_update_thread(void *p) static int adt7470_update_sensors(struct adt7470_data *data) { - struct i2c_client *client = data->client; - u8 cfg; + unsigned int val; + int err; int i; if (!data->temperatures_probed) - adt7470_read_temperatures(client, data); + err = adt7470_read_temperatures(data); else - for (i = 0; i < ADT7470_TEMP_COUNT; i++) - data->temp[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_REG(i)); + err = regmap_bulk_read(data->regmap, ADT7470_TEMP_REG(0), &data->temp[0], + ADT7470_TEMP_COUNT); + if (err < 0) + return err; - for (i = 0; i < ADT7470_FAN_COUNT; i++) - data->fan[i] = adt7470_read_word_data(client, - ADT7470_REG_FAN(i)); + for (i = 0; i < ADT7470_FAN_COUNT; i++) { + err = adt7470_read_word_data(data, ADT7470_REG_FAN(i), &val); + if (err < 0) + return err; + data->fan[i] = val; + } - for (i = 0; i < ADT7470_PWM_COUNT; i++) { - int reg; - int reg_mask; + err = regmap_bulk_read(data->regmap, ADT7470_REG_PWM(0), &data->pwm[0], ADT7470_PWM_COUNT); + if (err < 0) + return err; - data->pwm[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM(i)); + for (i = 0; i < ADT7470_PWM_COUNT; i++) { + unsigned int mask; if (i % 2) - reg_mask = ADT7470_PWM2_AUTO_MASK; + mask = ADT7470_PWM2_AUTO_MASK; else - reg_mask = ADT7470_PWM1_AUTO_MASK; + mask = ADT7470_PWM1_AUTO_MASK; - reg = ADT7470_REG_PWM_CFG(i); - if (i2c_smbus_read_byte_data(client, reg) & reg_mask) - data->pwm_automatic[i] = 1; - else - data->pwm_automatic[i] = 0; + err = regmap_read(data->regmap, ADT7470_REG_PWM_CFG(i), &val); + if (err < 0) + return err; + data->pwm_automatic[i] = !!(val & mask); - reg = ADT7470_REG_PWM_AUTO_TEMP(i); - cfg = i2c_smbus_read_byte_data(client, reg); + err = regmap_read(data->regmap, ADT7470_REG_PWM_AUTO_TEMP(i), &val); + if (err < 0) + return err; if (!(i % 2)) - data->pwm_auto_temp[i] = cfg >> 4; + data->pwm_auto_temp[i] = val >> 4; else - data->pwm_auto_temp[i] = cfg & 0xF; + data->pwm_auto_temp[i] = val & 0xF; } - if (i2c_smbus_read_byte_data(client, ADT7470_REG_CFG) & - ADT7470_FSPD_MASK) - data->force_pwm_max = 1; - else - data->force_pwm_max = 0; + err = regmap_read(data->regmap, ADT7470_REG_CFG, &val); + if (err < 0) + return err; + data->force_pwm_max = !!(val & ADT7470_FSPD_MASK); + + err = regmap_read(data->regmap, ADT7470_REG_ALARM1, &val); + if (err < 0) + return err; + data->alarm = val; + if (data->alarm & ADT7470_OOL_ALARM) { + err = regmap_read(data->regmap, ADT7470_REG_ALARM2, &val); + if (err < 0) + return err; + data->alarm |= ALARM2(val); + } - data->alarm = i2c_smbus_read_byte_data(client, ADT7470_REG_ALARM1); - if (data->alarm & ADT7470_OOL_ALARM) - data->alarm |= ALARM2(i2c_smbus_read_byte_data(client, - ADT7470_REG_ALARM2)); - data->alarms_mask = adt7470_read_word_data(client, - ADT7470_REG_ALARM1_MASK); + err = adt7470_read_word_data(data, ADT7470_REG_ALARM1_MASK, &val); + if (err < 0) + return err; + data->alarms_mask = val; return 0; } static int adt7470_update_limits(struct adt7470_data *data) { - struct i2c_client *client = data->client; + unsigned int val; + int err; int i; for (i = 0; i < ADT7470_TEMP_COUNT; i++) { - data->temp_min[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_MIN_REG(i)); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_MAX_REG(i)); + err = regmap_read(data->regmap, ADT7470_TEMP_MIN_REG(i), &val); + if (err < 0) + return err; + data->temp_min[i] = (s8)val; + err = regmap_read(data->regmap, ADT7470_TEMP_MAX_REG(i), &val); + if (err < 0) + return err; + data->temp_max[i] = (s8)val; } for (i = 0; i < ADT7470_FAN_COUNT; i++) { - data->fan_min[i] = adt7470_read_word_data(client, - ADT7470_REG_FAN_MIN(i)); - data->fan_max[i] = adt7470_read_word_data(client, - ADT7470_REG_FAN_MAX(i)); + err = adt7470_read_word_data(data, ADT7470_REG_FAN_MIN(i), &val); + if (err < 0) + return err; + data->fan_min[i] = val; + err = adt7470_read_word_data(data, ADT7470_REG_FAN_MAX(i), &val); + if (err < 0) + return err; + data->fan_max[i] = val; } for (i = 0; i < ADT7470_PWM_COUNT; i++) { - data->pwm_max[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM_MAX(i)); - data->pwm_min[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM_MIN(i)); - data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM_TMIN(i)); + err = regmap_read(data->regmap, ADT7470_REG_PWM_MAX(i), &val); + if (err < 0) + return err; + data->pwm_max[i] = val; + err = regmap_read(data->regmap, ADT7470_REG_PWM_MIN(i), &val); + if (err < 0) + return err; + data->pwm_min[i] = val; + err = regmap_read(data->regmap, ADT7470_REG_PWM_TMIN(i), &val); + if (err < 0) + return err; + data->pwm_tmin[i] = (s8)val; } return 0; @@ -472,93 +533,63 @@ static ssize_t num_temp_sensors_store(struct device *dev, return count; } -static ssize_t temp_min_show(struct device *dev, - struct device_attribute *devattr, char *buf) +static int adt7470_temp_read(struct device *dev, u32 attr, int channel, long *val) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7470_data *data = adt74 |
