summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-08-31 14:37:41 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-08-31 14:37:41 -0700
commite7c1bbcf0c315c56cd970642214aa1df3d8cf61d (patch)
tree45a5242c87fbe418b98cebf81659b809e21ed313
parent871dda463c6f2c2a4a660937e2f57616146f42de (diff)
parent0e35f63f7f4eebd268ec236fd1bbf4e561ce8de5 (diff)
downloadlinux-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 ...
-rw-r--r--Documentation/devicetree/bindings/hwmon/amd,sbrmi.yaml53
-rw-r--r--Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml41
-rw-r--r--Documentation/hwmon/aquacomputer_d5next.rst61
-rw-r--r--Documentation/hwmon/index.rst2
-rw-r--r--Documentation/hwmon/sbrmi.rst79
-rw-r--r--Documentation/hwmon/scpi-hwmon.rst2
-rw-r--r--Documentation/hwmon/sht4x.rst2
-rw-r--r--MAINTAINERS7
-rw-r--r--arch/x86/kernel/amd_nb.c5
-rw-r--r--drivers/hwmon/Kconfig20
-rw-r--r--drivers/hwmon/Makefile3
-rw-r--r--drivers/hwmon/adt7470.c1051
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c363
-rw-r--r--drivers/hwmon/axi-fan-control.c117
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c910
-rw-r--r--drivers/hwmon/fam15h_power.c4
-rw-r--r--drivers/hwmon/intel-m10-bmc-hwmon.c116
-rw-r--r--drivers/hwmon/k10temp.c30
-rw-r--r--drivers/hwmon/ntc_thermistor.c20
-rw-r--r--drivers/hwmon/pmbus/bpa-rs600.c68
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c6
-rw-r--r--drivers/hwmon/sbrmi.c359
-rw-r--r--drivers/hwmon/w83627ehf.c122
-rw-r--r--drivers/hwmon/w83781d.c11
-rw-r--r--include/linux/pci_ids.h1
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, &regval, 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, &regval, 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