Merge tag 'hwmon-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 29 Aug 2023 17:02:35 +0000 (10:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 29 Aug 2023 17:02:35 +0000 (10:02 -0700)
Pull hwmon updates from Guenter Roeck:
 "New drivers:

   - Renesas HS3001

  Chip support added to existing drivers:

   - pmbus/mp2975 driver now supports MP2971 and MP2973

  Functional improvements:

   - Additional voltage and temperature sensor support for
     NCT6798/NCT6799 in nt6755 driver

   - it87 driver now detects AMDTSI sensor type

   - dimmtemp now supports more than 32 DIMMs

  Driver removals:

   - sm665 driver removed as unsupportable and long since obsolete

  .. and minor fixes, cleanups, and simplifications in several drivers"

* tag 'hwmon-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (57 commits)
  hwmon: (tmp513) Simplify probe()
  hwmon: (tmp513) Fix the channel number in tmp51x_is_visible()
  hwmon: (mlxreg-fan) Extend number of supported fans
  hwmon: (sis5595) Do PCI error checks on own line
  hwmon: (vt8231) Do PCI error checks on own line
  hwmon: (via686a) Do PCI error checks on own line
  hwmon: pmbus: Fix -EIO seen on pli1209
  hwmon: pmbus: Drop unnecessary clear fault page
  hwmon: pmbus: Reduce clear fault page invocations
  hwmon: (nsa320-hwmon) Remove redundant of_match_ptr()
  hwmon: (pmbus/ucd9200) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (pmbus/ucd9000) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (pmbus/tps53679) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (pmbus/ibm-cffps) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (tmp513) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (max6697) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (max20730) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (lm90) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (lm85) fix Wvoid-pointer-to-enum-cast warning
  hwmon: (lm75) fix Wvoid-pointer-to-enum-cast warning
  ...

70 files changed:
Documentation/devicetree/bindings/trivial-devices.yaml
Documentation/hwmon/hs3001.rst [new file with mode: 0644]
Documentation/hwmon/index.rst
Documentation/hwmon/nct6775.rst
Documentation/hwmon/pmbus.rst
Documentation/hwmon/smm665.rst [deleted file]
MAINTAINERS
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/ad7418.c
drivers/hwmon/ads7828.c
drivers/hwmon/adt7475.c
drivers/hwmon/as370-hwmon.c
drivers/hwmon/aspeed-pwm-tacho.c
drivers/hwmon/asus-ec-sensors.c
drivers/hwmon/bt1-pvt.c
drivers/hwmon/g762.c
drivers/hwmon/gxp-fan-ctrl.c
drivers/hwmon/hp-wmi-sensors.c
drivers/hwmon/hs3001.c [new file with mode: 0644]
drivers/hwmon/ina2xx.c
drivers/hwmon/it87.c
drivers/hwmon/lan966x-hwmon.c
drivers/hwmon/lm63.c
drivers/hwmon/lm75.c
drivers/hwmon/lm85.c
drivers/hwmon/lm90.c
drivers/hwmon/lochnagar-hwmon.c
drivers/hwmon/ltq-cputemp.c
drivers/hwmon/max31730.c
drivers/hwmon/max6621.c
drivers/hwmon/max6639.c
drivers/hwmon/max6697.c
drivers/hwmon/mcp3021.c
drivers/hwmon/mlxreg-fan.c
drivers/hwmon/nct6775-core.c
drivers/hwmon/nct6775-platform.c
drivers/hwmon/nct6775.h
drivers/hwmon/nsa320-hwmon.c
drivers/hwmon/oxp-sensors.c
drivers/hwmon/peci/dimmtemp.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/acbel-fsg032.c
drivers/hwmon/pmbus/dps920ab.c
drivers/hwmon/pmbus/ibm-cffps.c
drivers/hwmon/pmbus/ir38064.c
drivers/hwmon/pmbus/max20730.c
drivers/hwmon/pmbus/mp2975.c
drivers/hwmon/pmbus/mp5023.c
drivers/hwmon/pmbus/mpq7932.c
drivers/hwmon/pmbus/pli1209bc.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/pmbus/q54sj108a2.c
drivers/hwmon/pmbus/tps53679.c
drivers/hwmon/pmbus/ucd9000.c
drivers/hwmon/pmbus/ucd9200.c
drivers/hwmon/sbtsi_temp.c
drivers/hwmon/scpi-hwmon.c
drivers/hwmon/sht3x.c
drivers/hwmon/sis5595.c
drivers/hwmon/smm665.c [deleted file]
drivers/hwmon/tmp421.c
drivers/hwmon/tmp464.c
drivers/hwmon/tmp513.c
drivers/hwmon/tps23861.c
drivers/hwmon/ultra45_env.c
drivers/hwmon/vexpress-hwmon.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83773g.c

index ba2bfb5..40bc475 100644 (file)
@@ -119,6 +119,10 @@ properties:
           - fsl,mpr121
             # Monolithic Power Systems Inc. multi-phase controller mp2888
           - mps,mp2888
+            # Monolithic Power Systems Inc. multi-phase controller mp2971
+          - mps,mp2971
+            # Monolithic Power Systems Inc. multi-phase controller mp2973
+          - mps,mp2973
             # Monolithic Power Systems Inc. multi-phase controller mp2975
           - mps,mp2975
             # Honeywell Humidicon HIH-6130 humidity/temperature sensor
@@ -315,6 +319,8 @@ properties:
           - plx,pex8648
             # Pulsedlight LIDAR range-finding sensor
           - pulsedlight,lidar-lite-v2
+            # Renesas HS3001 Temperature and Relative Humidity Sensors
+          - renesas,hs3001
             # Renesas ISL29501 time-of-flight sensor
           - renesas,isl29501
             # Rohm DH2228FV
diff --git a/Documentation/hwmon/hs3001.rst b/Documentation/hwmon/hs3001.rst
new file mode 100644 (file)
index 0000000..9f59dfc
--- /dev/null
@@ -0,0 +1,37 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver HS3001
+====================
+
+Supported chips:
+
+  * Renesas HS3001, HS3002, HS3003, HS3004
+
+    Prefix: 'hs3001'
+
+    Addresses scanned: -
+
+    Datasheet: https://www.renesas.com/us/en/document/dst/hs300x-datasheet?r=417401
+
+Author:
+
+  - Andre Werner <andre.werner@systec-electronic.com>
+
+Description
+-----------
+
+This driver implements support for the Renesas HS3001 chips, a humidity
+and temperature family. Temperature is measured in degrees celsius, relative
+humidity is expressed as a percentage. In the sysfs interface, all values are
+scaled by 1000, i.e. the value for 31.5 degrees celsius is 31500.
+
+The device communicates with the I2C protocol. Sensors have the I2C
+address 0x44 by default.
+
+sysfs-Interface
+---------------
+
+=================== =================
+temp1_input:        temperature input
+humidity1_input:    humidity input
+=================== =================
index 042e1cf..88dadea 100644 (file)
@@ -78,6 +78,7 @@ Hardware Monitoring Kernel Drivers
    gxp-fan-ctrl
    hih6130
    hp-wmi-sensors
+   hs3001
    ibmaem
    ibm-cffps
    ibmpowernv
@@ -195,7 +196,6 @@ Hardware Monitoring Kernel Drivers
    shtc1
    sis5595
    sl28cpld
-   smm665
    smpro-hwmon
    smsc47b397
    smsc47m192
index 5ba8276..9d7a10d 100644 (file)
@@ -80,7 +80,13 @@ Supported chips:
 
     Datasheet: Available from Nuvoton upon request
 
+  * Nuvoton NCT6796D-S/NCT6799D-R
 
+    Prefix: 'nct6799'
+
+    Addresses scanned: ISA address retrieved from Super I/O registers
+
+    Datasheet: Available from Nuvoton upon request
 
 Authors:
 
@@ -277,4 +283,7 @@ will not reflect a usable value. It often reports unreasonably high
 temperatures, and in some cases the reported temperature declines if the actual
 temperature increases (similar to the raw PECI temperature value - see PECI
 specification for details). CPUTIN should therefore be ignored on ASUS
-boards. The CPU temperature on ASUS boards is reported from PECI 0.
+boards. The CPU temperature on ASUS boards is reported from PECI 0 or TSI 0.
+
+NCT6796D-S and NCT6799D-R chips are very similar and their chip_id indicates
+they are different versions. This driver treats them the same way.
index 7ecfec6..eb1569b 100644 (file)
@@ -163,7 +163,7 @@ Emerson DS1200 power modules might look as follows::
        .driver = {
                   .name = "ds1200",
                   },
-       .probe_new = ds1200_probe,
+       .probe = ds1200_probe,
        .id_table = ds1200_id,
   };
 
diff --git a/Documentation/hwmon/smm665.rst b/Documentation/hwmon/smm665.rst
deleted file mode 100644 (file)
index 481e69d..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-Kernel driver smm665
-====================
-
-Supported chips:
-
-  * Summit Microelectronics SMM465
-
-    Prefix: 'smm465'
-
-    Addresses scanned: -
-
-    Datasheet:
-
-      http://www.summitmicro.com/prod_select/summary/SMM465/SMM465DS.pdf
-
-  * Summit Microelectronics SMM665, SMM665B
-
-    Prefix: 'smm665'
-
-    Addresses scanned: -
-
-    Datasheet:
-
-      http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
-
-  * Summit Microelectronics SMM665C
-
-    Prefix: 'smm665c'
-
-    Addresses scanned: -
-
-    Datasheet:
-
-      http://www.summitmicro.com/prod_select/summary/SMM665C/SMM665C_2125.pdf
-
-  * Summit Microelectronics SMM764
-
-    Prefix: 'smm764'
-
-    Addresses scanned: -
-
-    Datasheet:
-
-      http://www.summitmicro.com/prod_select/summary/SMM764/SMM764_2098.pdf
-
-  * Summit Microelectronics SMM766, SMM766B
-
-    Prefix: 'smm766'
-
-    Addresses scanned: -
-
-    Datasheets:
-
-      http://www.summitmicro.com/prod_select/summary/SMM766/SMM766_2086.pdf
-
-      http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
-
-Author: Guenter Roeck <linux@roeck-us.net>
-
-
-Module Parameters
------------------
-
-* vref: int
-    Default: 1250 (mV)
-
-    Reference voltage on VREF_ADC pin in mV. It should not be necessary to set
-    this parameter unless a non-default reference voltage is used.
-
-
-Description
------------
-
-[From datasheet] The SMM665 is an Active DC Output power supply Controller
-that monitors, margins and cascade sequences power. The part monitors six
-power supply channels as well as VDD, 12V input, two general-purpose analog
-inputs and an internal temperature sensor using a 10-bit ADC.
-
-Each monitored channel has its own high and low limits, plus a critical
-limit.
-
-Support for SMM465, SMM764, and SMM766 has been implemented but is untested.
-
-
-Usage Notes
------------
-
-This driver does not probe for devices, since there is no register which
-can be safely used to identify the chip. You will have to instantiate
-the devices explicitly. When instantiating the device, you have to specify
-its configuration register address.
-
-Example: the following will load the driver for an SMM665 at address 0x57
-on I2C bus #1::
-
-       $ modprobe smm665
-       $ echo smm665 0x57 > /sys/bus/i2c/devices/i2c-1/new_device
-
-
-Sysfs entries
--------------
-
-This driver uses the values in the datasheet to convert ADC register values
-into the values specified in the sysfs-interface document. All attributes are
-read only.
-
-Min, max, lcrit, and crit values are used by the chip to trigger external signals
-and/or other activity. Triggered signals can include HEALTHY, RST, Power Off,
-or Fault depending on the chip configuration. The driver reports values as lcrit
-or crit if exceeding the limits triggers RST, Power Off, or Fault, and as min or
-max otherwise. For details please see the SMM665 datasheet.
-
-For SMM465 and SMM764, values for Channel E and F are reported but undefined.
-
-======================= =======================================================
-in1_input              12V input voltage (mV)
-in2_input              3.3V (VDD) input voltage (mV)
-in3_input              Channel A voltage (mV)
-in4_input              Channel B voltage (mV)
-in5_input              Channel C voltage (mV)
-in6_input              Channel D voltage (mV)
-in7_input              Channel E voltage (mV)
-in8_input              Channel F voltage (mV)
-in9_input              AIN1 voltage (mV)
-in10_input             AIN2 voltage (mV)
-
-in1_min                        12v input minimum voltage (mV)
-in2_min                        3.3V (VDD) input minimum voltage (mV)
-in3_min                        Channel A minimum voltage (mV)
-in4_min                        Channel B minimum voltage (mV)
-in5_min                        Channel C minimum voltage (mV)
-in6_min                        Channel D minimum voltage (mV)
-in7_min                        Channel E minimum voltage (mV)
-in8_min                        Channel F minimum voltage (mV)
-in9_min                        AIN1 minimum voltage (mV)
-in10_min               AIN2 minimum voltage (mV)
-
-in1_max                        12v input maximum voltage (mV)
-in2_max                        3.3V (VDD) input maximum voltage (mV)
-in3_max                        Channel A maximum voltage (mV)
-in4_max                        Channel B maximum voltage (mV)
-in5_max                        Channel C maximum voltage (mV)
-in6_max                        Channel D maximum voltage (mV)
-in7_max                        Channel E maximum voltage (mV)
-in8_max                        Channel F maximum voltage (mV)
-in9_max                        AIN1 maximum voltage (mV)
-in10_max               AIN2 maximum voltage (mV)
-
-in1_lcrit              12v input critical minimum voltage (mV)
-in2_lcrit              3.3V (VDD) input critical minimum voltage (mV)
-in3_lcrit              Channel A critical minimum voltage (mV)
-in4_lcrit              Channel B critical minimum voltage (mV)
-in5_lcrit              Channel C critical minimum voltage (mV)
-in6_lcrit              Channel D critical minimum voltage (mV)
-in7_lcrit              Channel E critical minimum voltage (mV)
-in8_lcrit              Channel F critical minimum voltage (mV)
-in9_lcrit              AIN1 critical minimum voltage (mV)
-in10_lcrit             AIN2 critical minimum voltage (mV)
-
-in1_crit               12v input critical maximum voltage (mV)
-in2_crit               3.3V (VDD) input critical maximum voltage (mV)
-in3_crit               Channel A critical maximum voltage (mV)
-in4_crit               Channel B critical maximum voltage (mV)
-in5_crit               Channel C critical maximum voltage (mV)
-in6_crit               Channel D critical maximum voltage (mV)
-in7_crit               Channel E critical maximum voltage (mV)
-in8_crit               Channel F critical maximum voltage (mV)
-in9_crit               AIN1 critical maximum voltage (mV)
-in10_crit              AIN2 critical maximum voltage (mV)
-
-in1_crit_alarm         12v input critical alarm
-in2_crit_alarm         3.3V (VDD) input critical alarm
-in3_crit_alarm         Channel A critical alarm
-in4_crit_alarm         Channel B critical alarm
-in5_crit_alarm         Channel C critical alarm
-in6_crit_alarm         Channel D critical alarm
-in7_crit_alarm         Channel E critical alarm
-in8_crit_alarm         Channel F critical alarm
-in9_crit_alarm         AIN1 critical alarm
-in10_crit_alarm                AIN2 critical alarm
-
-temp1_input            Chip temperature
-temp1_min              Minimum chip temperature
-temp1_max              Maximum chip temperature
-temp1_crit             Critical chip temperature
-temp1_crit_alarm       Temperature critical alarm
-======================= =======================================================
index abfbd80..657bd6c 100644 (file)
@@ -9509,6 +9509,12 @@ S:       Maintained
 W:     http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 F:     fs/hpfs/
 
+HS3001 Hardware Temperature and Humidity Sensor
+M:     Andre Werner <andre.werner@systec-electronic.com>
+L:     linux-hwmon@vger.kernel.org
+S:     Maintained
+F:     drivers/hwmon/hs3001.c
+
 HSI SUBSYSTEM
 M:     Sebastian Reichel <sre@kernel.org>
 S:     Maintained
@@ -19625,13 +19631,6 @@ M:     Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
 F:     drivers/net/ethernet/smsc/smc91x.*
 
-SMM665 HARDWARE MONITOR DRIVER
-M:     Guenter Roeck <linux@roeck-us.net>
-L:     linux-hwmon@vger.kernel.org
-S:     Maintained
-F:     Documentation/hwmon/smm665.rst
-F:     drivers/hwmon/smm665.c
-
 SMSC EMC2103 HARDWARE MONITOR DRIVER
 M:     Steve Glendinning <steve.glendinning@shawell.net>
 L:     linux-hwmon@vger.kernel.org
index 307477b..ec38c88 100644 (file)
@@ -734,6 +734,16 @@ config SENSORS_HIH6130
          This driver can also be built as a module. If so, the module
          will be called hih6130.
 
+config SENSORS_HS3001
+       tristate "Renesas HS3001 humidity and temperature sensors"
+       depends on I2C
+       help
+         If you say yes here you get support for the Renesas HS3001,
+         to HS3004 humidity and temperature sensors.
+
+         This driver can also be built as a module. If so, the module
+         will be called hs3001.
+
 config SENSORS_IBMAEM
        tristate "IBM Active Energy Manager temperature/power sensors and control"
        select IPMI_SI
@@ -1951,20 +1961,6 @@ config SENSORS_SFCTEMP
          This driver can also be built as a module.  If so, the module
          will be called sfctemp.
 
-config SENSORS_SMM665
-       tristate "Summit Microelectronics SMM665"
-       depends on I2C
-       help
-         If you say yes here you get support for the hardware monitoring
-         features of the Summit Microelectronics SMM665/SMM665B Six-Channel
-         Active DC Output Controller / Monitor.
-
-         Other supported chips are SMM465, SMM665C, SMM764, and SMM766.
-         Support for those chips is untested.
-
-         This driver can also be built as a module. If so, the module will
-         be called smm665.
-
 config SENSORS_ADC128D818
        tristate "Texas Instruments ADC128D818"
        depends on I2C
index 3f4b0fd..4ac9452 100644 (file)
@@ -86,6 +86,7 @@ obj-$(CONFIG_SENSORS_GSC)     += gsc-hwmon.o
 obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
 obj-$(CONFIG_SENSORS_GXP_FAN_CTRL) += gxp-fan-ctrl.o
 obj-$(CONFIG_SENSORS_HIH6130)  += hih6130.o
+obj-$(CONFIG_SENSORS_HS3001)   += hs3001.o
 obj-$(CONFIG_SENSORS_ULTRA45)  += ultra45_env.o
 obj-$(CONFIG_SENSORS_I5500)    += i5500_temp.o
 obj-$(CONFIG_SENSORS_I5K_AMB)  += i5k_amb.o
@@ -191,7 +192,6 @@ obj-$(CONFIG_SENSORS_SHT3x) += sht3x.o
 obj-$(CONFIG_SENSORS_SHT4x)    += sht4x.o
 obj-$(CONFIG_SENSORS_SHTC1)    += shtc1.o
 obj-$(CONFIG_SENSORS_SIS5595)  += sis5595.o
-obj-$(CONFIG_SENSORS_SMM665)   += smm665.o
 obj-$(CONFIG_SENSORS_SMPRO)    += smpro-hwmon.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
index ffe81e4..4829f83 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 
@@ -253,7 +253,7 @@ static int ad7418_probe(struct i2c_client *client)
        mutex_init(&data->lock);
        data->client = client;
        if (dev->of_node)
-               data->type = (enum chips)of_device_get_match_data(dev);
+               data->type = (uintptr_t)of_device_get_match_data(dev);
        else
                data->type = i2c_match_id(ad7418_id, client)->driver_data;
 
index 1932613..809e830 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/platform_data/ads7828.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
@@ -139,8 +139,7 @@ static int ads7828_probe(struct i2c_client *client)
        }
 
        if (client->dev.of_node)
-               chip = (enum ads7828_chips)
-                       of_device_get_match_data(&client->dev);
+               chip = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                chip = i2c_match_id(ads7828_device_ids, client)->driver_data;
 
index c0ce883..03acadc 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/of_device.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -1653,7 +1652,7 @@ static int adt7475_probe(struct i2c_client *client)
        i2c_set_clientdata(client, data);
 
        if (client->dev.of_node)
-               chip = (enum chips)of_device_get_match_data(&client->dev);
+               chip = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                chip = id->driver_data;
 
index fffbf38..316454b 100644 (file)
@@ -11,7 +11,8 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
 
 #define CTRL           0x0
 #define  PD            BIT(0)
index d11f674..997df4b 100644 (file)
@@ -12,8 +12,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
index f52a539..51f9c2d 100644 (file)
@@ -340,7 +340,7 @@ static const struct ec_board_info board_info_crosshair_x670e_hero = {
        .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
                SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
                SENSOR_SET_TEMP_WATER,
-       .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
+       .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
        .family = family_amd_600_series,
 };
 
index 8d402a6..b77ebac 100644 (file)
@@ -891,15 +891,8 @@ static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev)
 static int pvt_request_regs(struct pvt_hwmon *pvt)
 {
        struct platform_device *pdev = to_platform_device(pvt->dev);
-       struct resource *res;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(pvt->dev, "Couldn't find PVT memresource\n");
-               return -EINVAL;
-       }
-
-       pvt->regs = devm_ioremap_resource(pvt->dev, res);
+       pvt->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(pvt->regs))
                return PTR_ERR(pvt->regs);
 
index 1b6ff47..fad69ef 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_data/g762.h>
 
 #define DRVNAME "g762"
index 2e05bc2..00e0570 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/hwmon.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
 #include <linux/platform_device.h>
 
 #define OFS_FAN_INST   0 /* Is 0 because plreg base will be set at INST */
index ebe2fb5..17ae62f 100644 (file)
@@ -435,25 +435,11 @@ static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance)
 /* hp_wmi_wobj_instance_count - find count of WMI object instances */
 static u8 hp_wmi_wobj_instance_count(const char *guid)
 {
-       u8 hi = HP_WMI_MAX_INSTANCES;
-       union acpi_object *wobj;
-       u8 lo = 0;
-       u8 mid;
-
-       while (lo < hi) {
-               mid = (lo + hi) / 2;
+       int count;
 
-               wobj = hp_wmi_get_wobj(guid, mid);
-               if (!wobj) {
-                       hi = mid;
-                       continue;
-               }
+       count = wmi_instance_count(guid);
 
-               lo = mid + 1;
-               kfree(wobj);
-       }
-
-       return lo;
+       return clamp(count, 0, (int)HP_WMI_MAX_INSTANCES);
 }
 
 static int check_wobj(const union acpi_object *wobj,
@@ -1927,7 +1913,7 @@ static bool add_event_handler(struct hp_wmi_sensors *state)
 static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
 {
        struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
-       struct hp_wmi_platform_events *pevents;
+       struct hp_wmi_platform_events *pevents = NULL;
        struct device *dev = &state->wdev->dev;
        struct hp_wmi_info *info;
        struct device *hwdev;
diff --git a/drivers/hwmon/hs3001.c b/drivers/hwmon/hs3001.c
new file mode 100644 (file)
index 0000000..ac574e4
--- /dev/null
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * This is a non-complete driver implementation for the
+ * HS3001 humidity and temperature sensor and compatibles. It does not include
+ * the configuration possibilities, where it needs to be set to 'programming mode'
+ * during power-up.
+ *
+ *
+ * Copyright (C) 2023 SYS TEC electronic AG
+ * Author: Andre Werner <andre.werner@systec-electronic.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* Measurement times */
+#define HS3001_WAKEUP_TIME     100     /* us */
+#define HS3001_8BIT_RESOLUTION 550     /* us */
+#define HS3001_10BIT_RESOLUTION        1310    /* us */
+#define HS3001_12BIT_RESOLUTION        4500    /* us */
+#define HS3001_14BIT_RESOLUTION        16900   /* us */
+
+#define HS3001_RESPONSE_LENGTH 4
+
+#define HS3001_FIXPOINT_ARITH  1000U
+
+#define HS3001_MASK_HUMIDITY_0X3FFF    GENMASK(13, 0)
+#define HS3001_MASK_STATUS_0XC0        GENMASK(7, 6)
+
+/* Definitions for Status Bits of A/D Data */
+#define HS3001_DATA_VALID      0x00    /* Valid Data */
+#define HS3001_DATA_STALE      0x01    /* Stale Data */
+
+struct hs3001_data {
+       struct i2c_client *client;
+       struct mutex i2c_lock; /* lock for sending i2c commands */
+       u32 wait_time;          /* in us */
+       int temperature;        /* in milli degree */
+       u32 humidity;           /* in milli % */
+};
+
+static int hs3001_extract_temperature(u16 raw)
+{
+       /* fixpoint arithmetic 1 digit */
+       u32 temp = (raw >> 2) * HS3001_FIXPOINT_ARITH * 165;
+
+       temp /= (1 << 14) - 1;
+
+       return (int)temp - 40 * HS3001_FIXPOINT_ARITH;
+}
+
+static u32 hs3001_extract_humidity(u16 raw)
+{
+       u32 hum = (raw & HS3001_MASK_HUMIDITY_0X3FFF) * HS3001_FIXPOINT_ARITH * 100;
+
+       return hum /= (1 << 14) - 1;
+}
+
+static int hs3001_data_fetch_command(struct i2c_client *client,
+                                    struct hs3001_data *data)
+{
+       int ret;
+       u8 buf[HS3001_RESPONSE_LENGTH];
+       u8 hs3001_status;
+
+       ret = i2c_master_recv(client, buf, HS3001_RESPONSE_LENGTH);
+       if (ret != HS3001_RESPONSE_LENGTH) {
+               ret = ret < 0 ? ret : -EIO;
+               dev_dbg(&client->dev,
+                       "Error in i2c communication. Error code: %d.\n", ret);
+               return ret;
+       }
+
+       hs3001_status = FIELD_GET(HS3001_MASK_STATUS_0XC0, buf[0]);
+       if (hs3001_status == HS3001_DATA_STALE) {
+               dev_dbg(&client->dev, "Sensor busy.\n");
+               return -EBUSY;
+       }
+       if (hs3001_status != HS3001_DATA_VALID) {
+               dev_dbg(&client->dev, "Data invalid.\n");
+               return -EIO;
+       }
+
+       data->humidity =
+               hs3001_extract_humidity(be16_to_cpup((__be16 *)&buf[0]));
+       data->temperature =
+               hs3001_extract_temperature(be16_to_cpup((__be16 *)&buf[2]));
+
+       return 0;
+}
+
+static umode_t hs3001_is_visible(const void *data, enum hwmon_sensor_types type,
+                                u32 attr, int channel)
+{
+       /* Both, humidity and temperature can only be read. */
+       return 0444;
+}
+
+static int hs3001_read(struct device *dev, enum hwmon_sensor_types type,
+                      u32 attr, int channel, long *val)
+{
+       struct hs3001_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+       int ret;
+
+       mutex_lock(&data->i2c_lock);
+       ret = i2c_master_send(client, NULL, 0);
+       if (ret < 0) {
+               mutex_unlock(&data->i2c_lock);
+               return ret;
+       }
+
+       /*
+        * Sensor needs some time to process measurement depending on
+        * resolution (ref. datasheet)
+        */
+       fsleep(data->wait_time);
+
+       ret = hs3001_data_fetch_command(client, data);
+       mutex_unlock(&data->i2c_lock);
+
+       if (ret < 0)
+               return ret;
+
+       switch (type) {
+       case hwmon_temp:
+               switch (attr) {
+               case hwmon_temp_input:
+                       *val = data->temperature;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case hwmon_humidity:
+               switch (attr) {
+               case hwmon_humidity_input:
+                       *val = data->humidity;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct hwmon_channel_info *hs3001_info[] = {
+       HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+       HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT),
+       NULL
+};
+
+static const struct hwmon_ops hs3001_hwmon_ops = {
+       .is_visible = hs3001_is_visible,
+       .read = hs3001_read,
+};
+
+static const struct hwmon_chip_info hs3001_chip_info = {
+       .ops = &hs3001_hwmon_ops,
+       .info = hs3001_info,
+};
+
+/* device ID table */
+static const struct i2c_device_id hs3001_ids[] = {
+       { "hs3001", 0 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(i2c, hs3001_ids);
+
+static const struct of_device_id hs3001_of_match[] = {
+       {.compatible = "renesas,hs3001"},
+       { },
+};
+
+MODULE_DEVICE_TABLE(of, hs3001_of_match);
+
+static int hs3001_probe(struct i2c_client *client)
+{
+       struct hs3001_data *data;
+       struct device *hwmon_dev;
+       struct device *dev = &client->dev;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -EOPNOTSUPP;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->client = client;
+
+       /*
+        * Measurement time = wake-up time + measurement time temperature
+        * + measurement time humidity. This is currently static, because
+        * enabling programming mode is not supported, yet.
+        */
+       data->wait_time = (HS3001_WAKEUP_TIME + HS3001_14BIT_RESOLUTION +
+                          HS3001_14BIT_RESOLUTION);
+
+       mutex_init(&data->i2c_lock);
+
+       hwmon_dev = devm_hwmon_device_register_with_info(dev,
+                                                        client->name,
+                                                        data,
+                                                        &hs3001_chip_info,
+                                                        NULL);
+
+       if (IS_ERR(hwmon_dev))
+               return dev_err_probe(dev, PTR_ERR(hwmon_dev),
+                                    "Unable to register hwmon device.\n");
+
+       return 0;
+}
+
+static struct i2c_driver hs3001_i2c_driver = {
+       .driver = {
+                  .name = "hs3001",
+                  .of_match_table = hs3001_of_match,
+       },
+       .probe = hs3001_probe,
+       .id_table = hs3001_ids,
+};
+
+module_i2c_driver(hs3001_i2c_driver);
+
+MODULE_AUTHOR("Andre Werner <andre.werner@systec-electronic.com>");
+MODULE_DESCRIPTION("HS3001 humidity and temperature sensor base driver");
+MODULE_LICENSE("GPL");
index cfd7efe..d8415d1 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/jiffies.h>
-#include <linux/of_device.h>
 #include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/util_macros.h>
@@ -625,7 +624,7 @@ static int ina2xx_probe(struct i2c_client *client)
        enum ina2xx_ids chip;
 
        if (client->dev.of_node)
-               chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
+               chip = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                chip = i2c_match_id(ina2xx_id, client)->driver_data;
 
index 5deff5e..fbe86ce 100644 (file)
@@ -221,6 +221,10 @@ static bool fix_pwm_polarity;
  * Super-I/O configuration space.
  */
 #define IT87_REG_VID           0x0a
+
+/* Interface Selection register on other chips */
+#define IT87_REG_IFSEL         0x0a
+
 /*
  * The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
  * for fan divisors. Later IT8712F revisions must use 16-bit tachometer
@@ -1159,28 +1163,66 @@ static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0);
 static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0);
 static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0);
 
+static int get_temp_type(struct it87_data *data, int index)
+{
+       /*
+        * 2 is deprecated;
+        * 3 = thermal diode;
+        * 4 = thermistor;
+        * 5 = AMDTSI;
+        * 6 = Intel PECI;
+        * 0 = disabled
+        */
+       u8 reg, extra;
+       int ttype, type = 0;
+
+       /* Detect PECI vs. AMDTSI */
+       ttype = 6;
+       if ((has_temp_peci(data, index)) || data->type == it8721 ||
+           data->type == it8720) {
+               extra = it87_read_value(data, IT87_REG_IFSEL);
+               if ((extra & 0x70) == 0x40)
+                       ttype = 5;
+       }
+
+       reg = it87_read_value(data, IT87_REG_TEMP_ENABLE);
+
+       /* Per chip special detection */
+       switch (data->type) {
+       case it8622:
+               if (!(reg & 0xc0) && index == 3)
+                       type = ttype;
+               break;
+       default:
+               break;
+       }
+
+       if (type || index >= 3)
+               return type;
+
+       extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
+
+       if ((has_temp_peci(data, index) && (reg >> 6 == index + 1)) ||
+           (has_temp_old_peci(data, index) && (extra & 0x80)))
+               type = ttype;   /* Intel PECI or AMDTSI */
+       else if (reg & BIT(index))
+               type = 3;       /* thermal diode */
+       else if (reg & BIT(index + 3))
+               type = 4;       /* thermistor */
+
+       return type;
+}
+
 static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
                              char *buf)
 {
        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-       int nr = sensor_attr->index;
        struct it87_data *data = it87_update_device(dev);
-       u8 reg, extra;
 
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       reg = data->sensor;     /* In case value is updated while used */
-       extra = data->extra;
-
-       if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) ||
-           (has_temp_old_peci(data, nr) && (extra & 0x80)))
-               return sprintf(buf, "6\n");  /* Intel PECI */
-       if (reg & (1 << nr))
-               return sprintf(buf, "3\n");  /* thermal diode */
-       if (reg & (8 << nr))
-               return sprintf(buf, "4\n");  /* thermistor */
-       return sprintf(buf, "0\n");      /* disabled */
+       return sprintf(buf, "%d\n", get_temp_type(data, sensor_attr->index));
 }
 
 static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr,
@@ -2313,6 +2355,12 @@ static umode_t it87_temp_is_visible(struct kobject *kobj,
        if (!(data->has_temp & BIT(i)))
                return 0;
 
+       if (a == 3) {
+               if (get_temp_type(data, i) == 0)
+                       return 0;
+               return attr->mode;
+       }
+
        if (a == 5 && !has_temp_offset(data))
                return 0;
 
index f865835..7247c03 100644 (file)
@@ -334,24 +334,6 @@ static struct regmap *lan966x_init_regmap(struct platform_device *pdev,
        return devm_regmap_init_mmio(&pdev->dev, base, &regmap_config);
 }
 
-static void lan966x_clk_disable(void *data)
-{
-       struct lan966x_hwmon *hwmon = data;
-
-       clk_disable_unprepare(hwmon->clk);
-}
-
-static int lan966x_clk_enable(struct device *dev, struct lan966x_hwmon *hwmon)
-{
-       int ret;
-
-       ret = clk_prepare_enable(hwmon->clk);
-       if (ret)
-               return ret;
-
-       return devm_add_action_or_reset(dev, lan966x_clk_disable, hwmon);
-}
-
 static int lan966x_hwmon_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -363,15 +345,11 @@ static int lan966x_hwmon_probe(struct platform_device *pdev)
        if (!hwmon)
                return -ENOMEM;
 
-       hwmon->clk = devm_clk_get(dev, NULL);
+       hwmon->clk = devm_clk_get_enabled(dev, NULL);
        if (IS_ERR(hwmon->clk))
                return dev_err_probe(dev, PTR_ERR(hwmon->clk),
                                     "failed to get clock\n");
 
-       ret = lan966x_clk_enable(dev, hwmon);
-       if (ret)
-               return dev_err_probe(dev, ret, "failed to enable clock\n");
-
        hwmon->clk_rate = clk_get_rate(hwmon->clk);
 
        hwmon->regmap_pvt = lan966x_init_regmap(pdev, "pvt");
index 6972454..0878a04 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/sysfs.h>
 #include <linux/types.h>
 
@@ -1105,7 +1105,7 @@ static int lm63_probe(struct i2c_client *client)
 
        /* Set the device type */
        if (client->dev.of_node)
-               data->kind = (enum chips)of_device_get_match_data(&client->dev);
+               data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                data->kind = i2c_match_id(lm63_id, client)->driver_data;
        if (data->kind == lm64)
index 72e634d..5b2ea05 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
-#include <linux/of_device.h>
 #include <linux/of.h>
 #include <linux/regmap.h>
 #include <linux/util_macros.h>
@@ -579,7 +578,7 @@ static int lm75_probe(struct i2c_client *client)
        enum lm75_type kind;
 
        if (client->dev.of_node)
-               kind = (enum lm75_type)of_device_get_match_data(&client->dev);
+               kind = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                kind = i2c_match_id(lm75_ids, client)->driver_data;
 
index 8540178..68c2100 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -1559,7 +1559,7 @@ static int lm85_probe(struct i2c_client *client)
 
        data->client = client;
        if (client->dev.of_node)
-               data->type = (enum chips)of_device_get_match_data(&client->dev);
+               data->type = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                data->type = i2c_match_id(lm85_id, client)->driver_data;
        mutex_init(&data->update_lock);
index 90101c2..e0d7454 100644 (file)
 #include <linux/kstrtox.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -2765,7 +2765,7 @@ static int lm90_probe(struct i2c_client *client)
 
        /* Set the device type */
        if (client->dev.of_node)
-               data->kind = (enum chips)of_device_get_match_data(&client->dev);
+               data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                data->kind = i2c_match_id(lm90_id, client)->driver_data;
 
index 6350904..5202ddd 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/mfd/lochnagar2_regs.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 
index 08e09a8..f7e4a4c 100644 (file)
@@ -9,8 +9,9 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/init.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
 
 #include <lantiq_soc.h>
 
index b1300ca..7d237db 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/hwmon.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
 #include <linux/of.h>
 #include <linux/slab.h>
 
index 7f709fd..af7e626 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 
 #define MAX6621_DRV_NAME               "max6621"
index caf5271..aa7f21a 100644 (file)
@@ -618,11 +618,17 @@ MODULE_DEVICE_TABLE(i2c, max6639_id);
 
 static DEFINE_SIMPLE_DEV_PM_OPS(max6639_pm_ops, max6639_suspend, max6639_resume);
 
+static const struct of_device_id max6639_of_match[] = {
+       { .compatible = "maxim,max6639", },
+       { },
+};
+
 static struct i2c_driver max6639_driver = {
        .class = I2C_CLASS_HWMON,
        .driver = {
                   .name = "max6639",
                   .pm = pm_sleep_ptr(&max6639_pm_ops),
+                  .of_match_table = max6639_of_match,
                   },
        .probe = max6639_probe,
        .id_table = max6639_id,
index 3a67778..7d10dd4 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
 #include <linux/of.h>
 
 #include <linux/platform_data/max6697.h>
@@ -703,7 +702,7 @@ static int max6697_probe(struct i2c_client *client)
                return -ENOMEM;
 
        if (client->dev.of_node)
-               data->type = (enum chips)of_device_get_match_data(&client->dev);
+               data->type = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                data->type = i2c_match_id(max6697_id, client)->driver_data;
        data->chip = &max6697_chip_data[data->type];
index 127e15f..9814eaf 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 
 /* Vdd / reference voltage in millivolt */
 #define MCP3021_VDD_REF_MAX    5500
index c2a9646..a5f89aa 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/regmap.h>
 #include <linux/thermal.h>
 
-#define MLXREG_FAN_MAX_TACHO           14
+#define MLXREG_FAN_MAX_TACHO           24
 #define MLXREG_FAN_MAX_PWM             4
 #define MLXREG_FAN_PWM_NOT_CONNECTED   0xff
 #define MLXREG_FAN_MAX_STATE           10
@@ -300,6 +300,16 @@ static const struct hwmon_channel_info * const mlxreg_fan_hwmon_info[] = {
                           HWMON_F_INPUT | HWMON_F_FAULT,
                           HWMON_F_INPUT | HWMON_F_FAULT,
                           HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
+                          HWMON_F_INPUT | HWMON_F_FAULT,
                           HWMON_F_INPUT | HWMON_F_FAULT),
        HWMON_CHANNEL_INFO(pwm,
                           HWMON_PWM_INPUT,
index 08ce498..02a7124 100644 (file)
@@ -33,7 +33,8 @@
  *                                           (0xd451)
  * nct6798d    14      7       7       2+6    0xd428 0xc1    0x5ca3
  *                                           (0xd429)
- * nct6799d    14      7       7       2+6    0xd802 0xc1    0x5ca3
+ * nct6796d-s  18      7       7       6+2    0xd801 0xc1    0x5ca3
+ * nct6799d-r  18      7       7       6+2    0xd802 0xc1    0x5ca3
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -79,14 +80,17 @@ static const char * const nct6775_device_names[] = {
 
 /* Common and NCT6775 specific data */
 
-/* Voltage min/max registers for nr=7..14 are in bank 5 */
+/*
+ * Voltage min/max registers for nr=7..14 are in bank 5
+ * min/max: 15-17 for NCT6799 only
+ */
 
 static const u16 NCT6775_REG_IN_MAX[] = {
        0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
-       0x55c, 0x55e, 0x560, 0x562 };
+       0x55c, 0x55e, 0x560, 0x562, 0x564, 0x570, 0x572 };
 static const u16 NCT6775_REG_IN_MIN[] = {
        0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
-       0x55d, 0x55f, 0x561, 0x563 };
+       0x55d, 0x55f, 0x561, 0x563, 0x565, 0x571, 0x573 };
 static const u16 NCT6775_REG_IN[] = {
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
 };
@@ -97,31 +101,23 @@ static const u16 NCT6775_REG_IN[] = {
 
 static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
 
-/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
-
-static const s8 NCT6775_ALARM_BITS[] = {
-       0, 1, 2, 3, 8, 21, 20, 16,      /* in0.. in7 */
-       17, -1, -1, -1, -1, -1, -1,     /* in8..in14 */
-       -1,                             /* unused */
-       6, 7, 11, -1, -1,               /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
-       12, -1 };                       /* intrusion0, intrusion1 */
+static const s8 NCT6775_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  8, 21, 20, 16, 17, -1, -1, -1,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+        6,  7, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+        4,  5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       12, -1,                                           /* intr0-intr1  */
+};
 
 static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
 
-/*
- * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
- * 30..31 intrusion
- */
-static const s8 NCT6775_BEEP_BITS[] = {
-       0, 1, 2, 3, 8, 9, 10, 16,       /* in0.. in7 */
-       17, -1, -1, -1, -1, -1, -1,     /* in8..in14 */
-       21,                             /* global beep enable */
-       6, 7, 11, 28, -1,               /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
-       12, -1 };                       /* intrusion0, intrusion1 */
+static const s8 NCT6775_BEEP_BITS[NUM_BEEP_BITS] = {
+        0,  1,  2,  3,  8,  9, 10, 16, 17, -1, -1, -1,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+        6,  7, 11, 28, -1, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+        4,  5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       12, -1, 21                                        /* intr0-intr1, beep_en */
+};
 
 /* DC or PWM output fan configuration */
 static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
@@ -255,25 +251,24 @@ static const u16 NCT6775_REG_TSI_TEMP[] = { 0x669 };
 #define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME
 #define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME
 
-static const s8 NCT6776_ALARM_BITS[] = {
-       0, 1, 2, 3, 8, 21, 20, 16,      /* in0.. in7 */
-       17, -1, -1, -1, -1, -1, -1,     /* in8..in14 */
-       -1,                             /* unused */
-       6, 7, 11, 10, 23,               /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
-       12, 9 };                        /* intrusion0, intrusion1 */
-
-static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
-
-static const s8 NCT6776_BEEP_BITS[] = {
-       0, 1, 2, 3, 4, 5, 6, 7,         /* in0.. in7 */
-       8, -1, -1, -1, -1, -1, -1,      /* in8..in14 */
-       24,                             /* global beep enable */
-       25, 26, 27, 28, 29,             /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       16, 17, 18, 19, 20, 21,         /* temp1..temp6 */
-       30, 31 };                       /* intrusion0, intrusion1 */
+static const s8 NCT6776_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  8, 21, 20, 16, 17, -1, -1, -1,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+        6,  7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+        4,  5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       12,  9,                                           /* intr0-intr1  */
+};
+
+/* 0xbf: nct6799 only */
+static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
+
+static const s8 NCT6776_BEEP_BITS[NUM_BEEP_BITS] = {
+        0,  1,  2,  3,  4,  5,  6,  7,  8, -1, -1, -1,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       30, 31, 24                                        /* intr0-intr1, beep_en */
+};
 
 static const u16 NCT6776_REG_TOLERANCE_H[] = {
        0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
@@ -337,30 +332,35 @@ static const u16 NCT6776_REG_TSI_TEMP[] = {
 
 /* NCT6779 specific data */
 
+/*
+ * 15-17 for NCT6799 only, register labels are:
+ *      CPUVC,  VIN1,  AVSB,  3VCC,  VIN0,  VIN8,  VIN4, 3VSB
+ *       VBAT,   VTT,  VIN5,  VIN6,  VIN2,  VIN3,  VIN7, VIN9
+ *       VHIF, VIN10
+ */
 static const u16 NCT6779_REG_IN[] = {
        0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
-       0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
+       0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e, 0x48f,
+       0x470, 0x471};
 
 static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
        0x459, 0x45A, 0x45B, 0x568 };
 
-static const s8 NCT6779_ALARM_BITS[] = {
-       0, 1, 2, 3, 8, 21, 20, 16,      /* in0.. in7 */
-       17, 24, 25, 26, 27, 28, 29,     /* in8..in14 */
-       -1,                             /* unused */
-       6, 7, 11, 10, 23,               /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
-       12, 9 };                        /* intrusion0, intrusion1 */
-
-static const s8 NCT6779_BEEP_BITS[] = {
-       0, 1, 2, 3, 4, 5, 6, 7,         /* in0.. in7 */
-       8, 9, 10, 11, 12, 13, 14,       /* in8..in14 */
-       24,                             /* global beep enable */
-       25, 26, 27, 28, 29,             /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       16, 17, -1, -1, -1, -1,         /* temp1..temp6 */
-       30, 31 };                       /* intrusion0, intrusion1 */
+static const s8 NCT6779_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  8, 21, 20, 16, 17, 24, 25, 26,   /* in0-in11     */
+       27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+        6,  7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+        4,  5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       12,  9,                                           /* intr0-intr1  */
+};
+
+static const s8 NCT6779_BEEP_BITS[NUM_BEEP_BITS] = {
+        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,   /* in0-in11     */
+       12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       30, 31, 24                                        /* intr0-intr1, beep_en */
+};
 
 static const u16 NCT6779_REG_FAN[] = {
        0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce };
@@ -448,14 +448,13 @@ static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e };
 static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
        0x459, 0x45A, 0x45B, 0x568, 0x45D };
 
-static const s8 NCT6791_ALARM_BITS[] = {
-       0, 1, 2, 3, 8, 21, 20, 16,      /* in0.. in7 */
-       17, 24, 25, 26, 27, 28, 29,     /* in8..in14 */
-       -1,                             /* unused */
-       6, 7, 11, 10, 23, 33,           /* fan1..fan6 */
-       -1, -1,                         /* unused */
-       4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
-       12, 9 };                        /* intrusion0, intrusion1 */
+static const s8 NCT6791_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  8, 21, 20, 16, 17, 24, 25, 26,   /* in0-in11     */
+       27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+        6,  7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+        4,  5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       12,  9,                                           /* intr0-intr1  */
+};
 
 /* NCT6792/NCT6793 specific data */
 
@@ -618,6 +617,28 @@ static const char *const nct6796_temp_label[] = {
 
 static const u16 NCT6796_REG_TSI_TEMP[] = { 0x409, 0x40b };
 
+static const u16 NCT6798_REG_TEMP[] = {
+       0x27, 0x150, 0x670, 0x672, 0x674, 0x676, 0x678, 0x67a};
+
+static const u16 NCT6798_REG_TEMP_SOURCE[] = {
+       0x621, 0x622, 0xc26, 0xc27, 0xc28, 0xc29, 0xc2a, 0xc2b };
+
+static const u16 NCT6798_REG_TEMP_MON[] = {
+       0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, 0x4a0 };
+static const u16 NCT6798_REG_TEMP_OVER[] = {
+       0x39, 0x155, 0xc1a, 0xc1b, 0xc1c, 0xc1d, 0xc1e, 0xc1f };
+static const u16 NCT6798_REG_TEMP_HYST[] = {
+       0x3a, 0x153, 0xc20, 0xc21, 0xc22, 0xc23, 0xc24, 0xc25 };
+
+static const u16 NCT6798_REG_TEMP_CRIT[32] = {
+       0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35, 0 };
+
+static const u16 NCT6798_REG_TEMP_ALTERNATE[32] = {
+       0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0x496, 0,
+       0, 0, 0, 0, 0x4a2, 0, 0, 0,
+       0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
+       0x408, 0x419, 0x41a, 0x4f4, 0x4f5 };
+
 static const char *const nct6798_temp_label[] = {
        "",
        "SYSTIN",
@@ -656,6 +677,26 @@ static const char *const nct6798_temp_label[] = {
 #define NCT6798_TEMP_MASK      0xbfff0ffe
 #define NCT6798_VIRT_TEMP_MASK 0x80000c00
 
+static const u16 NCT6799_REG_ALARM[NUM_REG_ALARM] = {
+       0x459, 0x45A, 0x45B, 0x568, 0x45D, 0xc01 };
+
+static const s8 NCT6799_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  8, -1, 20, 16, 17, 24, 25, 26,   /* in0-in11     */
+       27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+        6,  7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+        4,  5, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       12,  9,                                           /* intr0-intr1  */
+};
+
+static const s8 NCT6799_BEEP_BITS[NUM_BEEP_BITS] = {
+        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,   /* in0-in11     */
+       12, 13, 14, 15, 34, 35, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1,   /* temp1-temp12 */
+       30, 31, 24                                        /* intr0-intr1, beep_en */
+};
+
+/* PECI Calibration only for NCT6799D, not NCT6796D-S */
 static const char *const nct6799_temp_label[] = {
        "",
        "SYSTIN",
@@ -685,8 +726,8 @@ static const char *const nct6799_temp_label[] = {
        "Agent1 Dimm1",
        "BYTE_TEMP0",
        "BYTE_TEMP1",
-       "PECI Agent 0 Calibration",     /* undocumented */
-       "PECI Agent 1 Calibration",     /* undocumented */
+       "PECI/TSI Agent 0 Calibration",
+       "PECI/TSI Agent 1 Calibration",
        "",
        "Virtual_TEMP"
 };
@@ -763,27 +804,23 @@ static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
 static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
        0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
 
-static const s8 NCT6106_ALARM_BITS[] = {
-       0, 1, 2, 3, 4, 5, 7, 8,         /* in0.. in7 */
-       9, -1, -1, -1, -1, -1, -1,      /* in8..in14 */
-       -1,                             /* unused */
-       32, 33, 34, -1, -1,             /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       16, 17, 18, 19, 20, 21,         /* temp1..temp6 */
-       48, -1                          /* intrusion0, intrusion1 */
+static const s8 NCT6106_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  4,  5,  7,  8,  9, -1, -1, -1,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       32, 33, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       48, -1,                                           /* intr0-intr1  */
 };
 
 static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
        0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
 
-static const s8 NCT6106_BEEP_BITS[] = {
-       0, 1, 2, 3, 4, 5, 7, 8,         /* in0.. in7 */
-       9, 10, 11, 12, -1, -1, -1,      /* in8..in14 */
-       32,                             /* global beep enable */
-       24, 25, 26, 27, 28,             /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       16, 17, 18, 19, 20, 21,         /* temp1..temp6 */
-       34, -1                          /* intrusion0, intrusion1 */
+static const s8 NCT6106_BEEP_BITS[NUM_BEEP_BITS] = {
+        0,  1,  2,  3,  4,  5,  7,  8,  9, 10, 11, 12,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       34, -1, 32                                        /* intr0-intr1, beep_en */
 };
 
 static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = {
@@ -843,24 +880,20 @@ static const u16 NCT6116_REG_AUTO_TEMP[] = {
 static const u16 NCT6116_REG_AUTO_PWM[] = {
        0x164, 0x174, 0x184, 0x1d4, 0x1e4 };
 
-static const s8 NCT6116_ALARM_BITS[] = {
-       0, 1, 2, 3, 4, 5, 7, 8,         /* in0.. in7 */
-       9, -1, -1, -1, -1, -1, -1,      /* in8..in9 */
-       -1,                             /* unused */
-       32, 33, 34, 35, 36,             /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       16, 17, 18, -1, -1, -1,         /* temp1..temp6 */
-       48, -1                          /* intrusion0, intrusion1 */
+static const s8 NCT6116_ALARM_BITS[NUM_ALARM_BITS] = {
+        0,  1,  2,  3,  4,  5,  7,  8,  9, -1, -1, -1,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       32, 33, 34, 35, 36, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       48, -1,                                           /* intr0-intr1  */
 };
 
-static const s8 NCT6116_BEEP_BITS[] = {
-       0, 1, 2, 3, 4, 5, 7, 8,         /* in0.. in7 */
-       9, 10, 11, 12, -1, -1, -1,      /* in8..in14 */
-       32,                             /* global beep enable */
-       24, 25, 26, 27, 28,             /* fan1..fan5 */
-       -1, -1, -1,                     /* unused */
-       16, 17, 18, -1, -1, -1,         /* temp1..temp6 */
-       34, -1                          /* intrusion0, intrusion1 */
+static const s8 NCT6116_BEEP_BITS[NUM_BEEP_BITS] = {
+        0,  1,  2,  3,  4,  5,  7,  8,  9, 10, 11, 12,   /* in0-in11     */
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* in12-in23    */
+       24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1,   /* fan1-fan12   */
+       16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1,   /* temp1-temp12 */
+       34, -1, 32                                        /* intr0-intr1, beep_en */
 };
 
 static const u16 NCT6116_REG_TSI_TEMP[] = { 0x59, 0x5b };
@@ -958,12 +991,12 @@ static const u16 scale_in[15] = {
 /*
  * NCT6798 scaling:
  *    CPUVC, IN1, AVSB, 3VCC, IN0, IN8, IN4, 3VSB, VBAT,  VTT,  IN5,  IN6, IN2,
- *      IN3, IN7
- * Additional scales to be added later: IN9 (800), VHIF (1600)
+ *      IN3, IN7,  IN9, VHIF, IN10
+ * 15-17 for NCT6799 only
  */
-static const u16 scale_in_6798[15] = {
+static const u16 scale_in_6798[NUM_IN] = {
        800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 1600, 1600, 1600, 800,
-       800, 800
+       800, 800,  800, 1600, 800
 };
 
 static inline long in_from_reg(u8 reg, u8 nr, const u16 *scales)
@@ -3862,13 +3895,9 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
        case nct6795:
        case nct6796:
        case nct6797:
-       case nct6798:
-       case nct6799:
                data->in_num = 15;
                data->pwm_num = (data->kind == nct6796 ||
-                                data->kind == nct6797 ||
-                                data->kind == nct6798 ||
-                                data->kind == nct6799) ? 7 : 6;
+                                data->kind == nct6797) ? 7 : 6;
                data->auto_pwm_num = 4;
                data->has_fan_div = false;
                data->temp_fixed_num = 6;
@@ -3912,16 +3941,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                        data->temp_mask = NCT6796_TEMP_MASK;
                        data->virt_temp_mask = NCT6796_VIRT_TEMP_MASK;
                        break;
-               case nct6798:
-                       data->temp_label = nct6798_temp_label;
-                       data->temp_mask = NCT6798_TEMP_MASK;
-                       data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
-                       break;
-               case nct6799:
-                       data->temp_label = nct6799_temp_label;
-                       data->temp_mask = NCT6799_TEMP_MASK;
-                       data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
-                       break;
                }
 
                data->REG_CONFIG = NCT6775_REG_CONFIG;
@@ -3980,8 +3999,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                case nct6795:
                case nct6796:
                case nct6797:
-               case nct6798:
-               case nct6799:
                        data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
                        num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
                        break;
@@ -3990,9 +4007,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                        break;
                }
 
-               if (data->kind == nct6798 || data->kind == nct6799)
-                       data->scale_in = scale_in_6798;
-
                reg_temp = NCT6779_REG_TEMP;
                num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
                if (data->kind == nct6791) {
@@ -4009,6 +4023,95 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                reg_temp_crit = NCT6779_REG_TEMP_CRIT;
 
                break;
+       case nct6798:
+       case nct6799:
+               data->in_num = data->kind == nct6799 ? 18 : 15;
+               data->scale_in = scale_in_6798;
+               data->pwm_num = 7;
+               data->auto_pwm_num = 4;
+               data->has_fan_div = false;
+               data->temp_fixed_num = 6;
+               data->num_temp_alarms = 7;
+               data->num_temp_beeps = 8;
+
+               data->ALARM_BITS = NCT6799_ALARM_BITS;
+               data->BEEP_BITS = NCT6799_BEEP_BITS;
+
+               data->fan_from_reg = fan_from_reg_rpm;
+               data->fan_from_reg_min = fan_from_reg13;
+               data->target_temp_mask = 0xff;
+               data->tolerance_mask = 0x07;
+               data->speed_tolerance_limit = 63;
+
+               switch (data->kind) {
+               default:
+               case nct6798:
+                       data->temp_label = nct6798_temp_label;
+                       data->temp_mask = NCT6798_TEMP_MASK;
+                       data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
+                       break;
+               case nct6799:
+                       data->temp_label = nct6799_temp_label;
+                       data->temp_mask = NCT6799_TEMP_MASK;
+                       data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
+                       break;
+               }
+
+               data->REG_CONFIG = NCT6775_REG_CONFIG;
+               data->REG_VBAT = NCT6775_REG_VBAT;
+               data->REG_DIODE = NCT6775_REG_DIODE;
+               data->DIODE_MASK = NCT6775_DIODE_MASK;
+               data->REG_VIN = NCT6779_REG_IN;
+               data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+               data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+               data->REG_TARGET = NCT6775_REG_TARGET;
+               data->REG_FAN = NCT6779_REG_FAN;
+               data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+               data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+               data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
+               data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
+               data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+               data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
+               data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
+               data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
+               data->REG_PWM[0] = NCT6775_REG_PWM;
+               data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+               data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+               data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
+               data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
+               data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+               data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+               data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+               data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+               data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+               data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+               data->REG_CRITICAL_TEMP_TOLERANCE = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+               data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
+               data->CRITICAL_PWM_ENABLE_MASK = NCT6779_CRITICAL_PWM_ENABLE_MASK;
+               data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
+               data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
+               data->REG_TEMP_SOURCE = NCT6798_REG_TEMP_SOURCE;
+               data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
+               data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
+               data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
+               data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
+               data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
+               data->REG_ALARM = NCT6799_REG_ALARM;
+               data->REG_BEEP = NCT6792_REG_BEEP;
+               data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
+               num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
+
+               reg_temp = NCT6798_REG_TEMP;
+               num_reg_temp = ARRAY_SIZE(NCT6798_REG_TEMP);
+               reg_temp_mon = NCT6798_REG_TEMP_MON;
+               num_reg_temp_mon = ARRAY_SIZE(NCT6798_REG_TEMP_MON);
+               reg_temp_over = NCT6798_REG_TEMP_OVER;
+               reg_temp_hyst = NCT6798_REG_TEMP_HYST;
+               reg_temp_config = NCT6779_REG_TEMP_CONFIG;
+               reg_temp_alternate = NCT6798_REG_TEMP_ALTERNATE;
+               reg_temp_crit = NCT6798_REG_TEMP_CRIT;
+
+               break;
        default:
                return -ENODEV;
        }
index a409d7a..81bf03d 100644 (file)
@@ -35,7 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = {
        "NCT6796D",
        "NCT6797D",
        "NCT6798D",
-       "NCT6799D",
+       "NCT6796D-S/NCT6799D-R",
 };
 
 static unsigned short force_id;
index a84c6ce..296eff9 100644 (file)
@@ -8,7 +8,7 @@ enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
             nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
 
-#define NUM_TEMP       10      /* Max number of temp attribute sets w/ limits*/
+#define NUM_TEMP       12      /* Max number of temp attribute sets w/ limits*/
 #define NUM_TEMP_FIXED 6       /* Max number of fixed temp attribute sets */
 #define NUM_TSI_TEMP   8       /* Max number of TSI temp register pairs */
 
@@ -16,6 +16,7 @@ enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
 #define NUM_REG_BEEP   5       /* Max number of beep registers */
 
 #define NUM_FAN                7
+#define NUM_IN         18
 
 struct nct6775_data {
        int addr;       /* IO base of hw monitor block */
@@ -97,7 +98,7 @@ struct nct6775_data {
        /* Register values */
        u8 bank;                /* current register bank */
        u8 in_num;              /* number of in inputs we have */
-       u8 in[15][3];           /* [0]=in, [1]=in_max, [2]=in_min */
+       u8 in[NUM_IN][3];       /* [0]=in, [1]=in_max, [2]=in_min */
        const u16 *scale_in;    /* internal scaling factors */
        unsigned int rpm[NUM_FAN];
        u16 fan_min[NUM_FAN];
@@ -166,7 +167,7 @@ struct nct6775_data {
        u16 have_temp;
        u16 have_temp_fixed;
        u16 have_tsi_temp;
-       u16 have_in;
+       u32 have_in;
 
        /* Remember extra register values over suspend/resume */
        u8 vbat;
@@ -239,10 +240,25 @@ nct6775_add_attr_group(struct nct6775_data *data, const struct attribute_group *
 
 #define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE    0x28
 
-#define FAN_ALARM_BASE         16
-#define TEMP_ALARM_BASE                24
-#define INTRUSION_ALARM_BASE   30
-#define BEEP_ENABLE_BASE       15
+/*
+ * ALARM_BITS and BEEP_BITS store bit-index for the mask of the registers
+ * loaded into data->alarm and data->beep.
+ *
+ * Every input register (IN/TEMP/FAN) must have a corresponding
+ *   ALARM/BEEP bit at the same index BITS[BASE + index]
+ * Set value to -1 to disable the visibility of that '*_alarm' attribute and
+ * to pad the bits until the next BASE
+ *
+ * Beep has an additional GLOBAL_BEEP_ENABLE bit
+ */
+#define VIN_ALARM_BASE          0
+#define FAN_ALARM_BASE         24
+#define TEMP_ALARM_BASE                36
+#define INTRUSION_ALARM_BASE   48
+#define BEEP_ENABLE_BASE       50
+
+#define NUM_ALARM_BITS         (INTRUSION_ALARM_BASE + 4)
+#define NUM_BEEP_BITS          (BEEP_ENABLE_BASE + 1)
 
 /*
  * Not currently used:
index ebe6b03..18076ba 100644 (file)
@@ -20,8 +20,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
 /* Tests for error return values rely upon this value being < 0x80 */
@@ -193,7 +191,7 @@ static struct platform_driver nsa320_hwmon_driver = {
        .probe = nsa320_hwmon_probe,
        .driver = {
                .name = "nsa320-hwmon",
-               .of_match_table = of_match_ptr(of_nsa320_hwmon_match),
+               .of_match_table = of_nsa320_hwmon_match,
        },
 };
 
index 1e1cc67..ea96020 100644 (file)
@@ -434,23 +434,9 @@ static const struct hwmon_chip_info oxp_ec_chip_info = {
 /* Initialization logic */
 static int oxp_platform_probe(struct platform_device *pdev)
 {
-       const struct dmi_system_id *dmi_entry;
        struct device *dev = &pdev->dev;
        struct device *hwdev;
 
-       /*
-        * Have to check for AMD processor here because DMI strings are the
-        * same between Intel and AMD boards, the only way to tell them apart
-        * is the CPU.
-        * Intel boards seem to have different EC registers and values to
-        * read/write.
-        */
-       dmi_entry = dmi_first_match(dmi_table);
-       if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-               return -ENODEV;
-
-       board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
-
        hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
                                                     &oxp_ec_chip_info, NULL);
 
@@ -469,6 +455,21 @@ static struct platform_device *oxp_platform_device;
 
 static int __init oxp_platform_init(void)
 {
+       const struct dmi_system_id *dmi_entry;
+
+       /*
+        * Have to check for AMD processor here because DMI strings are the
+        * same between Intel and AMD boards, the only way to tell them apart
+        * is the CPU.
+        * Intel boards seem to have different EC registers and values to
+        * read/write.
+        */
+       dmi_entry = dmi_first_match(dmi_table);
+       if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+               return -ENODEV;
+
+       board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
+
        oxp_platform_device =
                platform_create_bundle(&oxp_platform_driver,
                                       oxp_platform_probe, NULL, 0, NULL, 0);
index ed96840..ce89da3 100644 (file)
@@ -219,19 +219,21 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
 {
        int chan_rank_max = priv->gen_info->chan_rank_max;
        int dimm_idx_max = priv->gen_info->dimm_idx_max;
-       u32 chan_rank_empty = 0;
-       u32 dimm_mask = 0;
-       int chan_rank, dimm_idx, ret;
+       DECLARE_BITMAP(dimm_mask, DIMM_NUMS_MAX);
+       DECLARE_BITMAP(chan_rank_empty, CHAN_RANK_MAX);
+
+       int chan_rank, dimm_idx, ret, i;
        u32 pcs;
 
-       BUILD_BUG_ON(BITS_PER_TYPE(chan_rank_empty) < CHAN_RANK_MAX);
-       BUILD_BUG_ON(BITS_PER_TYPE(dimm_mask) < DIMM_NUMS_MAX);
        if (chan_rank_max * dimm_idx_max > DIMM_NUMS_MAX) {
                WARN_ONCE(1, "Unsupported number of DIMMs - chan_rank_max: %d, dimm_idx_max: %d",
                          chan_rank_max, dimm_idx_max);
                return -EINVAL;
        }
 
+       bitmap_zero(dimm_mask, DIMM_NUMS_MAX);
+       bitmap_zero(chan_rank_empty, CHAN_RANK_MAX);
+
        for (chan_rank = 0; chan_rank < chan_rank_max; chan_rank++) {
                ret = peci_pcs_read(priv->peci_dev, PECI_PCS_DDR_DIMM_TEMP, chan_rank, &pcs);
                if (ret) {
@@ -242,7 +244,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
                         * detection to be performed at a later point in time.
                         */
                        if (ret == -EINVAL) {
-                               chan_rank_empty |= BIT(chan_rank);
+                               bitmap_set(chan_rank_empty, chan_rank, 1);
                                continue;
                        }
 
@@ -251,7 +253,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
 
                for (dimm_idx = 0; dimm_idx < dimm_idx_max; dimm_idx++)
                        if (__dimm_temp(pcs, dimm_idx))
-                               dimm_mask |= BIT(chan_rank * dimm_idx_max + dimm_idx);
+                               bitmap_set(dimm_mask, chan_rank * dimm_idx_max + dimm_idx, 1);
        }
 
        /*
@@ -260,7 +262,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
         * host platform boot. Retrying a couple of times lets us make sure
         * that the state is persistent.
         */
-       if (chan_rank_empty == GENMASK(chan_rank_max - 1, 0)) {
+       if (bitmap_full(chan_rank_empty, chan_rank_max)) {
                if (priv->no_dimm_retry_count < NO_DIMM_RETRY_COUNT_MAX) {
                        priv->no_dimm_retry_count++;
 
@@ -274,14 +276,16 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
         * It's possible that memory training is not done yet. In this case we
         * defer the detection to be performed at a later point in time.
         */
-       if (!dimm_mask) {
+       if (bitmap_empty(dimm_mask, DIMM_NUMS_MAX)) {
                priv->no_dimm_retry_count = 0;
                return -EAGAIN;
        }
 
-       dev_dbg(priv->dev, "Scanned populated DIMMs: %#x\n", dimm_mask);
+       for_each_set_bit(i, dimm_mask, DIMM_NUMS_MAX) {
+               dev_dbg(priv->dev, "Found DIMM%#x\n", i);
+       }
 
-       bitmap_from_arr32(priv->dimm_mask, &dimm_mask, DIMM_NUMS_MAX);
+       bitmap_copy(priv->dimm_mask, dimm_mask, DIMM_NUMS_MAX);
 
        return 0;
 }
index 270b633..b4e93bd 100644 (file)
@@ -317,6 +317,13 @@ config SENSORS_MP2975
          This driver can also be built as a module. If so, the module will
          be called mp2975.
 
+config SENSORS_MP2975_REGULATOR
+       depends on SENSORS_MP2975 && REGULATOR
+       bool "Regulator support for MPS MP2975"
+       help
+         If you say yes here you get regulator support for MPS MP2975
+         Dual Loop Digital Multi-Phase Controller.
+
 config SENSORS_MP5023
        tristate "MPS MP5023"
        help
index 0a0ef4c..e0c55fd 100644 (file)
@@ -3,14 +3,51 @@
  * Copyright 2023 IBM Corp.
  */
 
+#include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/i2c.h>
+#include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/pmbus.h>
 #include <linux/hwmon-sysfs.h>
 #include "pmbus.h"
 
+#define ACBEL_MFR_FW_REVISION  0xd9
+
+static ssize_t acbel_fsg032_debugfs_read(struct file *file, char __user *buf, size_t count,
+                                        loff_t *ppos)
+{
+       struct i2c_client *client = file->private_data;
+       u8 data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
+       char out[8];
+       int rc;
+
+       rc = i2c_smbus_read_block_data(client, ACBEL_MFR_FW_REVISION, data);
+       if (rc < 0)
+               return rc;
+
+       rc = snprintf(out, sizeof(out), "%*phN\n", min(rc, 3), data);
+       return simple_read_from_buffer(buf, count, ppos, out, rc);
+}
+
+static const struct file_operations acbel_debugfs_ops = {
+       .llseek = noop_llseek,
+       .read = acbel_fsg032_debugfs_read,
+       .write = NULL,
+       .open = simple_open,
+};
+
+static void acbel_fsg032_init_debugfs(struct i2c_client *client)
+{
+       struct dentry *debugfs = pmbus_get_debugfs_dir(client);
+
+       if (!debugfs)
+               return;
+
+       debugfs_create_file("fw_version", 0444, debugfs, client, &acbel_debugfs_ops);
+}
+
 static const struct i2c_device_id acbel_fsg032_id[] = {
        { "acbel_fsg032" },
        {}
@@ -59,6 +96,7 @@ static int acbel_fsg032_probe(struct i2c_client *client)
        if (rc)
                return rc;
 
+       acbel_fsg032_init_debugfs(client);
        return 0;
 }
 
index f7ff3e4..04e0d59 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/debugfs.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include "pmbus.h"
 
 struct dps920ab_data {
index c791925..1ba4c5e 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/pmbus.h>
 
 #include "pmbus.h"
@@ -489,7 +489,7 @@ static int ibm_cffps_probe(struct i2c_client *client)
        const struct i2c_device_id *id;
 
        if (md) {
-               vs = (enum versions)md;
+               vs = (uintptr_t)md;
        } else {
                id = i2c_match_id(ibm_cffps_id, client);
                if (id)
index 871c322..04185be 100644 (file)
@@ -6,7 +6,7 @@
  *
  * VOUT_MODE is not supported by the device. The driver fakes VOUT linear16
  * mode with exponent value -8 as direct mode with m=256/b=0/R=0.
- *          
+ *
  * The device supports VOUT_PEAK, IOUT_PEAK, and TEMPERATURE_PEAK, however
  * this driver does not currently support them.
  */
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/regulator/driver.h>
 #include "pmbus.h"
 
index 7bcf279..d56ec24 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/pmbus.h>
 #include <linux/util_macros.h>
 #include "pmbus.h"
@@ -114,6 +114,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
        const struct pmbus_driver_info *info;
        const struct max20730_data *data;
        char tbuf[DEBUG_FS_DATA_MAX] = { 0 };
+       char *result = tbuf;
        u16 val;
 
        info = pmbus_get_driver_info(psu->client);
@@ -148,13 +149,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                        >> MAX20730_MFR_DEVSET1_TSTAT_BIT_POS;
 
                if (val == 0)
-                       len = strlcpy(tbuf, "2000\n", DEBUG_FS_DATA_MAX);
+                       result = "2000\n";
                else if (val == 1)
-                       len = strlcpy(tbuf, "125\n", DEBUG_FS_DATA_MAX);
+                       result = "125\n";
                else if (val == 2)
-                       len = strlcpy(tbuf, "62.5\n", DEBUG_FS_DATA_MAX);
+                       result = "62.5\n";
                else
-                       len = strlcpy(tbuf, "32\n", DEBUG_FS_DATA_MAX);
+                       result = "32\n";
                break;
        case MAX20730_DEBUGFS_INTERNAL_GAIN:
                val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_RGAIN_MASK)
@@ -163,35 +164,35 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                if (data->id == max20734) {
                        /* AN6209 */
                        if (val == 0)
-                               len = strlcpy(tbuf, "0.8\n", DEBUG_FS_DATA_MAX);
+                               result = "0.8\n";
                        else if (val == 1)
-                               len = strlcpy(tbuf, "3.2\n", DEBUG_FS_DATA_MAX);
+                               result = "3.2\n";
                        else if (val == 2)
-                               len = strlcpy(tbuf, "1.6\n", DEBUG_FS_DATA_MAX);
+                               result = "1.6\n";
                        else
-                               len = strlcpy(tbuf, "6.4\n", DEBUG_FS_DATA_MAX);
+                               result = "6.4\n";
                } else if (data->id == max20730 || data->id == max20710) {
                        /* AN6042 or AN6140 */
                        if (val == 0)
-                               len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
+                               result = "0.9\n";
                        else if (val == 1)
-                               len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
+                               result = "3.6\n";
                        else if (val == 2)
-                               len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
+                               result = "1.8\n";
                        else
-                               len = strlcpy(tbuf, "7.2\n", DEBUG_FS_DATA_MAX);
+                               result = "7.2\n";
                } else if (data->id == max20743) {
                        /* AN6042 */
                        if (val == 0)
-                               len = strlcpy(tbuf, "0.45\n", DEBUG_FS_DATA_MAX);
+                               result = "0.45\n";
                        else if (val == 1)
-                               len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
+                               result = "1.8\n";
                        else if (val == 2)
-                               len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
+                               result = "0.9\n";
                        else
-                               len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
+                               result = "3.6\n";
                } else {
-                       len = strlcpy(tbuf, "Not supported\n", DEBUG_FS_DATA_MAX);
+                       result = "Not supported\n";
                }
                break;
        case MAX20730_DEBUGFS_BOOT_VOLTAGE:
@@ -199,26 +200,26 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                        >> MAX20730_MFR_DEVSET1_VBOOT_BIT_POS;
 
                if (val == 0)
-                       len = strlcpy(tbuf, "0.6484\n", DEBUG_FS_DATA_MAX);
+                       result = "0.6484\n";
                else if (val == 1)
-                       len = strlcpy(tbuf, "0.8984\n", DEBUG_FS_DATA_MAX);
+                       result = "0.8984\n";
                else if (val == 2)
-                       len = strlcpy(tbuf, "1.0\n", DEBUG_FS_DATA_MAX);
+                       result = "1.0\n";
                else
-                       len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+                       result = "Invalid\n";
                break;
        case MAX20730_DEBUGFS_OUT_V_RAMP_RATE:
                val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_VRATE)
                        >> MAX20730_MFR_DEVSET2_VRATE_BIT_POS;
 
                if (val == 0)
-                       len = strlcpy(tbuf, "4\n", DEBUG_FS_DATA_MAX);
+                       result = "4\n";
                else if (val == 1)
-                       len = strlcpy(tbuf, "2\n", DEBUG_FS_DATA_MAX);
+                       result = "2\n";
                else if (val == 2)
-                       len = strlcpy(tbuf, "1\n", DEBUG_FS_DATA_MAX);
+                       result = "1\n";
                else
-                       len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+                       result = "Invalid\n";
                break;
        case MAX20730_DEBUGFS_OC_PROTECT_MODE:
                ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
@@ -230,13 +231,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                        >> MAX20730_MFR_DEVSET2_SS_BIT_POS;
 
                if (val == 0)
-                       len = strlcpy(tbuf, "0.75\n", DEBUG_FS_DATA_MAX);
+                       result = "0.75\n";
                else if (val == 1)
-                       len = strlcpy(tbuf, "1.5\n", DEBUG_FS_DATA_MAX);
+                       result = "1.5\n";
                else if (val == 2)
-                       len = strlcpy(tbuf, "3\n", DEBUG_FS_DATA_MAX);
+                       result = "3\n";
                else
-                       len = strlcpy(tbuf, "6\n", DEBUG_FS_DATA_MAX);
+                       result = "6\n";
                break;
        case MAX20730_DEBUGFS_IMAX:
                ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
@@ -287,10 +288,11 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
                                "%d.%d\n", ret / 10000, ret % 10000);
                break;
        default:
-               len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+               result = "Invalid\n";
        }
 
-       return simple_read_from_buffer(buf, count, ppos, tbuf, len);
+       len = strlen(result);
+       return simple_read_from_buffer(buf, count, ppos, result, len);
 }
 
 static const struct file_operations max20730_fops = {
@@ -714,7 +716,7 @@ static int max20730_probe(struct i2c_client *client)
        }
 
        if (client->dev.of_node)
-               chip_id = (enum chips)of_device_get_match_data(dev);
+               chip_id = (uintptr_t)of_device_get_match_data(dev);
        else
                chip_id = i2c_match_id(max20730_id, client)->driver_data;
 
index 2109b04..26ba506 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include "pmbus.h"
 
 /* Vendor specific registers. */
@@ -34,6 +35,8 @@
 #define MP2975_MFR_OVP_TH_SET          0xe5
 #define MP2975_MFR_UVP_SET             0xe6
 
+#define MP2973_MFR_RESO_SET            0xc7
+
 #define MP2975_VOUT_FORMAT             BIT(15)
 #define MP2975_VID_STEP_SEL_R1         BIT(4)
 #define MP2975_IMVP9_EN_R1             BIT(13)
 #define MP2975_SENSE_AMPL_HALF         2
 #define MP2975_VIN_UV_LIMIT_UNIT       8
 
+#define MP2973_VOUT_FORMAT_R1          GENMASK(7, 6)
+#define MP2973_VOUT_FORMAT_R2          GENMASK(4, 3)
+#define MP2973_VOUT_FORMAT_DIRECT_R1   BIT(7)
+#define MP2973_VOUT_FORMAT_LINEAR_R1   BIT(6)
+#define MP2973_VOUT_FORMAT_DIRECT_R2   BIT(4)
+#define MP2973_VOUT_FORMAT_LINEAR_R2   BIT(3)
+
+#define MP2973_MFR_VR_MULTI_CONFIG_R1  0x0d
+#define MP2973_MFR_VR_MULTI_CONFIG_R2  0x1d
+#define MP2973_VID_STEP_SEL_R1         BIT(4)
+#define MP2973_IMVP9_EN_R1             BIT(14)
+#define MP2973_VID_STEP_SEL_R2         BIT(3)
+#define MP2973_IMVP9_EN_R2             BIT(13)
+
+#define MP2973_MFR_OCP_TOTAL_SET       0x5f
+#define MP2973_OCP_TOTAL_CUR_MASK      GENMASK(6, 0)
+#define MP2973_MFR_OCP_LEVEL_RES       BIT(15)
+
+#define MP2973_MFR_READ_IOUT_PK                0x90
+#define MP2973_MFR_READ_POUT_PK                0x91
+
 #define MP2975_MAX_PHASE_RAIL1 8
 #define MP2975_MAX_PHASE_RAIL2 4
+
+#define MP2973_MAX_PHASE_RAIL1 14
+#define MP2973_MAX_PHASE_RAIL2 6
+
+#define MP2971_MAX_PHASE_RAIL1 8
+#define MP2971_MAX_PHASE_RAIL2 3
+
 #define MP2975_PAGE_NUM                2
 
 #define MP2975_RAIL2_FUNC      (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \
                                 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \
                                 PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)
 
+enum chips {
+       mp2971, mp2973, mp2975
+};
+
+static const int mp2975_max_phases[][MP2975_PAGE_NUM] = {
+       [mp2975] = { MP2975_MAX_PHASE_RAIL1, MP2975_MAX_PHASE_RAIL2 },
+       [mp2973] = { MP2973_MAX_PHASE_RAIL1, MP2973_MAX_PHASE_RAIL2 },
+       [mp2971] = { MP2971_MAX_PHASE_RAIL1, MP2971_MAX_PHASE_RAIL2 },
+};
+
 struct mp2975_data {
        struct pmbus_driver_info info;
+       enum chips chip_id;
        int vout_scale;
+       int max_phases[MP2975_PAGE_NUM];
        int vid_step[MP2975_PAGE_NUM];
        int vref[MP2975_PAGE_NUM];
        int vref_off[MP2975_PAGE_NUM];
        int vout_max[MP2975_PAGE_NUM];
        int vout_ov_fixed[MP2975_PAGE_NUM];
-       int vout_format[MP2975_PAGE_NUM];
        int curr_sense_gain[MP2975_PAGE_NUM];
 };
 
-#define to_mp2975_data(x)  container_of(x, struct mp2975_data, info)
+static const struct i2c_device_id mp2975_id[] = {
+       {"mp2971", mp2971},
+       {"mp2973", mp2973},
+       {"mp2975", mp2975},
+       {}
+};
 
-static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg)
-{
-       switch (reg) {
-       case PMBUS_VOUT_MODE:
-               /*
-                * Enforce VOUT direct format, since device allows to set the
-                * different formats for the different rails. Conversion from
-                * VID to direct provided by driver internally, in case it is
-                * necessary.
-                */
-               return PB_VOUT_MODE_DIRECT;
-       default:
-               return -ENODATA;
-       }
-}
+MODULE_DEVICE_TABLE(i2c, mp2975_id);
+
+static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = {
+       PMBUS_REGULATOR("vout", 0),
+       PMBUS_REGULATOR("vout", 1),
+};
+
+#define to_mp2975_data(x)  container_of(x, struct mp2975_data, info)
 
 static int
 mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
@@ -117,6 +157,41 @@ mp2975_vid2direct(int vrf, int val)
        return 0;
 }
 
+#define MAX_LIN_MANTISSA       (1023 * 1000)
+#define MIN_LIN_MANTISSA       (511 * 1000)
+
+/* Converts a milli-unit DIRECT value to LINEAR11 format */
+static u16 mp2975_data2reg_linear11(s64 val)
+{
+       s16 exponent = 0, mantissa;
+       bool negative = false;
+
+       /* simple case */
+       if (val == 0)
+               return 0;
+
+       /* Reduce large mantissa until it fits into 10 bit */
+       while (val >= MAX_LIN_MANTISSA && exponent < 15) {
+               exponent++;
+               val >>= 1;
+       }
+       /* Increase small mantissa to improve precision */
+       while (val < MIN_LIN_MANTISSA && exponent > -15) {
+               exponent--;
+               val <<= 1;
+       }
+
+       /* Convert mantissa from milli-units to units */
+       mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
+
+       /* restore sign */
+       if (negative)
+               mantissa = -mantissa;
+
+       /* Convert to 5 bit exponent, 11 bit mantissa */
+       return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
+}
+
 static int
 mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data,
                  int page, int phase, u8 reg)
@@ -214,6 +289,89 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data,
        return ret;
 }
 
+static int mp2973_read_word_data(struct i2c_client *client, int page,
+                                int phase, int reg)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct mp2975_data *data = to_mp2975_data(info);
+       int ret;
+
+       switch (reg) {
+       case PMBUS_OT_FAULT_LIMIT:
+               ret = mp2975_read_word_helper(client, page, phase, reg,
+                                             GENMASK(7, 0));
+               break;
+       case PMBUS_VIN_OV_FAULT_LIMIT:
+               ret = mp2975_read_word_helper(client, page, phase, reg,
+                                             GENMASK(7, 0));
+               if (ret < 0)
+                       return ret;
+
+               ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT);
+               break;
+       case PMBUS_VOUT_OV_FAULT_LIMIT:
+               /*
+                * MP2971 and mp2973 only supports tracking (ovp1) mode.
+                */
+               ret = mp2975_read_word_helper(client, page, phase,
+                                             MP2975_MFR_OVP_TH_SET,
+                                             GENMASK(2, 0));
+               if (ret < 0)
+                       return ret;
+
+               ret = data->vout_max[page] + 50 * (ret + 1);
+               break;
+       case PMBUS_VOUT_UV_FAULT_LIMIT:
+               ret = mp2975_read_word_helper(client, page, phase, reg,
+                                             GENMASK(8, 0));
+               if (ret < 0)
+                       return ret;
+               ret = mp2975_vid2direct(info->vrm_version[page], ret);
+               break;
+       case PMBUS_VIRT_READ_POUT_MAX:
+               ret = pmbus_read_word_data(client, page, phase,
+                                          MP2973_MFR_READ_POUT_PK);
+               break;
+       case PMBUS_VIRT_READ_IOUT_MAX:
+               ret = pmbus_read_word_data(client, page, phase,
+                                          MP2973_MFR_READ_IOUT_PK);
+               break;
+       case PMBUS_IOUT_OC_FAULT_LIMIT:
+               ret = mp2975_read_word_helper(client, page, phase,
+                                             MP2973_MFR_OCP_TOTAL_SET,
+                                             GENMASK(15, 0));
+               if (ret < 0)
+                       return ret;
+
+               if (ret & MP2973_MFR_OCP_LEVEL_RES)
+                       ret = 2 * (ret & MP2973_OCP_TOTAL_CUR_MASK);
+               else
+                       ret = ret & MP2973_OCP_TOTAL_CUR_MASK;
+
+               ret = mp2975_data2reg_linear11(ret * info->phases[page] * 1000);
+               break;
+       case PMBUS_UT_WARN_LIMIT:
+       case PMBUS_UT_FAULT_LIMIT:
+       case PMBUS_VIN_UV_WARN_LIMIT:
+       case PMBUS_VIN_UV_FAULT_LIMIT:
+       case PMBUS_VOUT_UV_WARN_LIMIT:
+       case PMBUS_VOUT_OV_WARN_LIMIT:
+       case PMBUS_VIN_OV_WARN_LIMIT:
+       case PMBUS_IIN_OC_FAULT_LIMIT:
+       case PMBUS_IOUT_OC_LV_FAULT_LIMIT:
+       case PMBUS_IOUT_OC_WARN_LIMIT:
+       case PMBUS_IOUT_UC_FAULT_LIMIT:
+       case PMBUS_POUT_OP_FAULT_LIMIT:
+       case PMBUS_POUT_OP_WARN_LIMIT:
+       case PMBUS_PIN_OP_WARN_LIMIT:
+               return -ENXIO;
+       default:
+               return -ENODATA;
+       }
+
+       return ret;
+}
+
 static int mp2975_read_word_data(struct i2c_client *client, int page,
                                 int phase, int reg)
 {
@@ -222,6 +380,11 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
        int ret;
 
        switch (reg) {
+       case PMBUS_STATUS_WORD:
+               /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */
+               ret = pmbus_read_word_data(client, page, phase, reg);
+               ret ^= PB_STATUS_POWER_GOOD_N;
+               break;
        case PMBUS_OT_FAULT_LIMIT:
                ret = mp2975_read_word_helper(client, page, phase, reg,
                                              GENMASK(7, 0));
@@ -260,24 +423,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
                ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 *
                                        (ret + 1) * data->vout_scale, 10);
                break;
-       case PMBUS_READ_VOUT:
-               ret = mp2975_read_word_helper(client, page, phase, reg,
-                                             GENMASK(11, 0));
-               if (ret < 0)
-                       return ret;
-
-               /*
-                * READ_VOUT can be provided in VID or direct format. The
-                * format type is specified by bit 15 of the register
-                * MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct
-                * format, since device allows to set the different formats for
-                * the different rails and also all VOUT limits registers are
-                * provided in a direct format. In case format is VID - convert
-                * to direct.
-                */
-               if (data->vout_format[page] == vid)
-                       ret = mp2975_vid2direct(info->vrm_version[page], ret);
-               break;
        case PMBUS_VIRT_READ_POUT_MAX:
                ret = mp2975_read_word_helper(client, page, phase,
                                              MP2975_MFR_READ_POUT_PK,
@@ -326,25 +471,25 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
        return ret;
 }
 
-static int mp2975_identify_multiphase_rail2(struct i2c_client *client)
+static int mp2975_identify_multiphase_rail2(struct i2c_client *client,
+                                           struct mp2975_data *data)
 {
        int ret;
 
        /*
-        * Identify multiphase for rail 2 - could be from 0 to 4.
+        * Identify multiphase for rail 2 - could be from 0 to data->max_phases[1].
         * In case phase number is zero â€“ only page zero is supported
         */
        ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
        if (ret < 0)
                return ret;
 
-       /* Identify multiphase for rail 2 - could be from 0 to 4. */
        ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2);
        if (ret < 0)
                return ret;
 
        ret &= GENMASK(2, 0);
-       return (ret >= 4) ? 4 : ret;
+       return (ret >= data->max_phases[1]) ? data->max_phases[1] : ret;
 }
 
 static void mp2975_set_phase_rail1(struct pmbus_driver_info *info)
@@ -375,7 +520,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
        if (ret < 0)
                return ret;
 
-       /* Identify multiphase for rail 1 - could be from 1 to 8. */
+       /* Identify multiphase for rail 1 - could be from 1 to data->max_phases[0]. */
        ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1);
        if (ret <= 0)
                return ret;
@@ -383,21 +528,23 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
        info->phases[0] = ret & GENMASK(3, 0);
 
        /*
-        * The device provides a total of 8 PWM pins, and can be configured
+        * The device provides a total of $n PWM pins, and can be configured
         * to different phase count applications for rail 1 and rail 2.
-        * Rail 1 can be set to 8 phases, while rail 2 can only be set to 4
-        * phases at most. When rail 1’s phase count is configured as 0, rail
+        * Rail 1 can be set to $n phases, while rail 2 can be set to less than
+        * that. When rail 1’s phase count is configured as 0, rail
         * 1 operates with 1-phase DCM. When rail 2 phase count is configured
         * as 0, rail 2 is disabled.
         */
-       if (info->phases[0] > MP2975_MAX_PHASE_RAIL1)
+       if (info->phases[0] > data->max_phases[0])
                return -EINVAL;
 
-       mp2975_set_phase_rail1(info);
-       num_phases2 = min(MP2975_MAX_PHASE_RAIL1 - info->phases[0],
-                         MP2975_MAX_PHASE_RAIL2);
-       if (info->phases[1] && info->phases[1] <= num_phases2)
-               mp2975_set_phase_rail2(info, num_phases2);
+       if (data->chip_id == mp2975) {
+               mp2975_set_phase_rail1(info);
+               num_phases2 = min(data->max_phases[0] - info->phases[0],
+                                 data->max_phases[1]);
+               if (info->phases[1] && info->phases[1] <= num_phases2)
+                       mp2975_set_phase_rail2(info, num_phases2);
+       }
 
        return 0;
 }
@@ -451,6 +598,35 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,
                                          MP2975_MFR_VR_MULTI_CONFIG_R2, 1,
                                          MP2975_IMVP9_EN_R2,
                                          MP2975_VID_STEP_SEL_R2);
+
+       return ret;
+}
+
+static int
+mp2973_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,
+                         struct pmbus_driver_info *info)
+{
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
+       if (ret < 0)
+               return ret;
+
+       /* Identify VID mode for rail 1. */
+       ret = mp2975_identify_vid(client, data, info,
+                                 MP2973_MFR_VR_MULTI_CONFIG_R1, 0,
+                                 MP2973_IMVP9_EN_R1, MP2973_VID_STEP_SEL_R1);
+
+       if (ret < 0)
+               return ret;
+
+       /* Identify VID mode for rail 2, if connected. */
+       if (info->phases[1])
+               ret = mp2975_identify_vid(client, data, info,
+                                         MP2973_MFR_VR_MULTI_CONFIG_R2, 1,
+                                         MP2973_IMVP9_EN_R2,
+                                         MP2973_VID_STEP_SEL_R2);
+
        return ret;
 }
 
@@ -565,20 +741,37 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data,
 }
 
 static int
-mp2975_identify_vout_format(struct i2c_client *client,
-                           struct mp2975_data *data, int page)
+mp2975_set_vout_format(struct i2c_client *client,
+                      struct mp2975_data *data, int page)
 {
-       int ret;
+       int ret, i;
 
-       ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
-       if (ret < 0)
-               return ret;
-
-       if (ret & MP2975_VOUT_FORMAT)
-               data->vout_format[page] = vid;
-       else
-               data->vout_format[page] = direct;
-       return 0;
+       /* Enable DIRECT VOUT format 1mV/LSB */
+       if (data->chip_id == mp2975) {
+               ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
+               if (ret < 0)
+                       return ret;
+               if (ret & MP2975_VOUT_FORMAT) {
+                       ret &= ~MP2975_VOUT_FORMAT;
+                       ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, ret);
+               }
+       } else {
+               ret = i2c_smbus_read_word_data(client, MP2973_MFR_RESO_SET);
+               if (ret < 0)
+                       return ret;
+               i = ret;
+
+               if (page == 0) {
+                       i &= ~MP2973_VOUT_FORMAT_R1;
+                       i |= MP2973_VOUT_FORMAT_DIRECT_R1;
+               } else {
+                       i &= ~MP2973_VOUT_FORMAT_R2;
+                       i |= MP2973_VOUT_FORMAT_DIRECT_R2;
+               }
+               if (i != ret)
+                       ret = i2c_smbus_write_word_data(client, MP2973_MFR_RESO_SET, i);
+       }
+       return ret;
 }
 
 static int
@@ -600,7 +793,7 @@ mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data,
        if (ret < 0)
                return ret;
        thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON :
-                                                      MP2975_PROT_DEV_OV_OFF;
+                                                      MP2975_PROT_DEV_OV_OFF;
 
        /* Select the gain of remote sense amplifier. */
        ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP);
@@ -624,10 +817,10 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,
        for (i = 0; i < data->info.pages; i++) {
                ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
                if (ret < 0)
-                       return ret;
+                       continue;
 
-               /* Obtain voltage reference offsets. */
-               ret = mp2975_vref_offset_get(client, data, i);
+               /* Set VOUT format for READ_VOUT command : direct. */
+               ret = mp2975_set_vout_format(client, data, i);
                if (ret < 0)
                        return ret;
 
@@ -636,12 +829,12 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,
                if (ret < 0)
                        return ret;
 
-               /*
-                * Get VOUT format for READ_VOUT command : VID or direct.
-                * Pages on same device can be configured with different
-                * formats.
-                */
-               ret = mp2975_identify_vout_format(client, data, i);
+               /* Skip if reading Vref is unsupported */
+               if (data->chip_id != mp2975)
+                       continue;
+
+               /* Obtain voltage reference offsets. */
+               ret = mp2975_vref_offset_get(client, data, i);
                if (ret < 0)
                        return ret;
 
@@ -676,8 +869,32 @@ static struct pmbus_driver_info mp2975_info = {
                PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
                PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
                PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL,
-       .read_byte_data = mp2975_read_byte_data,
        .read_word_data = mp2975_read_word_data,
+#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
+       .num_regulators = 1,
+       .reg_desc = mp2975_reg_desc,
+#endif
+};
+
+static struct pmbus_driver_info mp2973_info = {
+       .pages = 1,
+       .format[PSC_VOLTAGE_IN] = linear,
+       .format[PSC_VOLTAGE_OUT] = direct,
+       .format[PSC_TEMPERATURE] = linear,
+       .format[PSC_CURRENT_IN] = linear,
+       .format[PSC_CURRENT_OUT] = linear,
+       .format[PSC_POWER] = linear,
+       .m[PSC_VOLTAGE_OUT] = 1,
+       .R[PSC_VOLTAGE_OUT] = 3,
+       .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+               PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+               PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
+               PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+       .read_word_data = mp2973_read_word_data,
+#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
+       .num_regulators = 1,
+       .reg_desc = mp2975_reg_desc,
+#endif
 };
 
 static int mp2975_probe(struct i2c_client *client)
@@ -691,11 +908,23 @@ static int mp2975_probe(struct i2c_client *client)
        if (!data)
                return -ENOMEM;
 
-       memcpy(&data->info, &mp2975_info, sizeof(*info));
+       if (client->dev.of_node)
+               data->chip_id = (enum chips)(unsigned long)of_device_get_match_data(&client->dev);
+       else
+               data->chip_id = i2c_match_id(mp2975_id, client)->driver_data;
+
+       memcpy(data->max_phases, mp2975_max_phases[data->chip_id],
+              sizeof(data->max_phases));
+
+       if (data->chip_id == mp2975)
+               memcpy(&data->info, &mp2975_info, sizeof(*info));
+       else
+               memcpy(&data->info, &mp2973_info, sizeof(*info));
+
        info = &data->info;
 
        /* Identify multiphase configuration for rail 2. */
-       ret = mp2975_identify_multiphase_rail2(client);
+       ret = mp2975_identify_multiphase_rail2(client, data);
        if (ret < 0)
                return ret;
 
@@ -704,6 +933,8 @@ static int mp2975_probe(struct i2c_client *client)
                data->info.pages = MP2975_PAGE_NUM;
                data->info.phases[1] = ret;
                data->info.func[1] = MP2975_RAIL2_FUNC;
+               if (IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR))
+                       data->info.num_regulators = MP2975_PAGE_NUM;
        }
 
        /* Identify multiphase configuration. */
@@ -711,25 +942,32 @@ static int mp2975_probe(struct i2c_client *client)
        if (ret)
                return ret;
 
-       /* Identify VID setting per rail. */
-       ret = mp2975_identify_rails_vid(client, data, info);
-       if (ret < 0)
-               return ret;
+       if (data->chip_id == mp2975) {
+               /* Identify VID setting per rail. */
+               ret = mp2975_identify_rails_vid(client, data, info);
+               if (ret < 0)
+                       return ret;
 
-       /* Obtain current sense gain of power stage. */
-       ret = mp2975_current_sense_gain_get(client, data);
-       if (ret)
-               return ret;
+               /* Obtain current sense gain of power stage. */
+               ret = mp2975_current_sense_gain_get(client, data);
+               if (ret)
+                       return ret;
 
-       /* Obtain voltage reference values. */
-       ret = mp2975_vref_get(client, data, info);
-       if (ret)
-               return ret;
+               /* Obtain voltage reference values. */
+               ret = mp2975_vref_get(client, data, info);
+               if (ret)
+                       return ret;
 
-       /* Obtain vout over-voltage scales. */
-       ret = mp2975_vout_ov_scale_get(client, data, info);
-       if (ret < 0)
-               return ret;
+               /* Obtain vout over-voltage scales. */
+               ret = mp2975_vout_ov_scale_get(client, data, info);
+               if (ret < 0)
+                       return ret;
+       } else {
+               /* Identify VID setting per rail. */
+               ret = mp2973_identify_rails_vid(client, data, info);
+               if (ret < 0)
+                       return ret;
+       }
 
        /* Obtain offsets, maximum and format for vout. */
        ret = mp2975_vout_per_rail_config_get(client, data, info);
@@ -739,15 +977,10 @@ static int mp2975_probe(struct i2c_client *client)
        return pmbus_do_probe(client, info);
 }
 
-static const struct i2c_device_id mp2975_id[] = {
-       {"mp2975", 0},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, mp2975_id);
-
 static const struct of_device_id __maybe_unused mp2975_of_match[] = {
-       {.compatible = "mps,mp2975"},
+       {.compatible = "mps,mp2971", .data = (void *)mp2971},
+       {.compatible = "mps,mp2973", .data = (void *)mp2973},
+       {.compatible = "mps,mp2975", .data = (void *)mp2975},
        {}
 };
 MODULE_DEVICE_TABLE(of, mp2975_of_match);
index c4c4324..21acb7f 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include "pmbus.h"
 
 static struct pmbus_driver_info mp5023_info = {
index 865d42e..6c62f01 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/pmbus.h>
 #include "pmbus.h"
 
index 7d8bd31..c954337 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2022 9elements GmbH
  */
 
+#include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/pmbus.h>
@@ -53,6 +54,30 @@ static int pli1209bc_read_word_data(struct i2c_client *client, int page,
        }
 }
 
+static int pli1209bc_write_byte(struct i2c_client *client, int page, u8 reg)
+{
+       int ret;
+
+       switch (reg) {
+       case PMBUS_CLEAR_FAULTS:
+               ret = pmbus_write_byte(client, page, reg);
+               /*
+                * PLI1209 takes 230 usec to execute the CLEAR_FAULTS command.
+                * During that time it's busy and NACKs all requests on the
+                * SMBUS interface. It also NACKs reads on PMBUS_STATUS_BYTE
+                * making it impossible to poll the BUSY flag.
+                *
+                * Just wait for not BUSY unconditionally.
+                */
+               usleep_range(250, 300);
+               break;
+       default:
+               ret = -ENODATA;
+               break;
+       }
+       return ret;
+}
+
 #if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
 static const struct regulator_desc pli1209bc_reg_desc = {
        .name = "vout2",
@@ -102,6 +127,7 @@ static struct pmbus_driver_info pli1209bc_info = {
            | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
            | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT,
        .read_word_data = pli1209bc_read_word_data,
+       .write_byte = pli1209bc_write_byte,
 #if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
        .num_regulators = 1,
        .reg_desc = &pli1209bc_reg_desc,
index 69a4e62..1363d9f 100644 (file)
@@ -561,7 +561,8 @@ static bool pmbus_check_register(struct i2c_client *client,
                rv = pmbus_check_status_cml(client);
        if (rv < 0 && (data->flags & PMBUS_READ_STATUS_AFTER_FAILED_CHECK))
                data->read_status(client, -1);
-       pmbus_clear_fault_page(client, -1);
+       if (reg < PMBUS_VIRT_BASE)
+               pmbus_clear_fault_page(client, -1);
        return rv >= 0;
 }
 
@@ -2540,7 +2541,6 @@ static int pmbus_identify_common(struct i2c_client *client,
                }
        }
 
-       pmbus_clear_fault_page(client, page);
        return 0;
 }
 
index b830f3b..a235c1c 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/i2c.h>
 #include <linux/kstrtox.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include "pmbus.h"
 
 #define STORE_DEFAULT_ALL              0x11
index ef99005..5c94662 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include "pmbus.h"
 
 enum chips {
@@ -235,7 +235,7 @@ static int tps53679_probe(struct i2c_client *client)
        enum chips chip_id;
 
        if (dev->of_node)
-               chip_id = (enum chips)of_device_get_match_data(dev);
+               chip_id = (uintptr_t)of_device_get_match_data(dev);
        else
                chip_id = i2c_match_id(tps53679_id, client)->driver_data;
 
index c404d30..8d9d422 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -588,7 +588,7 @@ static int ucd9000_probe(struct i2c_client *client)
        }
 
        if (client->dev.of_node)
-               chip = (enum chips)of_device_get_match_data(&client->dev);
+               chip = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                chip = mid->driver_data;
 
index a828479..7920d1c 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -103,7 +103,7 @@ static int ucd9200_probe(struct i2c_client *client)
        }
 
        if (client->dev.of_node)
-               chip = (enum chips)of_device_get_match_data(&client->dev);
+               chip = (uintptr_t)of_device_get_match_data(&client->dev);
        else
                chip = mid->driver_data;
 
index b79cece..dd85cf8 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/hwmon.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
 #include <linux/of.h>
 
 /*
index 121e5e9..a0d2206 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <linux/hwmon.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/scpi_protocol.h>
 #include <linux/slab.h>
index bf18630..7965791 100644 (file)
@@ -147,8 +147,20 @@ static const u16 mode_to_update_interval[] = {
         100,
 };
 
+static const struct hwmon_channel_info * const sht3x_channel_info[] = {
+       HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
+       HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN |
+                               HWMON_T_MIN_HYST | HWMON_T_MAX |
+                               HWMON_T_MAX_HYST | HWMON_T_ALARM),
+       HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN |
+                               HWMON_H_MIN_HYST | HWMON_H_MAX |
+                               HWMON_H_MAX_HYST | HWMON_H_ALARM),
+       NULL,
+};
+
 struct sht3x_data {
        struct i2c_client *client;
+       enum sht3x_chips chip_id;
        struct mutex i2c_lock; /* lock for sending i2c commands */
        struct mutex data_lock; /* lock for updating driver data */
 
@@ -276,27 +288,24 @@ out:
        return data;
 }
 
-/* sysfs attributes */
-static ssize_t temp1_input_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+static int temp1_input_read(struct device *dev)
 {
        struct sht3x_data *data = sht3x_update_client(dev);
 
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       return sprintf(buf, "%d\n", data->temperature);
+       return data->temperature;
 }
 
-static ssize_t humidity1_input_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
+static int humidity1_input_read(struct device *dev)
 {
        struct sht3x_data *data = sht3x_update_client(dev);
 
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       return sprintf(buf, "%u\n", data->humidity);
+       return data->humidity;
 }
 
 /*
@@ -332,33 +341,24 @@ static int limits_update(struct sht3x_data *data)
        return ret;
 }
 
-static ssize_t temp1_limit_show(struct device *dev,
-                               struct device_attribute *attr,
-                               char *buf)
+static int temp1_limit_read(struct device *dev, int index)
 {
        struct sht3x_data *data = dev_get_drvdata(dev);
-       u8 index = to_sensor_dev_attr(attr)->index;
-       int temperature_limit = data->temperature_limits[index];
 
-       return sysfs_emit(buf, "%d\n", temperature_limit);
+       return data->temperature_limits[index];
 }
 
-static ssize_t humidity1_limit_show(struct device *dev,
-                                   struct device_attribute *attr,
-                                   char *buf)
+static int humidity1_limit_read(struct device *dev, int index)
 {
        struct sht3x_data *data = dev_get_drvdata(dev);
-       u8 index = to_sensor_dev_attr(attr)->index;
-       u32 humidity_limit = data->humidity_limits[index];
 
-       return sysfs_emit(buf, "%u\n", humidity_limit);
+       return data->humidity_limits[index];
 }
 
 /*
- * limit_store must only be called with data_lock held
+ * limit_write must only be called with data_lock held
  */
-static size_t limit_store(struct device *dev,
-                         size_t count,
+static size_t limit_write(struct device *dev,
                          u8 index,
                          int temperature,
                          u32 humidity)
@@ -379,7 +379,7 @@ static size_t limit_store(struct device *dev,
         * ST = (T + 45) / 175 * 2^16
         * SRH = RH / 100 * 2^16
         * adapted for fixed point arithmetic and packed the same as
-        * in limit_show()
+        * in limit_read()
         */
        raw = ((u32)(temperature + 45000) * 24543) >> (16 + 7);
        raw |= ((humidity * 42950) >> 16) & 0xfe00;
@@ -400,50 +400,35 @@ static size_t limit_store(struct device *dev,
 
        data->temperature_limits[index] = temperature;
        data->humidity_limits[index] = humidity;
-       return count;
+
+       return 0;
 }
 
-static ssize_t temp1_limit_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf,
-                                size_t count)
+static int temp1_limit_write(struct device *dev, int index, int val)
 {
        int temperature;
        int ret;
        struct sht3x_data *data = dev_get_drvdata(dev);
-       u8 index = to_sensor_dev_attr(attr)->index;
 
-       ret = kstrtoint(buf, 0, &temperature);
-       if (ret)
-               return ret;
-
-       temperature = clamp_val(temperature, SHT3X_MIN_TEMPERATURE,
+       temperature = clamp_val(val, SHT3X_MIN_TEMPERATURE,
                                SHT3X_MAX_TEMPERATURE);
        mutex_lock(&data->data_lock);
-       ret = limit_store(dev, count, index, temperature,
+       ret = limit_write(dev, index, temperature,
                          data->humidity_limits[index]);
        mutex_unlock(&data->data_lock);
 
        return ret;
 }
 
-static ssize_t humidity1_limit_store(struct device *dev,
-                                    struct device_attribute *attr,
-                                    const char *buf,
-                                    size_t count)
+static int humidity1_limit_write(struct device *dev, int index, int val)
 {
        u32 humidity;
        int ret;
        struct sht3x_data *data = dev_get_drvdata(dev);
-       u8 index = to_sensor_dev_attr(attr)->index;
-
-       ret = kstrtou32(buf, 0, &humidity);
-       if (ret)
-               return ret;
 
-       humidity = clamp_val(humidity, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);
+       humidity = clamp_val(val, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);
        mutex_lock(&data->data_lock);
-       ret = limit_store(dev, count, index, data->temperature_limits[index],
+       ret = limit_write(dev, index, data->temperature_limits[index],
                          humidity);
        mutex_unlock(&data->data_lock);
 
@@ -474,7 +459,6 @@ static void sht3x_select_command(struct sht3x_data *data)
 }
 
 static int status_register_read(struct device *dev,
-                               struct device_attribute *attr,
                                char *buffer, int length)
 {
        int ret;
@@ -487,34 +471,30 @@ static int status_register_read(struct device *dev,
        return ret;
 }
 
-static ssize_t temp1_alarm_show(struct device *dev,
-                               struct device_attribute *attr,
-                               char *buf)
+static int temp1_alarm_read(struct device *dev)
 {
        char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
        int ret;
 
-       ret = status_register_read(dev, attr, buffer,
+       ret = status_register_read(dev, buffer,
                                   SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
        if (ret)
                return ret;
 
-       return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04));
+       return !!(buffer[0] & 0x04);
 }
 
-static ssize_t humidity1_alarm_show(struct device *dev,
-                                   struct device_attribute *attr,
-                                   char *buf)
+static int humidity1_alarm_read(struct device *dev)
 {
        char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
        int ret;
 
-       ret = status_register_read(dev, attr, buffer,
+       ret = status_register_read(dev, buffer,
                                   SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
        if (ret)
                return ret;
 
-       return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08));
+       return !!(buffer[0] & 0x08);
 }
 
 static ssize_t heater_enable_show(struct device *dev,
@@ -524,7 +504,7 @@ static ssize_t heater_enable_show(struct device *dev,
        char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
        int ret;
 
-       ret = status_register_read(dev, attr, buffer,
+       ret = status_register_read(dev, buffer,
                                   SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
        if (ret)
                return ret;
@@ -560,39 +540,28 @@ static ssize_t heater_enable_store(struct device *dev,
        return ret;
 }
 
-static ssize_t update_interval_show(struct device *dev,
-                                   struct device_attribute *attr,
-                                   char *buf)
+static int update_interval_read(struct device *dev)
 {
        struct sht3x_data *data = dev_get_drvdata(dev);
 
-       return sysfs_emit(buf, "%u\n",
-                        mode_to_update_interval[data->mode]);
+       return mode_to_update_interval[data->mode];
 }
 
-static ssize_t update_interval_store(struct device *dev,
-                                    struct device_attribute *attr,
-                                    const char *buf,
-                                    size_t count)
+static int update_interval_write(struct device *dev, int val)
 {
-       u16 update_interval;
        u8 mode;
        int ret;
        const char *command;
        struct sht3x_data *data = dev_get_drvdata(dev);
        struct i2c_client *client = data->client;
 
-       ret = kstrtou16(buf, 0, &update_interval);
-       if (ret)
-               return ret;
-
-       mode = get_mode_from_update_interval(update_interval);
+       mode = get_mode_from_update_interval(val);
 
        mutex_lock(&data->data_lock);
        /* mode did not change */
        if (mode == data->mode) {
                mutex_unlock(&data->data_lock);
-               return count;
+               return 0;
        }
 
        mutex_lock(&data->i2c_lock);
@@ -634,7 +603,7 @@ out:
        if (ret != SHT3X_CMD_LENGTH)
                return ret < 0 ? ret : -EIO;
 
-       return count;
+       return 0;
 }
 
 static ssize_t repeatability_show(struct device *dev,
@@ -668,60 +637,219 @@ static ssize_t repeatability_store(struct device *dev,
        return count;
 }
 
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0);
-static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0);
-static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max);
-static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max);
-static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst);
-static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit,
-                            limit_max_hyst);
-static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min);
-static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min);
-static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst);
-static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit,
-                            limit_min_hyst);
-static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0);
-static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0);
 static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0);
-static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0);
 static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0);
 
 static struct attribute *sht3x_attrs[] = {
-       &sensor_dev_attr_temp1_input.dev_attr.attr,
-       &sensor_dev_attr_humidity1_input.dev_attr.attr,
-       &sensor_dev_attr_temp1_max.dev_attr.attr,
-       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
-       &sensor_dev_attr_humidity1_max.dev_attr.attr,
-       &sensor_dev_attr_humidity1_max_hyst.dev_attr.attr,
-       &sensor_dev_attr_temp1_min.dev_attr.attr,
-       &sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
-       &sensor_dev_attr_humidity1_min.dev_attr.attr,
-       &sensor_dev_attr_humidity1_min_hyst.dev_attr.attr,
-       &sensor_dev_attr_temp1_alarm.dev_attr.attr,
-       &sensor_dev_attr_humidity1_alarm.dev_attr.attr,
        &sensor_dev_attr_heater_enable.dev_attr.attr,
-       &sensor_dev_attr_update_interval.dev_attr.attr,
        &sensor_dev_attr_repeatability.dev_attr.attr,
        NULL
 };
 
-static struct attribute *sts3x_attrs[] = {
-       &sensor_dev_attr_temp1_input.dev_attr.attr,
-       &sensor_dev_attr_temp1_max.dev_attr.attr,
-       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
-       &sensor_dev_attr_temp1_min.dev_attr.attr,
-       &sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
-       &sensor_dev_attr_temp1_alarm.dev_attr.attr,
-       &sensor_dev_attr_heater_enable.dev_attr.attr,
-       &sensor_dev_attr_update_interval.dev_attr.attr,
-       &sensor_dev_attr_repeatability.dev_attr.attr,
-       NULL
+ATTRIBUTE_GROUPS(sht3x);
+
+static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type,
+                               u32 attr, int channel)
+{
+       const struct sht3x_data *chip_data = data;
+
+       switch (type) {
+       case hwmon_chip:
+               switch (attr) {
+               case hwmon_chip_update_interval:
+                       return 0644;
+               default:
+                       break;
+               }
+               break;
+       case hwmon_temp:
+               switch (attr) {
+               case hwmon_temp_input:
+               case hwmon_temp_alarm:
+                       return 0444;
+               case hwmon_temp_max:
+               case hwmon_temp_max_hyst:
+               case hwmon_temp_min:
+               case hwmon_temp_min_hyst:
+                       return 0644;
+               default:
+                       break;
+               }
+               break;
+       case hwmon_humidity:
+               if (chip_data->chip_id == sts3x)
+                       break;
+               switch (attr) {
+               case hwmon_humidity_input:
+               case hwmon_humidity_alarm:
+                       return 0444;
+               case hwmon_humidity_max:
+               case hwmon_humidity_max_hyst:
+               case hwmon_humidity_min:
+               case hwmon_humidity_min_hyst:
+                       return 0644;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int sht3x_read(struct device *dev, enum hwmon_sensor_types type,
+                     u32 attr, int channel, long *val)
+{
+       enum sht3x_limits index;
+
+       switch (type) {
+       case hwmon_chip:
+               switch (attr) {
+               case hwmon_chip_update_interval:
+                       *val = update_interval_read(dev);
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+               break;
+       case hwmon_temp:
+               switch (attr) {
+               case hwmon_temp_input:
+                       *val = temp1_input_read(dev);
+                       break;
+               case hwmon_temp_alarm:
+                       *val = temp1_alarm_read(dev);
+                       break;
+               case hwmon_temp_max:
+                       index = limit_max;
+                       *val = temp1_limit_read(dev, index);
+                       break;
+               case hwmon_temp_max_hyst:
+                       index = limit_max_hyst;
+                       *val = temp1_limit_read(dev, index);
+                       break;
+               case hwmon_temp_min:
+                       index = limit_min;
+                       *val = temp1_limit_read(dev, index);
+                       break;
+               case hwmon_temp_min_hyst:
+                       index = limit_min_hyst;
+                       *val = temp1_limit_read(dev, index);
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+               break;
+       case hwmon_humidity:
+               switch (attr) {
+               case hwmon_humidity_input:
+                       *val = humidity1_input_read(dev);
+                       break;
+               case hwmon_humidity_alarm:
+                       *val = humidity1_alarm_read(dev);
+                       break;
+               case hwmon_humidity_max:
+                       index = limit_max;
+                       *val = humidity1_limit_read(dev, index);
+                       break;
+               case hwmon_humidity_max_hyst:
+                       index = limit_max_hyst;
+                       *val = humidity1_limit_read(dev, index);
+                       break;
+               case hwmon_humidity_min:
+                       index = limit_min;
+                       *val = humidity1_limit_read(dev, index);
+                       break;
+               case hwmon_humidity_min_hyst:
+                       index = limit_min_hyst;
+                       *val = humidity1_limit_read(dev, index);
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int sht3x_write(struct device *dev, enum hwmon_sensor_types type,
+                      u32 attr, int channel, long val)
+{
+       enum sht3x_limits index;
+
+       switch (type) {
+       case hwmon_chip:
+               switch (attr) {
+               case hwmon_chip_update_interval:
+                       return update_interval_write(dev, val);
+               default:
+                       return -EOPNOTSUPP;
+               }
+       case hwmon_temp:
+               switch (attr) {
+               case hwmon_temp_max:
+                       index = limit_max;
+                       break;
+               case hwmon_temp_max_hyst:
+                       index = limit_max_hyst;
+                       break;
+               case hwmon_temp_min:
+                       index = limit_min;
+                       break;
+               case hwmon_temp_min_hyst:
+                       index = limit_min_hyst;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+               return temp1_limit_write(dev, index, val);
+       case hwmon_humidity:
+               switch (attr) {
+               case hwmon_humidity_max:
+                       index = limit_max;
+                       break;
+               case hwmon_humidity_max_hyst:
+                       index = limit_max_hyst;
+                       break;
+               case hwmon_humidity_min:
+                       index = limit_min;
+                       break;
+               case hwmon_humidity_min_hyst:
+                       index = limit_min_hyst;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+               return humidity1_limit_write(dev, index, val);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static const struct hwmon_ops sht3x_ops = {
+       .is_visible = sht3x_is_visible,
+       .read = sht3x_read,
+       .write = sht3x_write,
 };
 
-ATTRIBUTE_GROUPS(sht3x);
-ATTRIBUTE_GROUPS(sts3x);
+static const struct hwmon_chip_info sht3x_chip_info = {
+       .ops = &sht3x_ops,
+       .info = sht3x_channel_info,
+};
+
+/* device ID table */
+static const struct i2c_device_id sht3x_ids[] = {
+       {"sht3x", sht3x},
+       {"sts3x", sts3x},
+       {}
+};
 
-static const struct i2c_device_id sht3x_ids[];
+MODULE_DEVICE_TABLE(i2c, sht3x_ids);
 
 static int sht3x_probe(struct i2c_client *client)
 {
@@ -730,7 +858,6 @@ static int sht3x_probe(struct i2c_client *client)
        struct device *hwmon_dev;
        struct i2c_adapter *adap = client->adapter;
        struct device *dev = &client->dev;
-       const struct attribute_group **attribute_groups;
 
        /*
         * we require full i2c support since the sht3x uses multi-byte read and
@@ -753,6 +880,7 @@ static int sht3x_probe(struct i2c_client *client)
        data->mode = 0;
        data->last_update = jiffies - msecs_to_jiffies(3000);
        data->client = client;
+       data->chip_id = i2c_match_id(sht3x_ids, client)->driver_data;
        crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
 
        sht3x_select_command(data);
@@ -771,15 +899,11 @@ static int sht3x_probe(struct i2c_client *client)
        if (ret)
                return ret;
 
-       if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x)
-               attribute_groups = sts3x_groups;
-       else
-               attribute_groups = sht3x_groups;
-
-       hwmon_dev = devm_hwmon_device_register_with_groups(dev,
-                                                          client->name,
-                                                          data,
-                                                          attribute_groups);
+       hwmon_dev = devm_hwmon_device_register_with_info(dev,
+                                                        client->name,
+                                                        data,
+                                                        &sht3x_chip_info,
+                                                        sht3x_groups);
 
        if (IS_ERR(hwmon_dev))
                dev_dbg(dev, "unable to register hwmon device\n");
@@ -787,15 +911,6 @@ static int sht3x_probe(struct i2c_client *client)
        return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-/* device ID table */
-static const struct i2c_device_id sht3x_ids[] = {
-       {"sht3x", sht3x},
-       {"sts3x", sts3x},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, sht3x_ids);
-
 static struct i2c_driver sht3x_i2c_driver = {
        .driver.name = "sht3x",
        .probe       = sht3x_probe,
index b0b05fd..0a04795 100644 (file)
@@ -798,7 +798,7 @@ static int sis5595_pci_probe(struct pci_dev *dev,
 {
        u16 address;
        u8 enable;
-       int *i;
+       int *i, err;
 
        for (i = blacklist; *i != 0; i++) {
                struct pci_dev *d;
@@ -818,8 +818,8 @@ static int sis5595_pci_probe(struct pci_dev *dev,
                pci_write_config_word(dev, SIS5595_BASE_REG, force_addr);
        }
 
-       if (PCIBIOS_SUCCESSFUL !=
-           pci_read_config_word(dev, SIS5595_BASE_REG, &address)) {
+       err = pci_read_config_word(dev, SIS5595_BASE_REG, &address);
+       if (err != PCIBIOS_SUCCESSFUL) {
                dev_err(&dev->dev, "Failed to read ISA address\n");
                return -ENODEV;
        }
@@ -836,22 +836,23 @@ static int sis5595_pci_probe(struct pci_dev *dev,
                return -ENODEV;
        }
 
-       if (PCIBIOS_SUCCESSFUL !=
-           pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) {
+       err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable);
+       if (err != PCIBIOS_SUCCESSFUL) {
                dev_err(&dev->dev, "Failed to read enable register\n");
                return -ENODEV;
        }
        if (!(enable & 0x80)) {
-               if ((PCIBIOS_SUCCESSFUL !=
-                    pci_write_config_byte(dev, SIS5595_ENABLE_REG,
-                                          enable | 0x80))
-                || (PCIBIOS_SUCCESSFUL !=
-                    pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable))
-                || (!(enable & 0x80))) {
-                       /* doesn't work for some chips! */
-                       dev_err(&dev->dev, "Failed to enable HWM device\n");
-                       return -ENODEV;
-               }
+               err = pci_write_config_byte(dev, SIS5595_ENABLE_REG, enable | 0x80);
+               if (err != PCIBIOS_SUCCESSFUL)
+                       goto enable_fail;
+
+               err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable);
+               if (err != PCIBIOS_SUCCESSFUL)
+                       goto enable_fail;
+
+               /* doesn't work for some chips! */
+               if (!(enable & 0x80))
+                       goto enable_fail;
        }
 
        if (platform_driver_register(&sis5595_driver)) {
@@ -871,6 +872,10 @@ static int sis5595_pci_probe(struct pci_dev *dev,
         */
        return -ENODEV;
 
+enable_fail:
+       dev_err(&dev->dev, "Failed to enable HWM device\n");
+       goto exit;
+
 exit_unregister:
        pci_dev_put(dev);
        platform_driver_unregister(&sis5595_driver);
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
deleted file mode 100644 (file)
index 026c76f..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for SMM665 Power Controller / Monitor
- *
- * Copyright (C) 2010 Ericsson AB.
- *
- * This driver should also work for SMM465, SMM764, and SMM766, but is untested
- * for those chips. Only monitoring functionality is implemented.
- *
- * Datasheets:
- * http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
- * http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-
-/* Internal reference voltage (VREF, x 1000 */
-#define SMM665_VREF_ADC_X1000  1250
-
-/* module parameters */
-static int vref = SMM665_VREF_ADC_X1000;
-module_param(vref, int, 0);
-MODULE_PARM_DESC(vref, "Reference voltage in mV");
-
-enum chips { smm465, smm665, smm665c, smm764, smm766 };
-
-/*
- * ADC channel addresses
- */
-#define        SMM665_MISC16_ADC_DATA_A        0x00
-#define        SMM665_MISC16_ADC_DATA_B        0x01
-#define        SMM665_MISC16_ADC_DATA_C        0x02
-#define        SMM665_MISC16_ADC_DATA_D        0x03
-#define        SMM665_MISC16_ADC_DATA_E        0x04
-#define        SMM665_MISC16_ADC_DATA_F        0x05
-#define        SMM665_MISC16_ADC_DATA_VDD      0x06
-#define        SMM665_MISC16_ADC_DATA_12V      0x07
-#define        SMM665_MISC16_ADC_DATA_INT_TEMP 0x08
-#define        SMM665_MISC16_ADC_DATA_AIN1     0x09
-#define        SMM665_MISC16_ADC_DATA_AIN2     0x0a
-
-/*
- * Command registers
- */
-#define        SMM665_MISC8_CMD_STS            0x80
-#define        SMM665_MISC8_STATUS1            0x81
-#define        SMM665_MISC8_STATUSS2           0x82
-#define        SMM665_MISC8_IO_POLARITY        0x83
-#define        SMM665_MISC8_PUP_POLARITY       0x84
-#define        SMM665_MISC8_ADOC_STATUS1       0x85
-#define        SMM665_MISC8_ADOC_STATUS2       0x86
-#define        SMM665_MISC8_WRITE_PROT         0x87
-#define        SMM665_MISC8_STS_TRACK          0x88
-
-/*
- * Configuration registers and register groups
- */
-#define SMM665_ADOC_ENABLE             0x0d
-#define SMM665_LIMIT_BASE              0x80    /* First limit register */
-
-/*
- * Limit register bit masks
- */
-#define SMM665_TRIGGER_RST             0x8000
-#define SMM665_TRIGGER_HEALTHY         0x4000
-#define SMM665_TRIGGER_POWEROFF                0x2000
-#define SMM665_TRIGGER_SHUTDOWN                0x1000
-#define SMM665_ADC_MASK                        0x03ff
-
-#define smm665_is_critical(lim)        ((lim) & (SMM665_TRIGGER_RST \
-                                       | SMM665_TRIGGER_POWEROFF \
-                                       | SMM665_TRIGGER_SHUTDOWN))
-/*
- * Fault register bit definitions
- * Values are merged from status registers 1/2,
- * with status register 1 providing the upper 8 bits.
- */
-#define SMM665_FAULT_A         0x0001
-#define SMM665_FAULT_B         0x0002
-#define SMM665_FAULT_C         0x0004
-#define SMM665_FAULT_D         0x0008
-#define SMM665_FAULT_E         0x0010
-#define SMM665_FAULT_F         0x0020
-#define SMM665_FAULT_VDD       0x0040
-#define SMM665_FAULT_12V       0x0080
-#define SMM665_FAULT_TEMP      0x0100
-#define SMM665_FAULT_AIN1      0x0200
-#define SMM665_FAULT_AIN2      0x0400
-
-/*
- * I2C Register addresses
- *
- * The configuration register needs to be the configured base register.
- * The command/status register address is derived from it.
- */
-#define SMM665_REGMASK         0x78
-#define SMM665_CMDREG_BASE     0x48
-#define SMM665_CONFREG_BASE    0x50
-
-/*
- *  Equations given by chip manufacturer to calculate voltage/temperature values
- *  vref = Reference voltage on VREF_ADC pin (module parameter)
- *  adc  = 10bit ADC value read back from registers
- */
-
-/* Voltage A-F and VDD */
-#define SMM665_VMON_ADC_TO_VOLTS(adc)  ((adc) * vref / 256)
-
-/* Voltage 12VIN */
-#define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256)
-
-/* Voltage AIN1, AIN2 */
-#define SMM665_AIN_ADC_TO_VOLTS(adc)   ((adc) * vref / 512)
-
-/* Temp Sensor */
-#define SMM665_TEMP_ADC_TO_CELSIUS(adc) (((adc) <= 511) ?                 \
-                                        ((int)(adc) * 1000 / 4) :         \
-                                        (((int)(adc) - 0x400) * 1000 / 4))
-
-#define SMM665_NUM_ADC         11
-
-/*
- * Chip dependent ADC conversion time, in uS
- */
-#define SMM665_ADC_WAIT_SMM665 70
-#define SMM665_ADC_WAIT_SMM766 185
-
-struct smm665_data {
-       enum chips type;
-       int conversion_time;            /* ADC conversion time */
-       struct i2c_client *client;
-       struct mutex update_lock;
-       bool valid;
-       unsigned long last_updated;     /* in jiffies */
-       u16 adc[SMM665_NUM_ADC];        /* adc values (raw) */
-       u16 faults;                     /* fault status */
-       /* The following values are in mV */
-       int critical_min_limit[SMM665_NUM_ADC];
-       int alarm_min_limit[SMM665_NUM_ADC];
-       int critical_max_limit[SMM665_NUM_ADC];
-       int alarm_max_limit[SMM665_NUM_ADC];
-       struct i2c_client *cmdreg;
-};
-
-/*
- * smm665_read16()
- *
- * Read 16 bit value from <reg>, <reg+1>. Upper 8 bits are in <reg>.
- */
-static int smm665_read16(struct i2c_client *client, int reg)
-{
-       int rv, val;
-
-       rv = i2c_smbus_read_byte_data(client, reg);
-       if (rv < 0)
-               return rv;
-       val = rv << 8;
-       rv = i2c_smbus_read_byte_data(client, reg + 1);
-       if (rv < 0)
-               return rv;
-       val |= rv;
-       return val;
-}
-
-/*
- * Read adc value.
- */
-static int smm665_read_adc(struct smm665_data *data, int adc)
-{
-       struct i2c_client *client = data->cmdreg;
-       int rv;
-       int radc;
-
-       /*
-        * Algorithm for reading ADC, per SMM665 datasheet
-        *
-        *  {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]}
-        * [wait conversion time]
-        *  {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]}
-        *
-        * To implement the first part of this exchange,
-        * do a full read transaction and expect a failure/Nack.
-        * This sets up the address pointer on the SMM665
-        * and starts the ADC conversion.
-        * Then do a two-byte read transaction.
-        */
-       rv = i2c_smbus_read_byte_data(client, adc << 3);
-       if (rv != -ENXIO) {
-               /*
-                * We expect ENXIO to reflect NACK
-                * (per Documentation/i2c/fault-codes.rst).
-                * Everything else is an error.
-                */
-               dev_dbg(&client->dev,
-                       "Unexpected return code %d when setting ADC index", rv);
-               return (rv < 0) ? rv : -EIO;
-       }
-
-       udelay(data->conversion_time);
-
-       /*
-        * Now read two bytes.
-        *
-        * Neither i2c_smbus_read_byte() nor
-        * i2c_smbus_read_block_data() worked here,
-        * so use i2c_smbus_read_word_swapped() instead.
-        * We could also try to use i2c_master_recv(),
-        * but that is not always supported.
-        */
-       rv = i2c_smbus_read_word_swapped(client, 0);
-       if (rv < 0) {
-               dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
-               return rv;
-       }
-       /*
-        * Validate/verify readback adc channel (in bit 11..14).
-        */
-       radc = (rv >> 11) & 0x0f;
-       if (radc != adc) {
-               dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
-                       adc, radc);
-               return -EIO;
-       }
-
-       return rv & SMM665_ADC_MASK;
-}
-
-static struct smm665_data *smm665_update_device(struct device *dev)
-{
-       struct smm665_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = data->client;
-       struct smm665_data *ret = data;
-
-       mutex_lock(&data->update_lock);
-
-       if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-               int i, val;
-
-               /*
-                * read status registers
-                */
-               val = smm665_read16(client, SMM665_MISC8_STATUS1);
-               if (unlikely(val < 0)) {
-                       ret = ERR_PTR(val);
-                       goto abort;
-               }
-               data->faults = val;
-
-               /* Read adc registers */
-               for (i = 0; i < SMM665_NUM_ADC; i++) {
-                       val = smm665_read_adc(data, i);
-                       if (unlikely(val < 0)) {
-                               ret = ERR_PTR(val);
-                               goto abort;
-                       }
-                       data->adc[i] = val;
-               }
-               data->last_updated = jiffies;
-               data->valid = true;
-       }
-abort:
-       mutex_unlock(&data->update_lock);
-       return ret;
-}
-
-/* Return converted value from given adc */
-static int smm665_convert(u16 adcval, int index)
-{
-       int val = 0;
-
-       switch (index) {
-       case SMM665_MISC16_ADC_DATA_12V:
-               val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
-               break;
-
-       case SMM665_MISC16_ADC_DATA_VDD:
-       case SMM665_MISC16_ADC_DATA_A:
-       case SMM665_MISC16_ADC_DATA_B:
-       case SMM665_MISC16_ADC_DATA_C:
-       case SMM665_MISC16_ADC_DATA_D:
-       case SMM665_MISC16_ADC_DATA_E:
-       case SMM665_MISC16_ADC_DATA_F:
-               val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
-               break;
-
-       case SMM665_MISC16_ADC_DATA_AIN1:
-       case SMM665_MISC16_ADC_DATA_AIN2:
-               val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
-               break;
-
-       case SMM665_MISC16_ADC_DATA_INT_TEMP:
-               val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK);
-               break;
-
-       default:
-               /* If we get here, the developer messed up */
-               WARN_ON_ONCE(1);
-               break;
-       }
-
-       return val;
-}
-
-static int smm665_get_min(struct device *dev, int index)
-{
-       struct smm665_data *data = dev_get_drvdata(dev);
-
-       return data->alarm_min_limit[index];
-}
-
-static int smm665_get_max(struct device *dev, int index)
-{
-       struct smm665_data *data = dev_get_drvdata(dev);
-
-       return data->alarm_max_limit[index];
-}
-
-static int smm665_get_lcrit(struct device *dev, int index)
-{
-       struct smm665_data *data = dev_get_drvdata(dev);
-
-       return data->critical_min_limit[index];
-}
-
-static int smm665_get_crit(struct device *dev, int index)
-{
-       struct smm665_data *data = dev_get_drvdata(dev);
-
-       return data->critical_max_limit[index];
-}
-
-static ssize_t smm665_show_crit_alarm(struct device *dev,
-                                     struct device_attribute *da, char *buf)
-{
-       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-       struct smm665_data *data = smm665_update_device(dev);
-       int val = 0;
-
-       if (IS_ERR(data))
-               return PTR_ERR(data);
-
-       if (data->faults & (1 << attr->index))
-               val = 1;
-
-       return sysfs_emit(buf, "%d\n", val);
-}
-
-static ssize_t smm665_show_input(struct device *dev,
-                                struct device_attribute *da, char *buf)
-{
-       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-       struct smm665_data *data = smm665_update_device(dev);
-       int adc = attr->index;
-       int val;
-
-       if (IS_ERR(data))
-               return PTR_ERR(data);
-
-       val = smm665_convert(data->adc[adc], adc);
-       return sysfs_emit(buf, "%d\n", val);
-}
-
-#define SMM665_SHOW(what) \
-static ssize_t smm665_show_##what(struct device *dev, \
-                                   struct device_attribute *da, char *buf) \
-{ \
-       struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
-       const int val = smm665_get_##what(dev, attr->index); \
-       return snprintf(buf, PAGE_SIZE, "%d\n", val); \
-}
-
-SMM665_SHOW(min);
-SMM665_SHOW(max);
-SMM665_SHOW(lcrit);
-SMM665_SHOW(crit);
-
-/*
- * These macros are used below in constructing device attribute objects
- * for use with sysfs_create_group() to make a sysfs device file
- * for each register.
- */
-
-#define SMM665_ATTR(name, type, cmd_idx) \
-       static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \
-                                 smm665_show_##type, NULL, cmd_idx)
-
-/* Construct a sensor_device_attribute structure for each register */
-
-/* Input voltages */
-SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages min */
-SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages max */
-SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages lcrit */
-SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages crit */
-SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* critical alarms */
-SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V);
-SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD);
-SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A);
-SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B);
-SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C);
-SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D);
-SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E);
-SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F);
-SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1);
-SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2);
-
-/* Temperature */
-SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP);
-
-/*
- * Finally, construct an array of pointers to members of the above objects,
- * as required for sysfs_create_group()
- */
-static struct attribute *smm665_attrs[] = {
-       &sensor_dev_attr_in1_input.dev_attr.attr,
-       &sensor_dev_attr_in1_min.dev_attr.attr,
-       &sensor_dev_attr_in1_max.dev_attr.attr,
-       &sensor_dev_attr_in1_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in1_crit.dev_attr.attr,
-       &sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in2_input.dev_attr.attr,
-       &sensor_dev_attr_in2_min.dev_attr.attr,
-       &sensor_dev_attr_in2_max.dev_attr.attr,
-       &sensor_dev_attr_in2_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in2_crit.dev_attr.attr,
-       &sensor_dev_attr_in2_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in3_input.dev_attr.attr,
-       &sensor_dev_attr_in3_min.dev_attr.attr,
-       &sensor_dev_attr_in3_max.dev_attr.attr,
-       &sensor_dev_attr_in3_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in3_crit.dev_attr.attr,
-       &sensor_dev_attr_in3_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in4_input.dev_attr.attr,
-       &sensor_dev_attr_in4_min.dev_attr.attr,
-       &sensor_dev_attr_in4_max.dev_attr.attr,
-       &sensor_dev_attr_in4_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in4_crit.dev_attr.attr,
-       &sensor_dev_attr_in4_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in5_input.dev_attr.attr,
-       &sensor_dev_attr_in5_min.dev_attr.attr,
-       &sensor_dev_attr_in5_max.dev_attr.attr,
-       &sensor_dev_attr_in5_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in5_crit.dev_attr.attr,
-       &sensor_dev_attr_in5_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in6_input.dev_attr.attr,
-       &sensor_dev_attr_in6_min.dev_attr.attr,
-       &sensor_dev_attr_in6_max.dev_attr.attr,
-       &sensor_dev_attr_in6_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in6_crit.dev_attr.attr,
-       &sensor_dev_attr_in6_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in7_input.dev_attr.attr,
-       &sensor_dev_attr_in7_min.dev_attr.attr,
-       &sensor_dev_attr_in7_max.dev_attr.attr,
-       &sensor_dev_attr_in7_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in7_crit.dev_attr.attr,
-       &sensor_dev_attr_in7_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in8_input.dev_attr.attr,
-       &sensor_dev_attr_in8_min.dev_attr.attr,
-       &sensor_dev_attr_in8_max.dev_attr.attr,
-       &sensor_dev_attr_in8_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in8_crit.dev_attr.attr,
-       &sensor_dev_attr_in8_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in9_input.dev_attr.attr,
-       &sensor_dev_attr_in9_min.dev_attr.attr,
-       &sensor_dev_attr_in9_max.dev_attr.attr,
-       &sensor_dev_attr_in9_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in9_crit.dev_attr.attr,
-       &sensor_dev_attr_in9_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_in10_input.dev_attr.attr,
-       &sensor_dev_attr_in10_min.dev_attr.attr,
-       &sensor_dev_attr_in10_max.dev_attr.attr,
-       &sensor_dev_attr_in10_lcrit.dev_attr.attr,
-       &sensor_dev_attr_in10_crit.dev_attr.attr,
-       &sensor_dev_attr_in10_crit_alarm.dev_attr.attr,
-
-       &sensor_dev_attr_temp1_input.dev_attr.attr,
-       &sensor_dev_attr_temp1_min.dev_attr.attr,
-       &sensor_dev_attr_temp1_max.dev_attr.attr,
-       &sensor_dev_attr_temp1_lcrit.dev_attr.attr,
-       &sensor_dev_attr_temp1_crit.dev_attr.attr,
-       &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
-
-       NULL,
-};
-
-ATTRIBUTE_GROUPS(smm665);
-
-static const struct i2c_device_id smm665_id[];
-
-static int smm665_probe(struct i2c_client *client)
-{
-       struct i2c_adapter *adapter = client->adapter;
-       struct smm665_data *data;
-       struct device *hwmon_dev;
-       int i, ret;
-
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
-                                    | I2C_FUNC_SMBUS_WORD_DATA))
-               return -ENODEV;
-
-       if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0)
-               return -ENODEV;
-
-       data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       i2c_set_clientdata(client, data);
-       mutex_init(&data->update_lock);
-
-       data->client = client;
-       data->type = i2c_match_id(smm665_id, client)->driver_data;
-       data->cmdreg = i2c_new_dummy_device(adapter, (client->addr & ~SMM665_REGMASK)
-                                    | SMM665_CMDREG_BASE);
-       if (IS_ERR(data->cmdreg))
-               return PTR_ERR(data->cmdreg);
-
-       switch (data->type) {
-       case smm465:
-       case smm665:
-               data->conversion_time = SMM665_ADC_WAIT_SMM665;
-               break;
-       case smm665c:
-       case smm764:
-       case smm766:
-               data->conversion_time = SMM665_ADC_WAIT_SMM766;
-               break;
-       }
-
-       ret = -ENODEV;
-       if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0)
-               goto out_unregister;
-
-       /*
-        * Read limits.
-        *
-        * Limit registers start with register SMM665_LIMIT_BASE.
-        * Each channel uses 8 registers, providing four limit values
-        * per channel. Each limit value requires two registers, with the
-        * high byte in the first register and the low byte in the second
-        * register. The first two limits are under limit values, followed
-        * by two over limit values.
-        *
-        * Limit register order matches the ADC register order, so we use
-        * ADC register defines throughout the code to index limit registers.
-        *
-        * We save the first retrieved value both as "critical" and "alarm"
-        * value. The second value overwrites either the critical or the
-        * alarm value, depending on its configuration. This ensures that both
-        * critical and alarm values are initialized, even if both registers are
-        * configured as critical or non-critical.
-        */
-       for (i = 0; i < SMM665_NUM_ADC; i++) {
-               int val;
-
-               val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8);
-               if (unlikely(val < 0))
-                       goto out_unregister;
-               data->critical_min_limit[i] = data->alarm_min_limit[i]
-                 = smm665_convert(val, i);
-               val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2);
-               if (unlikely(val < 0))
-                       goto out_unregister;
-               if (smm665_is_critical(val))
-                       data->critical_min_limit[i] = smm665_convert(val, i);
-               else
-                       data->alarm_min_limit[i] = smm665_convert(val, i);
-               val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4);
-               if (unlikely(val < 0))
-                       goto out_unregister;
-               data->critical_max_limit[i] = data->alarm_max_limit[i]
-                 = smm665_convert(val, i);
-               val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6);
-               if (unlikely(val < 0))
-                       goto out_unregister;
-               if (smm665_is_critical(val))
-                       data->critical_max_limit[i] = smm665_convert(val, i);
-               else
-                       data->alarm_max_limit[i] = smm665_convert(val, i);
-       }
-
-       hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
-                                                          client->name, data,
-                                                          smm665_groups);
-       if (IS_ERR(hwmon_dev)) {
-               ret = PTR_ERR(hwmon_dev);
-               goto out_unregister;
-       }
-
-       return 0;
-
-out_unregister:
-       i2c_unregister_device(data->cmdreg);
-       return ret;
-}
-
-static void smm665_remove(struct i2c_client *client)
-{
-       struct smm665_data *data = i2c_get_clientdata(client);
-
-       i2c_unregister_device(data->cmdreg);
-}
-
-static const struct i2c_device_id smm665_id[] = {
-       {"smm465", smm465},
-       {"smm665", smm665},
-       {"smm665c", smm665c},
-       {"smm764", smm764},
-       {"smm766", smm766},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, smm665_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver smm665_driver = {
-       .driver = {
-                  .name = "smm665",
-                  },
-       .probe = smm665_probe,
-       .remove = smm665_remove,
-       .id_table = smm665_id,
-};
-
-module_i2c_driver(smm665_driver);
-
-MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("SMM665 driver");
-MODULE_LICENSE("GPL");
index 3cde391..10b66c9 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/sysfs.h>
 
 /* Addresses to scan */
index 4b79c3f..f58ca4c 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
index bff10f4..9a180b1 100644 (file)
@@ -434,7 +434,7 @@ static umode_t tmp51x_is_visible(const void *_data,
 
        switch (type) {
        case hwmon_temp:
-               if (data->id == tmp512 && channel == 4)
+               if (data->id == tmp512 && channel == 3)
                        return 0;
                switch (attr) {
                case hwmon_temp_input:
@@ -720,10 +720,7 @@ static int tmp51x_probe(struct i2c_client *client)
        if (!data)
                return -ENOMEM;
 
-       if (client->dev.of_node)
-               data->id = (enum tmp51x_ids)device_get_match_data(&client->dev);
-       else
-               data->id = i2c_match_id(tmp51x_id, client)->driver_data;
+       data->id = (uintptr_t)i2c_get_match_data(client);
 
        ret = tmp51x_configure(dev, data);
        if (ret < 0) {
index 8fbbb29..d33ecba 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/hwmon.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 
 #define TEMPERATURE                    0x2c
index b23cff2..3b580f2 100644 (file)
@@ -9,7 +9,8 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
index 2ac5fb9..d82a3b4 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/vexpress.h>
 
index 37d7374..407933d 100644 (file)
@@ -855,16 +855,17 @@ static int via686a_pci_probe(struct pci_dev *dev,
                                       const struct pci_device_id *id)
 {
        u16 address, val;
+       int ret;
 
        if (force_addr) {
                address = force_addr & ~(VIA686A_EXTENT - 1);
                dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
-               if (PCIBIOS_SUCCESSFUL !=
-                   pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
+               ret = pci_write_config_word(dev, VIA686A_BASE_REG, address | 1);
+               if (ret != PCIBIOS_SUCCESSFUL)
                        return -ENODEV;
        }
-       if (PCIBIOS_SUCCESSFUL !=
-           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+       ret = pci_read_config_word(dev, VIA686A_BASE_REG, &val);
+       if (ret != PCIBIOS_SUCCESSFUL)
                return -ENODEV;
 
        address = val & ~(VIA686A_EXTENT - 1);
@@ -874,8 +875,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
                return -ENODEV;
        }
 
-       if (PCIBIOS_SUCCESSFUL !=
-           pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
+       ret = pci_read_config_word(dev, VIA686A_ENABLE_REG, &val);
+       if (ret != PCIBIOS_SUCCESSFUL)
                return -ENODEV;
        if (!(val & 0x0001)) {
                if (!force_addr) {
@@ -886,9 +887,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
                }
 
                dev_warn(&dev->dev, "Enabling sensors\n");
-               if (PCIBIOS_SUCCESSFUL !=
-                   pci_write_config_word(dev, VIA686A_ENABLE_REG,
-                                         val | 0x0001))
+               ret = pci_write_config_word(dev, VIA686A_ENABLE_REG, val | 0x1);
+               if (ret != PCIBIOS_SUCCESSFUL)
                        return -ENODEV;
        }
 
index b7c6392..16bc16d 100644 (file)
@@ -971,13 +971,15 @@ static int vt8231_pci_probe(struct pci_dev *dev,
                                const struct pci_device_id *id)
 {
        u16 address, val;
+       int ret;
+
        if (force_addr) {
                address = force_addr & 0xff00;
                dev_warn(&dev->dev, "Forcing ISA address 0x%x\n",
                         address);
 
-               if (PCIBIOS_SUCCESSFUL !=
-                   pci_write_config_word(dev, VT8231_BASE_REG, address | 1))
+               ret = pci_write_config_word(dev, VT8231_BASE_REG, address | 1);
+               if (ret != PCIBIOS_SUCCESSFUL)
                        return -ENODEV;
        }
 
@@ -997,9 +999,8 @@ static int vt8231_pci_probe(struct pci_dev *dev,
 
        if (!(val & 0x0001)) {
                dev_warn(&dev->dev, "enabling sensors\n");
-               if (PCIBIOS_SUCCESSFUL !=
-                       pci_write_config_word(dev, VT8231_ENABLE_REG,
-                                                       val | 0x0001))
+               ret = pci_write_config_word(dev, VT8231_ENABLE_REG, val | 0x1);
+               if (ret != PCIBIOS_SUCCESSFUL)
                        return -ENODEV;
        }
 
index 7f3615f..045eea8 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 
 /* W83773 has 3 channels */