Merge tag 'hwmon-for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Oct 2018 23:58:12 +0000 (00:58 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Oct 2018 23:58:12 +0000 (00:58 +0100)
Pull hwmon updates from Guenter Roeck:

 - Add support for trace events to hwmon core

 - Add support for NCT6797D, NCT6798D, MAX31725/6, LTM4686

 - Support all AMD Family 15h Model 6xh and Model 7xh processors in
   k10temp driver

 - Convert ina3221 driver to _info API

 - Fixes, cleanups, and improvements in various drivers

* tag 'hwmon-for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (46 commits)
  hwmon: (pmbus) Fix page count auto-detection.
  hwmon: (pmbus) remove redundant 'default n' from Kconfig
  hwmon: (core) Add trace events to _attr_show/store functions
  hwmon: (ina3221) Use _info API to register hwmon device
  hwmon: (npcm-750-pwm-fan) Change initial pwm target to 255
  hwmon: (ina3221) Validate shunt resistor value from DT
  hwmon: (tmp421) make const array 'names' static
  hwmon: (core) Add hwmon_in_enable attribute
  hwmon: (ina3221) mark PM functions as __maybe_unused
  hwmon: (ina3221) Read channel input source info from DT
  dt-bindings: hwmon: Add ina3221 documentation
  hwmon: (ina3221) Add suspend and resume functions
  hwmon: (ina3221) Fix INA3221_CONFIG_MODE macros
  hwmon: (ina3221) Add INA3221_CONFIG to volatile_table
  MAINTAINERS: Update PMBUS maintainer entry
  hwmon: (pwm-fan) Set fan speed to 0 on suspend
  hwmon: (pwm-fan) Silence error on probe deferral
  hwmon: (scpi-hwmon) remove redundant continue
  hwmon: (nct6775) Add support for NCT6798D
  hwmon: (nct6775) Add support for NCT6797D
  ...

30 files changed:
Documentation/devicetree/bindings/hwmon/ina3221.txt [new file with mode: 0644]
Documentation/devicetree/bindings/hwmon/ltc2978.txt
Documentation/hwmon/ina3221
Documentation/hwmon/lm75
Documentation/hwmon/ltc2978
Documentation/hwmon/mc13783-adc
MAINTAINERS
drivers/hwmon/aspeed-pwm-tacho.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/hwmon.c
drivers/hwmon/ibmpowernv.c
drivers/hwmon/iio_hwmon.c
drivers/hwmon/ina3221.c
drivers/hwmon/k10temp.c
drivers/hwmon/lm75.c
drivers/hwmon/lm92.c
drivers/hwmon/mc13783-adc.c
drivers/hwmon/nct6775.c
drivers/hwmon/npcm750-pwm-fan.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/ltc2978.c
drivers/hwmon/pmbus/pmbus.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/pwm-fan.c
drivers/hwmon/scmi-hwmon.c
drivers/hwmon/scpi-hwmon.c
drivers/hwmon/sht15.c
drivers/hwmon/tmp421.c
include/linux/hwmon.h
include/trace/events/hwmon.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/hwmon/ina3221.txt b/Documentation/devicetree/bindings/hwmon/ina3221.txt
new file mode 100644 (file)
index 0000000..a7b25ca
--- /dev/null
@@ -0,0 +1,44 @@
+Texas Instruments INA3221 Device Tree Bindings
+
+1) ina3221 node
+  Required properties:
+  - compatible: Must be "ti,ina3221"
+  - reg: I2C address
+
+  Optional properties:
+  = The node contains optional child nodes for three channels =
+  = Each child node describes the information of input source =
+
+  - #address-cells: Required only if a child node is present. Must be 1.
+  - #size-cells: Required only if a child node is present. Must be 0.
+
+2) child nodes
+  Required properties:
+  - reg: Must be 0, 1 or 2, corresponding to IN1, IN2 or IN3 port of INA3221
+
+  Optional properties:
+  - label: Name of the input source
+  - shunt-resistor-micro-ohms: Shunt resistor value in micro-Ohm
+
+Example:
+
+ina3221@40 {
+       compatible = "ti,ina3221";
+       reg = <0x40>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       input@0 {
+               reg = <0x0>;
+               status = "disabled";
+       };
+       input@1 {
+               reg = <0x1>;
+               shunt-resistor-micro-ohms = <5000>;
+       };
+       input@2 {
+               reg = <0x2>;
+               label = "VDD_5V";
+               shunt-resistor-micro-ohms = <5000>;
+       };
+};
index bf2a47bbdc585547995d2084482899436de533d0..b428a70a7cc0a9021a6a5c91f98a1c43458b891f 100644 (file)
@@ -15,6 +15,7 @@ Required properties:
   * "lltc,ltm2987"
   * "lltc,ltm4675"
   * "lltc,ltm4676"
+  * "lltc,ltm4686"
 - reg: I2C slave address
 
 Optional properties:
@@ -30,6 +31,7 @@ Valid names of regulators depend on number of supplies supported per device:
   * ltc3880, ltc3882, ltc3886 : vout0 - vout1
   * ltc3883 : vout0
   * ltm4676 : vout0 - vout1
+  * ltm4686 : vout0 - vout1
 
 Example:
 ltc2978@5e {
index 0ff74854cb2e6dddf704a74f31027cd3225bb22e..4b82cbfb551c04b37ae9c2f5f647df2a609469ad 100644 (file)
@@ -21,6 +21,8 @@ and power are calculated host-side from these.
 Sysfs entries
 -------------
 
+in[123]_label           Voltage channel labels
+in[123]_enable          Voltage channel enable controls
 in[123]_input           Bus voltage(mV) channels
 curr[123]_input         Current(mA) measurement channels
 shunt[123]_resistor     Shunt resistance(uOhm) channels
index ac95edfcd907ccddcf2f7be7cf34944b0895ea94..2f1120f88c1658da907095522bbe4f571c279cac 100644 (file)
@@ -17,8 +17,8 @@ Supported chips:
     Addresses scanned: none
     Datasheet: Publicly available at the Maxim website
                http://www.maximintegrated.com/
-  * Maxim MAX6625, MAX6626
-    Prefixes: 'max6625', 'max6626'
+  * Maxim MAX6625, MAX6626, MAX31725, MAX31726
+    Prefixes: 'max6625', 'max6626', 'max31725', 'max31726'
     Addresses scanned: none
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/
@@ -86,7 +86,7 @@ The LM75 is essentially an industry standard; there may be other
 LM75 clones not listed here, with or without various enhancements,
 that are supported. The clones are not detected by the driver, unless
 they reproduce the exact register tricks of the original LM75, and must
-therefore be instantiated explicitly. Higher resolution up to 12-bit
+therefore be instantiated explicitly. Higher resolution up to 16-bit
 is supported by this driver, other specific enhancements are not.
 
 The LM77 is not supported, contrary to what we pretended for a long time.
index 9a49d3c90cd1a7f2a28b19f0850cdc2bd00dbbae..dfb2caa401d9cd2df83d94adacd98e928b49858c 100644 (file)
@@ -55,6 +55,10 @@ Supported chips:
     Prefix: 'ltm4676'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltm4676
+  * Analog Devices LTM4686
+    Prefix: 'ltm4686'
+    Addresses scanned: -
+    Datasheet: http://www.analog.com/ltm4686
 
 Author: Guenter Roeck <linux@roeck-us.net>
 
@@ -76,6 +80,7 @@ additional components on a single die. The chip is instantiated and reported
 as two separate chips on two different I2C bus addresses.
 LTM4675 is a dual 9A or single 18A μModule regulator
 LTM4676 is a dual 13A or single 26A uModule regulator.
+LTM4686 is a dual 10A or single 20A uModule regulator.
 
 
 Usage Notes
index d0e7b3fa9e7539943358efe698d27eedd6356851..05ccc9f159f1c01953a3a5c3ae58e4bad81e3929 100644 (file)
@@ -2,12 +2,12 @@ Kernel driver mc13783-adc
 =========================
 
 Supported chips:
-  * Freescale Atlas MC13783
+  * Freescale MC13783
     Prefix: 'mc13783'
-    Datasheet: http://www.freescale.com/files/rf_if/doc/data_sheet/MC13783.pdf?fsrch=1
-  * Freescale Atlas MC13892
+    Datasheet: https://www.nxp.com/docs/en/data-sheet/MC13783.pdf
+  * Freescale MC13892
     Prefix: 'mc13892'
-    Datasheet: http://cache.freescale.com/files/analog/doc/data_sheet/MC13892.pdf?fsrch=1&sr=1
+    Datasheet: https://www.nxp.com/docs/en/data-sheet/MC13892.pdf
 
 Authors:
     Sascha Hauer <s.hauer@pengutronix.de>
index c393746b020999228340b13f3f559ee9b6853654..c742c517f95c74e069700623c80e2e04405260c6 100644 (file)
@@ -6468,6 +6468,7 @@ F:        Documentation/devicetree/bindings/hwmon/
 F:     Documentation/hwmon/
 F:     drivers/hwmon/
 F:     include/linux/hwmon*.h
+F:     include/trace/events/hwmon*.h
 
 HARDWARE RANDOM NUMBER GENERATOR CORE
 M:     Matt Mackall <mpm@selenic.com>
@@ -8860,13 +8861,6 @@ S:       Maintained
 F:     Documentation/hwmon/max16065
 F:     drivers/hwmon/max16065.c
 
-MAX20751 HARDWARE MONITOR DRIVER
-M:     Guenter Roeck <linux@roeck-us.net>
-L:     linux-hwmon@vger.kernel.org
-S:     Maintained
-F:     Documentation/hwmon/max20751
-F:     drivers/hwmon/max20751.c
-
 MAX2175 SDR TUNER DRIVER
 M:     Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
 L:     linux-media@vger.kernel.org
@@ -11601,7 +11595,26 @@ W:     http://hwmon.wiki.kernel.org/
 W:     http://www.roeck-us.net/linux/drivers/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
 S:     Maintained
+F:     Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
+F:     Documentation/devicetree/bindings/hwmon/max31785.txt
+F:     Documentation/devicetree/bindings/hwmon/ltc2978.txt
+F:     Documentation/hwmon/adm1275
+F:     Documentation/hwmon/ibm-cffps
+F:     Documentation/hwmon/ir35221
+F:     Documentation/hwmon/lm25066
+F:     Documentation/hwmon/ltc2978
+F:     Documentation/hwmon/ltc3815
+F:     Documentation/hwmon/max16064
+F:     Documentation/hwmon/max20751
+F:     Documentation/hwmon/max31785
+F:     Documentation/hwmon/max34440
+F:     Documentation/hwmon/max8688
 F:     Documentation/hwmon/pmbus
+F:     Documentation/hwmon/pmbus-core
+F:     Documentation/hwmon/tps40422
+F:     Documentation/hwmon/ucd9000
+F:     Documentation/hwmon/ucd9200
+F:     Documentation/hwmon/zl6100
 F:     drivers/hwmon/pmbus/
 F:     include/linux/pmbus.h
 
index 5e449eac788a1311ee1f3be0c6ba7f91c9415964..92de8139d398beeb6079e58ec382b253dc759cee 100644 (file)
@@ -852,7 +852,7 @@ static int aspeed_create_pwm_cooling(struct device *dev,
                dev_err(dev, "Property 'cooling-levels' cannot be read.\n");
                return ret;
        }
-       snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%s%d", child->name, pwm_port);
+       snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%pOFn%d", child, pwm_port);
 
        cdev->tcdev = thermal_of_cooling_device_register(child,
                                                         cdev->name,
index a6636fe4218943f01354f4ab995d561d4cff2aa6..a7cf00885c5d34dda3a937d1f9f8596aecda8008 100644 (file)
@@ -1210,10 +1210,8 @@ static int atk_register_hwmon(struct atk_data *data)
        data->hwmon_dev = hwmon_device_register_with_groups(dev, "atk0110",
                                                            data,
                                                            data->attr_groups);
-       if (IS_ERR(data->hwmon_dev))
-               return PTR_ERR(data->hwmon_dev);
 
-       return 0;
+       return PTR_ERR_OR_ZERO(data->hwmon_dev);
 }
 
 static int atk_probe_if(struct atk_data *data)
index 33d51281272bb066762d80b46161b4f7f44113b6..975c951698846bffb8ae98ec4a70759e60a1f11b 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/string.h>
 #include <linux/thermal.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/hwmon.h>
+
 #define HWMON_ID_PREFIX "hwmon"
 #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
 
@@ -171,6 +174,13 @@ static int hwmon_thermal_add_sensor(struct device *dev,
 }
 #endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */
 
+static int hwmon_attr_base(enum hwmon_sensor_types type)
+{
+       if (type == hwmon_in)
+               return 0;
+       return 1;
+}
+
 /* sysfs attribute management */
 
 static ssize_t hwmon_attr_show(struct device *dev,
@@ -185,6 +195,9 @@ static ssize_t hwmon_attr_show(struct device *dev,
        if (ret < 0)
                return ret;
 
+       trace_hwmon_attr_show(hattr->index + hwmon_attr_base(hattr->type),
+                             hattr->name, val);
+
        return sprintf(buf, "%ld\n", val);
 }
 
@@ -193,6 +206,7 @@ static ssize_t hwmon_attr_show_string(struct device *dev,
                                      char *buf)
 {
        struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
+       enum hwmon_sensor_types type = hattr->type;
        const char *s;
        int ret;
 
@@ -201,6 +215,9 @@ static ssize_t hwmon_attr_show_string(struct device *dev,
        if (ret < 0)
                return ret;
 
+       trace_hwmon_attr_show_string(hattr->index + hwmon_attr_base(type),
+                                    hattr->name, s);
+
        return sprintf(buf, "%s\n", s);
 }
 
@@ -221,14 +238,10 @@ static ssize_t hwmon_attr_store(struct device *dev,
        if (ret < 0)
                return ret;
 
-       return count;
-}
+       trace_hwmon_attr_store(hattr->index + hwmon_attr_base(hattr->type),
+                              hattr->name, val);
 
-static int hwmon_attr_base(enum hwmon_sensor_types type)
-{
-       if (type == hwmon_in)
-               return 0;
-       return 1;
+       return count;
 }
 
 static bool is_string_attr(enum hwmon_sensor_types type, u32 attr)
@@ -356,6 +369,7 @@ static const char * const hwmon_in_attr_templates[] = {
        [hwmon_in_max_alarm] = "in%d_max_alarm",
        [hwmon_in_lcrit_alarm] = "in%d_lcrit_alarm",
        [hwmon_in_crit_alarm] = "in%d_crit_alarm",
+       [hwmon_in_enable] = "in%d_enable",
 };
 
 static const char * const hwmon_curr_attr_templates[] = {
index 83472808c8163275d3f95e136b8aa3eb0291ead2..0ccca87f527191dc000649d1a0b1eaf44c87d35b 100644 (file)
@@ -458,9 +458,6 @@ static int populate_attr_groups(struct platform_device *pdev)
        for_each_child_of_node(opal, np) {
                const char *label;
 
-               if (np->name == NULL)
-                       continue;
-
                type = get_sensor_type(np);
                if (type == MAX_SENSOR_TYPE)
                        continue;
@@ -589,9 +586,6 @@ static int create_device_attrs(struct platform_device *pdev)
                const char *label;
                enum sensors type;
 
-               if (np->name == NULL)
-                       continue;
-
                type = get_sensor_type(np);
                if (type == MAX_SENSOR_TYPE)
                        continue;
@@ -603,8 +597,8 @@ static int create_device_attrs(struct platform_device *pdev)
                if (of_property_read_u32(np, "sensor-id", &sensor_id) &&
                    of_property_read_u32(np, "sensor-data", &sensor_id)) {
                        dev_info(&pdev->dev,
-                                "'sensor-id' missing in the node '%s'\n",
-                                np->name);
+                                "'sensor-id' missing in the node '%pOFn'\n",
+                                np);
                        continue;
                }
 
index 2f3f875c06ac174a973233bb607da7dec7086c57..eed66e533ee29c59389f00082dbd69bf1ca7cb65 100644 (file)
@@ -65,13 +65,9 @@ static int iio_hwmon_probe(struct platform_device *pdev)
        int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1;
        enum iio_chan_type type;
        struct iio_channel *channels;
-       const char *name = "iio_hwmon";
        struct device *hwmon_dev;
        char *sname;
 
-       if (dev->of_node && dev->of_node->name)
-               name = dev->of_node->name;
-
        channels = devm_iio_channel_get_all(dev);
        if (IS_ERR(channels)) {
                if (PTR_ERR(channels) == -ENODEV)
@@ -141,11 +137,15 @@ static int iio_hwmon_probe(struct platform_device *pdev)
        st->attr_group.attrs = st->attrs;
        st->groups[0] = &st->attr_group;
 
-       sname = devm_kstrdup(dev, name, GFP_KERNEL);
-       if (!sname)
-               return -ENOMEM;
+       if (dev->of_node) {
+               sname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node);
+               if (!sname)
+                       return -ENOMEM;
+               strreplace(sname, '-', '_');
+       } else {
+               sname = "iio_hwmon";
+       }
 
-       strreplace(sname, '-', '_');
        hwmon_dev = devm_hwmon_device_register_with_groups(dev, sname, st,
                                                           st->groups);
        return PTR_ERR_OR_ZERO(hwmon_dev);
index e6b49500c52aedc8751afd7114ed2283e505ea56..d61688f045949d12c6b4eea90d7122a923ac77f0 100644 (file)
 #define INA3221_WARN3                  0x0c
 #define INA3221_MASK_ENABLE            0x0f
 
-#define INA3221_CONFIG_MODE_SHUNT      BIT(1)
-#define INA3221_CONFIG_MODE_BUS                BIT(2)
-#define INA3221_CONFIG_MODE_CONTINUOUS BIT(3)
+#define INA3221_CONFIG_MODE_MASK       GENMASK(2, 0)
+#define INA3221_CONFIG_MODE_POWERDOWN  0
+#define INA3221_CONFIG_MODE_SHUNT      BIT(0)
+#define INA3221_CONFIG_MODE_BUS                BIT(1)
+#define INA3221_CONFIG_MODE_CONTINUOUS BIT(2)
+#define INA3221_CONFIG_CHx_EN(x)       BIT(14 - (x))
 
 #define INA3221_RSHUNT_DEFAULT         10000
 
@@ -74,30 +77,37 @@ enum ina3221_channels {
        INA3221_NUM_CHANNELS
 };
 
-static const unsigned int register_channel[] = {
-       [INA3221_SHUNT1] = INA3221_CHANNEL1,
-       [INA3221_SHUNT2] = INA3221_CHANNEL2,
-       [INA3221_SHUNT3] = INA3221_CHANNEL3,
-       [INA3221_CRIT1] = INA3221_CHANNEL1,
-       [INA3221_CRIT2] = INA3221_CHANNEL2,
-       [INA3221_CRIT3] = INA3221_CHANNEL3,
-       [INA3221_WARN1] = INA3221_CHANNEL1,
-       [INA3221_WARN2] = INA3221_CHANNEL2,
-       [INA3221_WARN3] = INA3221_CHANNEL3,
+/**
+ * struct ina3221_input - channel input source specific information
+ * @label: label of channel input source
+ * @shunt_resistor: shunt resistor value of channel input source
+ * @disconnected: connection status of channel input source
+ */
+struct ina3221_input {
+       const char *label;
+       int shunt_resistor;
+       bool disconnected;
 };
 
 /**
  * struct ina3221_data - device specific information
  * @regmap: Register map of the device
  * @fields: Register fields of the device
- * @shunt_resistors: Array of resistor values per channel
+ * @inputs: Array of channel input source specific structures
+ * @reg_config: Register value of INA3221_CONFIG
  */
 struct ina3221_data {
        struct regmap *regmap;
        struct regmap_field *fields[F_MAX_FIELDS];
-       int shunt_resistors[INA3221_NUM_CHANNELS];
+       struct ina3221_input inputs[INA3221_NUM_CHANNELS];
+       u32 reg_config;
 };
 
+static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel)
+{
+       return ina->reg_config & INA3221_CONFIG_CHx_EN(channel);
+}
+
 static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
                              int *val)
 {
@@ -113,107 +123,284 @@ static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
        return 0;
 }
 
-static ssize_t ina3221_show_bus_voltage(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
+static const u8 ina3221_in_reg[] = {
+       INA3221_BUS1,
+       INA3221_BUS2,
+       INA3221_BUS3,
+       INA3221_SHUNT1,
+       INA3221_SHUNT2,
+       INA3221_SHUNT3,
+};
+
+static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val)
 {
-       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
+       const bool is_shunt = channel > INA3221_CHANNEL3;
        struct ina3221_data *ina = dev_get_drvdata(dev);
-       unsigned int reg = sd_attr->index;
-       int val, voltage_mv, ret;
-
-       ret = ina3221_read_value(ina, reg, &val);
-       if (ret)
-               return ret;
+       u8 reg = ina3221_in_reg[channel];
+       int regval, ret;
+
+       /* Translate shunt channel index to sensor channel index */
+       channel %= INA3221_NUM_CHANNELS;
+
+       switch (attr) {
+       case hwmon_in_input:
+               if (!ina3221_is_enabled(ina, channel))
+                       return -ENODATA;
+
+               ret = ina3221_read_value(ina, reg, &regval);
+               if (ret)
+                       return ret;
+
+               /*
+                * Scale of shunt voltage (uV): LSB is 40uV
+                * Scale of bus voltage (mV): LSB is 8mV
+                */
+               *val = regval * (is_shunt ? 40 : 8);
+               return 0;
+       case hwmon_in_enable:
+               *val = ina3221_is_enabled(ina, channel);
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
 
-       voltage_mv = val * 8;
+static const u8 ina3221_curr_reg[][INA3221_NUM_CHANNELS] = {
+       [hwmon_curr_input] = { INA3221_SHUNT1, INA3221_SHUNT2, INA3221_SHUNT3 },
+       [hwmon_curr_max] = { INA3221_WARN1, INA3221_WARN2, INA3221_WARN3 },
+       [hwmon_curr_crit] = { INA3221_CRIT1, INA3221_CRIT2, INA3221_CRIT3 },
+       [hwmon_curr_max_alarm] = { F_WF1, F_WF2, F_WF3 },
+       [hwmon_curr_crit_alarm] = { F_CF1, F_CF2, F_CF3 },
+};
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", voltage_mv);
+static int ina3221_read_curr(struct device *dev, u32 attr,
+                            int channel, long *val)
+{
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       struct ina3221_input *input = &ina->inputs[channel];
+       int resistance_uo = input->shunt_resistor;
+       u8 reg = ina3221_curr_reg[attr][channel];
+       int regval, voltage_nv, ret;
+
+       switch (attr) {
+       case hwmon_curr_input:
+               if (!ina3221_is_enabled(ina, channel))
+                       return -ENODATA;
+               /* fall through */
+       case hwmon_curr_crit:
+       case hwmon_curr_max:
+               ret = ina3221_read_value(ina, reg, &regval);
+               if (ret)
+                       return ret;
+
+               /* Scale of shunt voltage: LSB is 40uV (40000nV) */
+               voltage_nv = regval * 40000;
+               /* Return current in mA */
+               *val = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo);
+               return 0;
+       case hwmon_curr_crit_alarm:
+       case hwmon_curr_max_alarm:
+               ret = regmap_field_read(ina->fields[reg], &regval);
+               if (ret)
+                       return ret;
+               *val = regval;
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
-static ssize_t ina3221_show_shunt_voltage(struct device *dev,
-                                         struct device_attribute *attr,
-                                         char *buf)
+static int ina3221_write_curr(struct device *dev, u32 attr,
+                             int channel, long val)
 {
-       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
-       unsigned int reg = sd_attr->index;
-       int val, voltage_uv, ret;
+       struct ina3221_input *input = &ina->inputs[channel];
+       int resistance_uo = input->shunt_resistor;
+       u8 reg = ina3221_curr_reg[attr][channel];
+       int regval, current_ma, voltage_uv;
 
-       ret = ina3221_read_value(ina, reg, &val);
-       if (ret)
-               return ret;
-       voltage_uv = val * 40;
+       /* clamp current */
+       current_ma = clamp_val(val,
+                              INT_MIN / resistance_uo,
+                              INT_MAX / resistance_uo);
+
+       voltage_uv = DIV_ROUND_CLOSEST(current_ma * resistance_uo, 1000);
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", voltage_uv);
+       /* clamp voltage */
+       voltage_uv = clamp_val(voltage_uv, -163800, 163800);
+
+       /* 1 / 40uV(scale) << 3(register shift) = 5 */
+       regval = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8;
+
+       return regmap_write(ina->regmap, reg, regval);
 }
 
-static ssize_t ina3221_show_current(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
+static int ina3221_write_enable(struct device *dev, int channel, bool enable)
 {
-       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
-       unsigned int reg = sd_attr->index;
-       unsigned int channel = register_channel[reg];
-       int resistance_uo = ina->shunt_resistors[channel];
-       int val, current_ma, voltage_nv, ret;
+       u16 config, mask = INA3221_CONFIG_CHx_EN(channel);
+       int ret;
 
-       ret = ina3221_read_value(ina, reg, &val);
+       config = enable ? mask : 0;
+
+       /* Enable or disable the channel */
+       ret = regmap_update_bits(ina->regmap, INA3221_CONFIG, mask, config);
        if (ret)
                return ret;
-       voltage_nv = val * 40000;
 
-       current_ma = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo);
+       /* Cache the latest config register value */
+       ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config);
+       if (ret)
+               return ret;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", current_ma);
+       return 0;
 }
 
-static ssize_t ina3221_set_current(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t count)
+static int ina3221_read(struct device *dev, enum hwmon_sensor_types type,
+                       u32 attr, int channel, long *val)
+{
+       switch (type) {
+       case hwmon_in:
+               /* 0-align channel ID */
+               return ina3221_read_in(dev, attr, channel - 1, val);
+       case hwmon_curr:
+               return ina3221_read_curr(dev, attr, channel, val);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static int ina3221_write(struct device *dev, enum hwmon_sensor_types type,
+                        u32 attr, int channel, long val)
+{
+       switch (type) {
+       case hwmon_in:
+               /* 0-align channel ID */
+               return ina3221_write_enable(dev, channel - 1, val);
+       case hwmon_curr:
+               return ina3221_write_curr(dev, attr, channel, val);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static int ina3221_read_string(struct device *dev, enum hwmon_sensor_types type,
+                              u32 attr, int channel, const char **str)
 {
-       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
-       unsigned int reg = sd_attr->index;
-       unsigned int channel = register_channel[reg];
-       int resistance_uo = ina->shunt_resistors[channel];
-       int val, current_ma, voltage_uv, ret;
+       int index = channel - 1;
 
-       ret = kstrtoint(buf, 0, &current_ma);
-       if (ret)
-               return ret;
+       *str = ina->inputs[index].label;
 
-       /* clamp current */
-       current_ma = clamp_val(current_ma,
-                              INT_MIN / resistance_uo,
-                              INT_MAX / resistance_uo);
+       return 0;
+}
 
-       voltage_uv = DIV_ROUND_CLOSEST(current_ma * resistance_uo, 1000);
+static umode_t ina3221_is_visible(const void *drvdata,
+                                 enum hwmon_sensor_types type,
+                                 u32 attr, int channel)
+{
+       const struct ina3221_data *ina = drvdata;
+       const struct ina3221_input *input = NULL;
+
+       switch (type) {
+       case hwmon_in:
+               /* Ignore in0_ */
+               if (channel == 0)
+                       return 0;
+
+               switch (attr) {
+               case hwmon_in_label:
+                       if (channel - 1 <= INA3221_CHANNEL3)
+                               input = &ina->inputs[channel - 1];
+                       /* Hide label node if label is not provided */
+                       return (input && input->label) ? 0444 : 0;
+               case hwmon_in_input:
+                       return 0444;
+               case hwmon_in_enable:
+                       return 0644;
+               default:
+                       return 0;
+               }
+       case hwmon_curr:
+               switch (attr) {
+               case hwmon_curr_input:
+               case hwmon_curr_crit_alarm:
+               case hwmon_curr_max_alarm:
+                       return 0444;
+               case hwmon_curr_crit:
+               case hwmon_curr_max:
+                       return 0644;
+               default:
+                       return 0;
+               }
+       default:
+               return 0;
+       }
+}
 
-       /* clamp voltage */
-       voltage_uv = clamp_val(voltage_uv, -163800, 163800);
+static const u32 ina3221_in_config[] = {
+       /* 0: dummy, skipped in is_visible */
+       HWMON_I_INPUT,
+       /* 1-3: input voltage Channels */
+       HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
+       HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
+       HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
+       /* 4-6: shunt voltage Channels */
+       HWMON_I_INPUT,
+       HWMON_I_INPUT,
+       HWMON_I_INPUT,
+       0
+};
 
-       /* 1 / 40uV(scale) << 3(register shift) = 5 */
-       val = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8;
+static const struct hwmon_channel_info ina3221_in = {
+       .type = hwmon_in,
+       .config = ina3221_in_config,
+};
 
-       ret = regmap_write(ina->regmap, reg, val);
-       if (ret)
-               return ret;
+#define INA3221_HWMON_CURR_CONFIG (HWMON_C_INPUT | \
+                                  HWMON_C_CRIT | HWMON_C_CRIT_ALARM | \
+                                  HWMON_C_MAX | HWMON_C_MAX_ALARM)
 
-       return count;
-}
+static const u32 ina3221_curr_config[] = {
+       INA3221_HWMON_CURR_CONFIG,
+       INA3221_HWMON_CURR_CONFIG,
+       INA3221_HWMON_CURR_CONFIG,
+       0
+};
+
+static const struct hwmon_channel_info ina3221_curr = {
+       .type = hwmon_curr,
+       .config = ina3221_curr_config,
+};
+
+static const struct hwmon_channel_info *ina3221_info[] = {
+       &ina3221_in,
+       &ina3221_curr,
+       NULL
+};
+
+static const struct hwmon_ops ina3221_hwmon_ops = {
+       .is_visible = ina3221_is_visible,
+       .read_string = ina3221_read_string,
+       .read = ina3221_read,
+       .write = ina3221_write,
+};
 
+static const struct hwmon_chip_info ina3221_chip_info = {
+       .ops = &ina3221_hwmon_ops,
+       .info = ina3221_info,
+};
+
+/* Extra attribute groups */
 static ssize_t ina3221_show_shunt(struct device *dev,
                                  struct device_attribute *attr, char *buf)
 {
        struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int channel = sd_attr->index;
-       unsigned int resistance_uo;
-
-       resistance_uo = ina->shunt_resistors[channel];
+       struct ina3221_input *input = &ina->inputs[channel];
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", resistance_uo);
+       return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor);
 }
 
 static ssize_t ina3221_set_shunt(struct device *dev,
@@ -223,6 +410,7 @@ static ssize_t ina3221_set_shunt(struct device *dev,
        struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int channel = sd_attr->index;
+       struct ina3221_input *input = &ina->inputs[channel];
        int val;
        int ret;
 
@@ -232,43 +420,11 @@ static ssize_t ina3221_set_shunt(struct device *dev,
 
        val = clamp_val(val, 1, INT_MAX);
 
-       ina->shunt_resistors[channel] = val;
+       input->shunt_resistor = val;
 
        return count;
 }
 
-static ssize_t ina3221_show_alert(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
-       struct ina3221_data *ina = dev_get_drvdata(dev);
-       unsigned int field = sd_attr->index;
-       unsigned int regval;
-       int ret;
-
-       ret = regmap_field_read(ina->fields[field], &regval);
-       if (ret)
-               return ret;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", regval);
-}
-
-/* bus voltage */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO,
-               ina3221_show_bus_voltage, NULL, INA3221_BUS1);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO,
-               ina3221_show_bus_voltage, NULL, INA3221_BUS2);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO,
-               ina3221_show_bus_voltage, NULL, INA3221_BUS3);
-
-/* calculated current */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO,
-               ina3221_show_current, NULL, INA3221_SHUNT1);
-static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO,
-               ina3221_show_current, NULL, INA3221_SHUNT2);
-static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO,
-               ina3221_show_current, NULL, INA3221_SHUNT3);
-
 /* shunt resistance */
 static SENSOR_DEVICE_ATTR(shunt1_resistor, S_IRUGO | S_IWUSR,
                ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL1);
@@ -277,83 +433,16 @@ static SENSOR_DEVICE_ATTR(shunt2_resistor, S_IRUGO | S_IWUSR,
 static SENSOR_DEVICE_ATTR(shunt3_resistor, S_IRUGO | S_IWUSR,
                ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL3);
 
-/* critical current */
-static SENSOR_DEVICE_ATTR(curr1_crit, S_IRUGO | S_IWUSR,
-               ina3221_show_current, ina3221_set_current, INA3221_CRIT1);
-static SENSOR_DEVICE_ATTR(curr2_crit, S_IRUGO | S_IWUSR,
-               ina3221_show_current, ina3221_set_current, INA3221_CRIT2);
-static SENSOR_DEVICE_ATTR(curr3_crit, S_IRUGO | S_IWUSR,
-               ina3221_show_current, ina3221_set_current, INA3221_CRIT3);
-
-/* critical current alert */
-static SENSOR_DEVICE_ATTR(curr1_crit_alarm, S_IRUGO,
-               ina3221_show_alert, NULL, F_CF1);
-static SENSOR_DEVICE_ATTR(curr2_crit_alarm, S_IRUGO,
-               ina3221_show_alert, NULL, F_CF2);
-static SENSOR_DEVICE_ATTR(curr3_crit_alarm, S_IRUGO,
-               ina3221_show_alert, NULL, F_CF3);
-
-/* warning current */
-static SENSOR_DEVICE_ATTR(curr1_max, S_IRUGO | S_IWUSR,
-               ina3221_show_current, ina3221_set_current, INA3221_WARN1);
-static SENSOR_DEVICE_ATTR(curr2_max, S_IRUGO | S_IWUSR,
-               ina3221_show_current, ina3221_set_current, INA3221_WARN2);
-static SENSOR_DEVICE_ATTR(curr3_max, S_IRUGO | S_IWUSR,
-               ina3221_show_current, ina3221_set_current, INA3221_WARN3);
-
-/* warning current alert */
-static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO,
-               ina3221_show_alert, NULL, F_WF1);
-static SENSOR_DEVICE_ATTR(curr2_max_alarm, S_IRUGO,
-               ina3221_show_alert, NULL, F_WF2);
-static SENSOR_DEVICE_ATTR(curr3_max_alarm, S_IRUGO,
-               ina3221_show_alert, NULL, F_WF3);
-
-/* shunt voltage */
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO,
-               ina3221_show_shunt_voltage, NULL, INA3221_SHUNT1);
-static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO,
-               ina3221_show_shunt_voltage, NULL, INA3221_SHUNT2);
-static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO,
-               ina3221_show_shunt_voltage, NULL, INA3221_SHUNT3);
-
 static struct attribute *ina3221_attrs[] = {
-       /* channel 1 */
-       &sensor_dev_attr_in1_input.dev_attr.attr,
-       &sensor_dev_attr_curr1_input.dev_attr.attr,
        &sensor_dev_attr_shunt1_resistor.dev_attr.attr,
-       &sensor_dev_attr_curr1_crit.dev_attr.attr,
-       &sensor_dev_attr_curr1_crit_alarm.dev_attr.attr,
-       &sensor_dev_attr_curr1_max.dev_attr.attr,
-       &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
-       &sensor_dev_attr_in4_input.dev_attr.attr,
-
-       /* channel 2 */
-       &sensor_dev_attr_in2_input.dev_attr.attr,
-       &sensor_dev_attr_curr2_input.dev_attr.attr,
        &sensor_dev_attr_shunt2_resistor.dev_attr.attr,
-       &sensor_dev_attr_curr2_crit.dev_attr.attr,
-       &sensor_dev_attr_curr2_crit_alarm.dev_attr.attr,
-       &sensor_dev_attr_curr2_max.dev_attr.attr,
-       &sensor_dev_attr_curr2_max_alarm.dev_attr.attr,
-       &sensor_dev_attr_in5_input.dev_attr.attr,
-
-       /* channel 3 */
-       &sensor_dev_attr_in3_input.dev_attr.attr,
-       &sensor_dev_attr_curr3_input.dev_attr.attr,
        &sensor_dev_attr_shunt3_resistor.dev_attr.attr,
-       &sensor_dev_attr_curr3_crit.dev_attr.attr,
-       &sensor_dev_attr_curr3_crit_alarm.dev_attr.attr,
-       &sensor_dev_attr_curr3_max.dev_attr.attr,
-       &sensor_dev_attr_curr3_max_alarm.dev_attr.attr,
-       &sensor_dev_attr_in6_input.dev_attr.attr,
-
        NULL,
 };
 ATTRIBUTE_GROUPS(ina3221);
 
 static const struct regmap_range ina3221_yes_ranges[] = {
-       regmap_reg_range(INA3221_SHUNT1, INA3221_BUS3),
+       regmap_reg_range(INA3221_CONFIG, INA3221_BUS3),
        regmap_reg_range(INA3221_MASK_ENABLE, INA3221_MASK_ENABLE),
 };
 
@@ -370,6 +459,66 @@ static const struct regmap_config ina3221_regmap_config = {
        .volatile_table = &ina3221_volatile_table,
 };
 
+static int ina3221_probe_child_from_dt(struct device *dev,
+                                      struct device_node *child,
+                                      struct ina3221_data *ina)
+{
+       struct ina3221_input *input;
+       u32 val;
+       int ret;
+
+       ret = of_property_read_u32(child, "reg", &val);
+       if (ret) {
+               dev_err(dev, "missing reg property of %s\n", child->name);
+               return ret;
+       } else if (val > INA3221_CHANNEL3) {
+               dev_err(dev, "invalid reg %d of %s\n", val, child->name);
+               return ret;
+       }
+
+       input = &ina->inputs[val];
+
+       /* Log the disconnected channel input */
+       if (!of_device_is_available(child)) {
+               input->disconnected = true;
+               return 0;
+       }
+
+       /* Save the connected input label if available */
+       of_property_read_string(child, "label", &input->label);
+
+       /* Overwrite default shunt resistor value optionally */
+       if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) {
+               if (val < 1 || val > INT_MAX) {
+                       dev_err(dev, "invalid shunt resistor value %u of %s\n",
+                               val, child->name);
+                       return -EINVAL;
+               }
+               input->shunt_resistor = val;
+       }
+
+       return 0;
+}
+
+static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
+{
+       const struct device_node *np = dev->of_node;
+       struct device_node *child;
+       int ret;
+
+       /* Compatible with non-DT platforms */
+       if (!np)
+               return 0;
+
+       for_each_child_of_node(np, child) {
+               ret = ina3221_probe_child_from_dt(dev, child, ina);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int ina3221_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -399,7 +548,13 @@ static int ina3221_probe(struct i2c_client *client,
        }
 
        for (i = 0; i < INA3221_NUM_CHANNELS; i++)
-               ina->shunt_resistors[i] = INA3221_RSHUNT_DEFAULT;
+               ina->inputs[i].shunt_resistor = INA3221_RSHUNT_DEFAULT;
+
+       ret = ina3221_probe_from_dt(dev, ina);
+       if (ret) {
+               dev_err(dev, "Unable to probe from device tree\n");
+               return ret;
+       }
 
        ret = regmap_field_write(ina->fields[F_RST], true);
        if (ret) {
@@ -407,9 +562,25 @@ static int ina3221_probe(struct i2c_client *client,
                return ret;
        }
 
-       hwmon_dev = devm_hwmon_device_register_with_groups(dev,
-                                                          client->name,
-                                                          ina, ina3221_groups);
+       /* Sync config register after reset */
+       ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config);
+       if (ret)
+               return ret;
+
+       /* Disable channels if their inputs are disconnected */
+       for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
+               if (ina->inputs[i].disconnected)
+                       ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i);
+       }
+       ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config);
+       if (ret)
+               return ret;
+
+       dev_set_drvdata(dev, ina);
+
+       hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina,
+                                                        &ina3221_chip_info,
+                                                        ina3221_groups);
        if (IS_ERR(hwmon_dev)) {
                dev_err(dev, "Unable to register hwmon device\n");
                return PTR_ERR(hwmon_dev);
@@ -418,6 +589,60 @@ static int ina3221_probe(struct i2c_client *client,
        return 0;
 }
 
+static int __maybe_unused ina3221_suspend(struct device *dev)
+{
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       int ret;
+
+       /* Save config register value and enable cache-only */
+       ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config);
+       if (ret)
+               return ret;
+
+       /* Set to power-down mode for power saving */
+       ret = regmap_update_bits(ina->regmap, INA3221_CONFIG,
+                                INA3221_CONFIG_MODE_MASK,
+                                INA3221_CONFIG_MODE_POWERDOWN);
+       if (ret)
+               return ret;
+
+       regcache_cache_only(ina->regmap, true);
+       regcache_mark_dirty(ina->regmap);
+
+       return 0;
+}
+
+static int __maybe_unused ina3221_resume(struct device *dev)
+{
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       int ret;
+
+       regcache_cache_only(ina->regmap, false);
+
+       /* Software reset the chip */
+       ret = regmap_field_write(ina->fields[F_RST], true);
+       if (ret) {
+               dev_err(dev, "Unable to reset device\n");
+               return ret;
+       }
+
+       /* Restore cached register values to hardware */
+       ret = regcache_sync(ina->regmap);
+       if (ret)
+               return ret;
+
+       /* Restore config register value to hardware */
+       ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct dev_pm_ops ina3221_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(ina3221_suspend, ina3221_resume)
+};
+
 static const struct of_device_id ina3221_of_match_table[] = {
        { .compatible = "ti,ina3221", },
        { /* sentinel */ }
@@ -435,6 +660,7 @@ static struct i2c_driver ina3221_i2c_driver = {
        .driver = {
                .name = INA3221_DRIVER_NAME,
                .of_match_table = ina3221_of_match_table,
+               .pm = &ina3221_pm,
        },
        .id_table = ina3221_ids,
 };
index bb15d7816a294f0fd3c9b99d4bc04195e374698e..2cef0c37ff6fe0b6c9eb9147316252d79f416b83 100644 (file)
@@ -325,8 +325,9 @@ static int k10temp_probe(struct pci_dev *pdev,
 
        data->pdev = pdev;
 
-       if (boot_cpu_data.x86 == 0x15 && (boot_cpu_data.x86_model == 0x60 ||
-                                         boot_cpu_data.x86_model == 0x70)) {
+       if (boot_cpu_data.x86 == 0x15 &&
+           ((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
+            (boot_cpu_data.x86_model & 0xf0) == 0x70)) {
                data->read_htcreg = read_htcreg_nb_f15;
                data->read_tempreg = read_tempreg_nb_f15;
        } else if (boot_cpu_data.x86 == 0x17) {
index 49f4b33a5685a82530df3149609902fce0db76be..e6e5a1080f0905bedf38e62a1b6161f6effd103b 100644 (file)
@@ -47,6 +47,7 @@ enum lm75_type {              /* keep sorted in alphabetical order */
        lm75b,
        max6625,
        max6626,
+       max31725,
        mcp980x,
        stds75,
        tcn75,
@@ -64,7 +65,6 @@ enum lm75_type {              /* keep sorted in alphabetical order */
 static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
                                        0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
-
 /* The LM75 registers */
 #define LM75_REG_TEMP          0x00
 #define LM75_REG_CONF          0x01
@@ -76,7 +76,7 @@ struct lm75_data {
        struct i2c_client       *client;
        struct regmap           *regmap;
        u8                      orig_conf;
-       u8                      resolution;     /* In bits, between 9 and 12 */
+       u8                      resolution;     /* In bits, between 9 and 16 */
        u8                      resolution_limits;
        unsigned int            sample_time;    /* In ms */
 };
@@ -339,6 +339,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                data->resolution_limits = 9;
                data->sample_time = MSEC_PER_SEC / 4;
                break;
+       case max31725:
+               data->resolution = 16;
+               data->sample_time = MSEC_PER_SEC / 8;
+               break;
        case tcn75:
                data->resolution = 9;
                data->sample_time = MSEC_PER_SEC / 8;
@@ -415,6 +419,8 @@ static const struct i2c_device_id lm75_ids[] = {
        { "lm75b", lm75b, },
        { "max6625", max6625, },
        { "max6626", max6626, },
+       { "max31725", max31725, },
+       { "max31726", max31725, },
        { "mcp980x", mcp980x, },
        { "stds75", stds75, },
        { "tcn75", tcn75, },
@@ -471,6 +477,14 @@ static const struct of_device_id lm75_of_match[] = {
                .compatible = "maxim,max6626",
                .data = (void *)max6626
        },
+       {
+               .compatible = "maxim,max31725",
+               .data = (void *)max31725
+       },
+       {
+               .compatible = "maxim,max31726",
+               .data = (void *)max31725
+       },
        {
                .compatible = "maxim,mcp980x",
                .data = (void *)mcp980x
index d40fe5122e941c345fd0656aea597fbec2daaf81..e7333f8e185cd09827dbd604ce83d6222b798058 100644 (file)
@@ -127,8 +127,8 @@ static struct lm92_data *lm92_update_device(struct device *dev)
 
        mutex_lock(&data->update_lock);
 
-       if (time_after(jiffies, data->last_updated + HZ)
-        || !data->valid) {
+       if (time_after(jiffies, data->last_updated + HZ) ||
+           !data->valid) {
                dev_dbg(&client->dev, "Updating lm92 data\n");
                for (i = 0; i < t_num_regs; i++) {
                        data->temp[i] =
@@ -153,7 +153,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
 }
 
 static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
-                          const char *buf, size_t count)
+                       const char *buf, size_t count)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct lm92_data *data = dev_get_drvdata(dev);
@@ -161,7 +161,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
        int nr = attr->index;
        long val;
        int err;
-       
+
        err = kstrtol(buf, 10, &val);
        if (err)
                return err;
@@ -178,6 +178,7 @@ static ssize_t show_temp_hyst(struct device *dev,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct lm92_data *data = lm92_update_device(dev);
+
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])
                       - TEMP_FROM_REG(data->temp[t_hyst]));
 }
@@ -186,6 +187,7 @@ static ssize_t temp1_min_hyst_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
        struct lm92_data *data = lm92_update_device(dev);
+
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[t_min])
                       + TEMP_FROM_REG(data->temp[t_hyst]));
 }
@@ -206,7 +208,7 @@ static ssize_t set_temp_hyst(struct device *dev,
 
        val = clamp_val(val, -120000, 220000);
        mutex_lock(&data->update_lock);
-        data->temp[t_hyst] =
+       data->temp[t_hyst] =
                TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val);
        i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
                                     data->temp[t_hyst]);
@@ -218,6 +220,7 @@ static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
                           char *buf)
 {
        struct lm92_data *data = lm92_update_device(dev);
+
        return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input]));
 }
 
@@ -324,7 +327,6 @@ static int lm92_probe(struct i2c_client *new_client,
        return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-
 /*
  * Module and driver stuff
  */
index 78fe8759d2a9448f12bb9ae02ee0101643a1e74e..825b922a3f92c848c6cb5b33ffe345b1d98cf94e 100644 (file)
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Driver for the ADC on Freescale Semiconductor MC13783 and MC13892 PMICs.
  *
  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright (C) 2009 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <linux/mfd/mc13xxx.h>
index 78603b78cf410de903aa22d55147e6b600ab0398..c3040079b1cb645ef10d66f0f23edd3c8b10483c 100644 (file)
  * nct6793d    15      6       6       2+6    0xd120 0xc1    0x5ca3
  * nct6795d    14      6       6       2+6    0xd350 0xc1    0x5ca3
  * nct6796d    14      7       7       2+6    0xd420 0xc1    0x5ca3
+ * nct6797d    14      7       7       2+6    0xd450 0xc1    0x5ca3
+ *                                           (0xd451)
+ * nct6798d    14      7       7       2+6    0xd458 0xc1    0x5ca3
+ *                                           (0xd459)
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -69,7 +73,7 @@
 #define USE_ALTERNATE
 
 enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793,
-            nct6795, nct6796 };
+            nct6795, nct6796, nct6797, nct6798 };
 
 /* used to set data->name = nct6775_device_names[data->sio_kind] */
 static const char * const nct6775_device_names[] = {
@@ -82,6 +86,8 @@ static const char * const nct6775_device_names[] = {
        "nct6793",
        "nct6795",
        "nct6796",
+       "nct6797",
+       "nct6798",
 };
 
 static const char * const nct6775_sio_names[] __initconst = {
@@ -94,6 +100,8 @@ static const char * const nct6775_sio_names[] __initconst = {
        "NCT6793D",
        "NCT6795D",
        "NCT6796D",
+       "NCT6797D",
+       "NCT6798D",
 };
 
 static unsigned short force_id;
@@ -129,7 +137,9 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6793_ID         0xd120
 #define SIO_NCT6795_ID         0xd350
 #define SIO_NCT6796_ID         0xd420
-#define SIO_ID_MASK            0xFFF0
+#define SIO_NCT6797_ID         0xd450
+#define SIO_NCT6798_ID         0xd458
+#define SIO_ID_MASK            0xFFF8
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
 
@@ -504,7 +514,7 @@ static const s8 NCT6779_BEEP_BITS[] = {
 static const u16 NCT6779_REG_FAN[] = {
        0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce };
 static const u16 NCT6779_REG_FAN_PULSES[NUM_FAN] = {
-       0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
+       0x644, 0x645, 0x646, 0x647, 0x648, 0x649, 0x64f };
 
 static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
        0x136, 0x236, 0x336, 0x836, 0x936, 0xa36, 0xb36 };
@@ -704,10 +714,10 @@ static const char *const nct6795_temp_label[] = {
        "PCH_CHIP_TEMP",
        "PCH_CPU_TEMP",
        "PCH_MCH_TEMP",
-       "PCH_DIM0_TEMP",
-       "PCH_DIM1_TEMP",
-       "PCH_DIM2_TEMP",
-       "PCH_DIM3_TEMP",
+       "Agent0 Dimm0",
+       "Agent0 Dimm1",
+       "Agent1 Dimm0",
+       "Agent1 Dimm1",
        "BYTE_TEMP0",
        "BYTE_TEMP1",
        "PECI Agent 0 Calibration",
@@ -742,10 +752,10 @@ static const char *const nct6796_temp_label[] = {
        "PCH_CHIP_TEMP",
        "PCH_CPU_TEMP",
        "PCH_MCH_TEMP",
-       "PCH_DIM0_TEMP",
-       "PCH_DIM1_TEMP",
-       "PCH_DIM2_TEMP",
-       "PCH_DIM3_TEMP",
+       "Agent0 Dimm0",
+       "Agent0 Dimm1",
+       "Agent1 Dimm0",
+       "Agent1 Dimm1",
        "BYTE_TEMP0",
        "BYTE_TEMP1",
        "PECI Agent 0 Calibration",
@@ -757,6 +767,44 @@ static const char *const nct6796_temp_label[] = {
 #define NCT6796_TEMP_MASK      0xbfff0ffe
 #define NCT6796_VIRT_TEMP_MASK 0x80000c00
 
+static const char *const nct6798_temp_label[] = {
+       "",
+       "SYSTIN",
+       "CPUTIN",
+       "AUXTIN0",
+       "AUXTIN1",
+       "AUXTIN2",
+       "AUXTIN3",
+       "AUXTIN4",
+       "SMBUSMASTER 0",
+       "SMBUSMASTER 1",
+       "Virtual_TEMP",
+       "Virtual_TEMP",
+       "",
+       "",
+       "",
+       "",
+       "PECI Agent 0",
+       "PECI Agent 1",
+       "PCH_CHIP_CPU_MAX_TEMP",
+       "PCH_CHIP_TEMP",
+       "PCH_CPU_TEMP",
+       "PCH_MCH_TEMP",
+       "Agent0 Dimm0",
+       "Agent0 Dimm1",
+       "Agent1 Dimm0",
+       "Agent1 Dimm1",
+       "BYTE_TEMP0",
+       "BYTE_TEMP1",
+       "",
+       "",
+       "",
+       "Virtual_TEMP"
+};
+
+#define NCT6798_TEMP_MASK      0x8fff0ffe
+#define NCT6798_VIRT_TEMP_MASK 0x80000c00
+
 /* NCT6102D/NCT6106D specific data */
 
 #define NCT6106_REG_VBAT       0x318
@@ -1288,6 +1336,8 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
        case nct6793:
        case nct6795:
        case nct6796:
+       case nct6797:
+       case nct6798:
                return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
                  (reg & 0xfff0) == 0x4c0 ||
                  reg == 0x402 ||
@@ -1643,6 +1693,8 @@ static void nct6775_update_pwm_limits(struct device *dev)
                case nct6793:
                case nct6795:
                case nct6796:
+               case nct6797:
+               case nct6798:
                        reg = nct6775_read_value(data,
                                        data->REG_CRITICAL_PWM_ENABLE[i]);
                        if (reg & data->CRITICAL_PWM_ENABLE_MASK)
@@ -2847,6 +2899,8 @@ store_temp_tolerance(struct device *dev, struct device_attribute *attr,
  * Fan speed tolerance is a tricky beast, since the associated register is
  * a tick counter, but the value is reported and configured as rpm.
  * Compute resulting low and high rpm values and report the difference.
+ * A fan speed tolerance only makes sense if a fan target speed has been
+ * configured, so only display values other than 0 if that is the case.
  */
 static ssize_t
 show_speed_tolerance(struct device *dev, struct device_attribute *attr,
@@ -2855,19 +2909,23 @@ show_speed_tolerance(struct device *dev, struct device_attribute *attr,
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
-       int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
-       int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
-       int tolerance;
-
-       if (low <= 0)
-               low = 1;
-       if (high > 0xffff)
-               high = 0xffff;
-       if (high < low)
-               high = low;
-
-       tolerance = (fan_from_reg16(low, data->fan_div[nr])
-                    - fan_from_reg16(high, data->fan_div[nr])) / 2;
+       int target = data->target_speed[nr];
+       int tolerance = 0;
+
+       if (target) {
+               int low = target - data->target_speed_tolerance[nr];
+               int high = target + data->target_speed_tolerance[nr];
+
+               if (low <= 0)
+                       low = 1;
+               if (high > 0xffff)
+                       high = 0xffff;
+               if (high < low)
+                       high = low;
+
+               tolerance = (fan_from_reg16(low, data->fan_div[nr])
+                            - fan_from_reg16(high, data->fan_div[nr])) / 2;
+       }
 
        return sprintf(buf, "%d\n", tolerance);
 }
@@ -3071,6 +3129,8 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
                case nct6793:
                case nct6795:
                case nct6796:
+               case nct6797:
+               case nct6798:
                        nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
                                            val);
                        reg = nct6775_read_value(data,
@@ -3430,7 +3490,6 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
        bool pwm3pin = false, pwm4pin = false, pwm5pin = false;
        bool pwm6pin = false, pwm7pin = false;
        int sioreg = data->sioreg;
-       int regval;
 
        /* Store SIO_REG_ENABLE for use during resume */
        superio_select(sioreg, NCT6775_LD_HWM);
@@ -3438,10 +3497,10 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
 
        /* fan4 and fan5 share some pins with the GPIO and serial flash */
        if (data->kind == nct6775) {
-               regval = superio_inb(sioreg, 0x2c);
+               int cr2c = superio_inb(sioreg, 0x2c);
 
-               fan3pin = regval & BIT(6);
-               pwm3pin = regval & BIT(7);
+               fan3pin = cr2c & BIT(6);
+               pwm3pin = cr2c & BIT(7);
 
                /* On NCT6775, fan4 shares pins with the fdc interface */
                fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
@@ -3486,85 +3545,130 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                fan4min = fan4pin;
                pwm3pin = fan3pin;
        } else if (data->kind == nct6106) {
-               regval = superio_inb(sioreg, 0x24);
-               fan3pin = !(regval & 0x80);
-               pwm3pin = regval & 0x08;
-       } else {
-               /* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D */
-               int regval_1b, regval_2a, regval_2f;
-               bool dsw_en;
-
-               regval = superio_inb(sioreg, 0x1c);
+               int cr24 = superio_inb(sioreg, 0x24);
 
-               fan3pin = !(regval & BIT(5));
-               fan4pin = !(regval & BIT(6));
-               fan5pin = !(regval & BIT(7));
-
-               pwm3pin = !(regval & BIT(0));
-               pwm4pin = !(regval & BIT(1));
-               pwm5pin = !(regval & BIT(2));
+               fan3pin = !(cr24 & 0x80);
+               pwm3pin = cr24 & 0x08;
+       } else {
+               /*
+                * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D,
+                * NCT6797D, NCT6798D
+                */
+               int cr1a = superio_inb(sioreg, 0x1a);
+               int cr1b = superio_inb(sioreg, 0x1b);
+               int cr1c = superio_inb(sioreg, 0x1c);
+               int cr1d = superio_inb(sioreg, 0x1d);
+               int cr2a = superio_inb(sioreg, 0x2a);
+               int cr2b = superio_inb(sioreg, 0x2b);
+               int cr2d = superio_inb(sioreg, 0x2d);
+               int cr2f = superio_inb(sioreg, 0x2f);
+               bool dsw_en = cr2f & BIT(3);
+               bool ddr4_en = cr2f & BIT(4);
+               int cre0;
+               int creb;
+               int cred;
+
+               superio_select(sioreg, NCT6775_LD_12);
+               cre0 = superio_inb(sioreg, 0xe0);
+               creb = superio_inb(sioreg, 0xeb);
+               cred = superio_inb(sioreg, 0xed);
+
+               fan3pin = !(cr1c & BIT(5));
+               fan4pin = !(cr1c & BIT(6));
+               fan5pin = !(cr1c & BIT(7));
+
+               pwm3pin = !(cr1c & BIT(0));
+               pwm4pin = !(cr1c & BIT(1));
+               pwm5pin = !(cr1c & BIT(2));
 
-               regval = superio_inb(sioreg, 0x2d);
                switch (data->kind) {
                case nct6791:
+                       fan6pin = cr2d & BIT(1);
+                       pwm6pin = cr2d & BIT(0);
+                       break;
                case nct6792:
-                       fan6pin = regval & BIT(1);
-                       pwm6pin = regval & BIT(0);
+                       fan6pin = !dsw_en && (cr2d & BIT(1));
+                       pwm6pin = !dsw_en && (cr2d & BIT(0));
                        break;
                case nct6793:
+                       fan5pin |= cr1b & BIT(5);
+                       fan5pin |= creb & BIT(5);
+
+                       fan6pin = creb & BIT(3);
+
+                       pwm5pin |= cr2d & BIT(7);
+                       pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
+
+                       pwm6pin = !dsw_en && (cr2d & BIT(0));
+                       pwm6pin |= creb & BIT(2);
+                       break;
                case nct6795:
+                       fan5pin |= cr1b & BIT(5);
+                       fan5pin |= creb & BIT(5);
+
+                       fan6pin = (cr2a & BIT(4)) &&
+                                       (!dsw_en || (cred & BIT(4)));
+                       fan6pin |= creb & BIT(3);
+
+                       pwm5pin |= cr2d & BIT(7);
+                       pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
+
+                       pwm6pin = (cr2a & BIT(3)) && (cred & BIT(2));
+                       pwm6pin |= creb & BIT(2);
+                       break;
                case nct6796:
-                       regval_1b = superio_inb(sioreg, 0x1b);
-                       regval_2a = superio_inb(sioreg, 0x2a);
-                       regval_2f = superio_inb(sioreg, 0x2f);
-                       dsw_en = regval_2f & BIT(3);
+                       fan5pin |= cr1b & BIT(5);
+                       fan5pin |= (cre0 & BIT(3)) && !(cr1b & BIT(0));
+                       fan5pin |= creb & BIT(5);
 
-                       if (!pwm5pin)
-                               pwm5pin = regval & BIT(7);
+                       fan6pin = (cr2a & BIT(4)) &&
+                                       (!dsw_en || (cred & BIT(4)));
+                       fan6pin |= creb & BIT(3);
 
-                       if (!fan5pin)
-                               fan5pin = regval_1b & BIT(5);
+                       fan7pin = !(cr2b & BIT(2));
 
-                       superio_select(sioreg, NCT6775_LD_12);
-                       if (data->kind != nct6796) {
-                               int regval_eb = superio_inb(sioreg, 0xeb);
+                       pwm5pin |= cr2d & BIT(7);
+                       pwm5pin |= (cre0 & BIT(4)) && !(cr1b & BIT(0));
+                       pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
 
-                               if (!dsw_en) {
-                                       fan6pin = regval & BIT(1);
-                                       pwm6pin = regval & BIT(0);
-                               }
+                       pwm6pin = (cr2a & BIT(3)) && (cred & BIT(2));
+                       pwm6pin |= creb & BIT(2);
 
-                               if (!fan5pin)
-                                       fan5pin = regval_eb & BIT(5);
-                               if (!pwm5pin)
-                                       pwm5pin = (regval_eb & BIT(4)) &&
-                                               !(regval_2a & BIT(0));
-                               if (!fan6pin)
-                                       fan6pin = regval_eb & BIT(3);
-                               if (!pwm6pin)
-                                       pwm6pin = regval_eb & BIT(2);
-                       }
+                       pwm7pin = !(cr1d & (BIT(2) | BIT(3)));
+                       break;
+               case nct6797:
+                       fan5pin |= !ddr4_en && (cr1b & BIT(5));
+                       fan5pin |= creb & BIT(5);
 
-                       if (data->kind == nct6795 || data->kind == nct6796) {
-                               int regval_ed = superio_inb(sioreg, 0xed);
+                       fan6pin = cr2a & BIT(4);
+                       fan6pin |= creb & BIT(3);
 
-                               if (!fan6pin)
-                                       fan6pin = (regval_2a & BIT(4)) &&
-                                         (!dsw_en ||
-                                          (dsw_en && (regval_ed & BIT(4))));
-                               if (!pwm6pin)
-                                       pwm6pin = (regval_2a & BIT(3)) &&
-                                         (regval_ed & BIT(2));
-                       }
+                       fan7pin = cr1a & BIT(1);
 
-                       if (data->kind == nct6796) {
-                               int regval_1d = superio_inb(sioreg, 0x1d);
-                               int regval_2b = superio_inb(sioreg, 0x2b);
+                       pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
+                       pwm5pin |= !ddr4_en && (cr2d & BIT(7));
 
-                               fan7pin = !(regval_2b & BIT(2));
-                               pwm7pin = !(regval_1d & (BIT(2) | BIT(3)));
-                       }
+                       pwm6pin = creb & BIT(2);
+                       pwm6pin |= cred & BIT(2);
 
+                       pwm7pin = cr1d & BIT(4);
+                       break;
+               case nct6798:
+                       fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3));
+                       fan6pin |= cr2a & BIT(4);
+                       fan6pin |= creb & BIT(5);
+
+                       fan7pin = cr1b & BIT(5);
+                       fan7pin |= !(cr2b & BIT(2));
+                       fan7pin |= creb & BIT(3);
+
+                       pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4));
+                       pwm6pin |= !(cred & BIT(2)) && (cr2a & BIT(3));
+                       pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
+
+                       pwm7pin = !(cr1d & (BIT(2) | BIT(3)));
+                       pwm7pin |= cr2d & BIT(7);
+                       pwm7pin |= creb & BIT(2);
                        break;
                default:        /* NCT6779D */
                        break;
@@ -3943,8 +4047,12 @@ static int nct6775_probe(struct platform_device *pdev)
        case nct6793:
        case nct6795:
        case nct6796:
+       case nct6797:
+       case nct6798:
                data->in_num = 15;
-               data->pwm_num = (data->kind == nct6796) ? 7 : 6;
+               data->pwm_num = (data->kind == nct6796 ||
+                                data->kind == nct6797 ||
+                                data->kind == nct6798) ? 7 : 6;
                data->auto_pwm_num = 4;
                data->has_fan_div = false;
                data->temp_fixed_num = 6;
@@ -3978,6 +4086,7 @@ static int nct6775_probe(struct platform_device *pdev)
                        data->virt_temp_mask = NCT6793_VIRT_TEMP_MASK;
                        break;
                case nct6795:
+               case nct6797:
                        data->temp_label = nct6795_temp_label;
                        data->temp_mask = NCT6795_TEMP_MASK;
                        data->virt_temp_mask = NCT6795_VIRT_TEMP_MASK;
@@ -3987,6 +4096,11 @@ static int nct6775_probe(struct platform_device *pdev)
                        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;
                }
 
                data->REG_CONFIG = NCT6775_REG_CONFIG;
@@ -4256,6 +4370,8 @@ static int nct6775_probe(struct platform_device *pdev)
        case nct6793:
        case nct6795:
        case nct6796:
+       case nct6797:
+       case nct6798:
                break;
        }
 
@@ -4291,6 +4407,8 @@ static int nct6775_probe(struct platform_device *pdev)
                case nct6793:
                case nct6795:
                case nct6796:
+               case nct6797:
+               case nct6798:
                        tmp |= 0x7e;
                        break;
                }
@@ -4493,6 +4611,12 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
        case SIO_NCT6796_ID:
                sio_data->kind = nct6796;
                break;
+       case SIO_NCT6797_ID:
+               sio_data->kind = nct6797;
+               break;
+       case SIO_NCT6798_ID:
+               sio_data->kind = nct6798;
+               break;
        default:
                if (val != 0xffff)
                        pr_debug("unsupported chip ID: 0x%04x\n", val);
index b998f9fbed41e3fd854625f1a399936efd84835b..b3b907bdfb635ab37b0ea3699ed3b5b90c993385 100644 (file)
@@ -52,7 +52,7 @@
 
 /* Define the Counter Register, value = 100 for match 100% */
 #define NPCM7XX_PWM_COUNTER_DEFAULT_NUM                255
-#define NPCM7XX_PWM_CMR_DEFAULT_NUM            127
+#define NPCM7XX_PWM_CMR_DEFAULT_NUM            255
 #define NPCM7XX_PWM_CMR_MAX                    255
 
 /* default all PWM channels PRESCALE2 = 1 */
@@ -861,7 +861,7 @@ static int npcm7xx_create_pwm_cooling(struct device *dev,
                dev_err(dev, "Property 'cooling-levels' cannot be read.\n");
                return ret;
        }
-       snprintf(cdev->name, THERMAL_NAME_LENGTH, "%s%d", child->name,
+       snprintf(cdev->name, THERMAL_NAME_LENGTH, "%pOFn%d", child,
                 pwm_port);
 
        cdev->tcdev = thermal_of_cooling_device_register(child,
index a82018aaf4736582ec62ba329a80cefeae13b153..629cb45f8557a0dd936b0827056fb08c30ddd4e7 100644 (file)
@@ -5,7 +5,6 @@
 menuconfig PMBUS
        tristate "PMBus support"
        depends on I2C
-       default n
        help
          Say yes here if you want to enable PMBus support.
 
@@ -28,7 +27,6 @@ config SENSORS_PMBUS
 
 config SENSORS_ADM1275
        tristate "Analog Devices ADM1275 and compatibles"
-       default n
        help
          If you say yes here you get hardware monitoring support for Analog
          Devices ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1293,
@@ -49,7 +47,6 @@ config SENSORS_IBM_CFFPS
 
 config SENSORS_IR35221
        tristate "Infineon IR35221"
-       default n
        help
          If you say yes here you get hardware monitoring support for the
          Infineon IR35221 controller.
@@ -59,7 +56,6 @@ config SENSORS_IR35221
 
 config SENSORS_LM25066
        tristate "National Semiconductor LM25066 and compatibles"
-       default n
        help
          If you say yes here you get hardware monitoring support for National
          Semiconductor LM25056, LM25066, LM5064, and LM5066.
@@ -69,7 +65,6 @@ config SENSORS_LM25066
 
 config SENSORS_LTC2978
        tristate "Linear Technologies LTC2978 and compatibles"
-       default n
        help
          If you say yes here you get hardware monitoring support for Linear
          Technology LTC2974, LTC2975, LTC2977, LTC2978, LTC2980, LTC3880,
@@ -83,11 +78,11 @@ config SENSORS_LTC2978_REGULATOR
        depends on SENSORS_LTC2978 && REGULATOR
        help
          If you say yes here you get regulator support for Linear
-         Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
+         Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, LTM4676
+         and LTM4686.
 
 config SENSORS_LTC3815
        tristate "Linear Technologies LTC3815"
-       default n
        help
          If you say yes here you get hardware monitoring support for Linear
          Technology LTC3815.
@@ -97,7 +92,6 @@ config SENSORS_LTC3815
 
 config SENSORS_MAX16064
        tristate "Maxim MAX16064"
-       default n
        help
          If you say yes here you get hardware monitoring support for Maxim
          MAX16064.
@@ -107,7 +101,6 @@ config SENSORS_MAX16064
 
 config SENSORS_MAX20751
        tristate "Maxim MAX20751"
-       default n
        help
          If you say yes here you get hardware monitoring support for Maxim
          MAX20751.
@@ -117,7 +110,6 @@ config SENSORS_MAX20751
 
 config SENSORS_MAX31785
        tristate "Maxim MAX31785 and compatibles"
-       default n
        help
          If you say yes here you get hardware monitoring support for Maxim
          MAX31785.
@@ -127,7 +119,6 @@ config SENSORS_MAX31785
 
 config SENSORS_MAX34440
        tristate "Maxim MAX34440 and compatibles"
-       default n
        help
          If you say yes here you get hardware monitoring support for Maxim
          MAX34440, MAX34441, MAX34446, MAX34451, MAX34460, and MAX34461.
@@ -137,7 +128,6 @@ config SENSORS_MAX34440
 
 config SENSORS_MAX8688
        tristate "Maxim MAX8688"
-       default n
        help
          If you say yes here you get hardware monitoring support for Maxim
          MAX8688.
@@ -147,7 +137,6 @@ config SENSORS_MAX8688
 
 config SENSORS_TPS40422
        tristate "TI TPS40422"
-       default n
        help
          If you say yes here you get hardware monitoring support for TI
          TPS40422.
@@ -166,7 +155,6 @@ config SENSORS_TPS53679
 
 config SENSORS_UCD9000
        tristate "TI UCD90120, UCD90124, UCD90160, UCD9090, UCD90910"
-       default n
        help
          If you say yes here you get hardware monitoring support for TI
          UCD90120, UCD90124, UCD90160, UCD9090, UCD90910, Sequencer and System
@@ -177,7 +165,6 @@ config SENSORS_UCD9000
 
 config SENSORS_UCD9200
        tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
-       default n
        help
          If you say yes here you get hardware monitoring support for TI
          UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
@@ -188,7 +175,6 @@ config SENSORS_UCD9200
 
 config SENSORS_ZL6100
        tristate "Intersil ZL6100 and compatibles"
-       default n
        help
          If you say yes here you get hardware monitoring support for Intersil
          ZL2004, ZL2005, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, ZL6105,
index 58b789c28b483f062b17822a32487be6bdba14ee..07afb92bb36b6feac3a2d3191e93e5d7e9441dee 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2011 Ericsson AB.
  * Copyright (c) 2013, 2014, 2015 Guenter Roeck
  * Copyright (c) 2015 Linear Technology
+ * Copyright (c) 2018 Analog Devices Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,7 +29,7 @@
 #include "pmbus.h"
 
 enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
-       ltc3883, ltc3886, ltc3887, ltm2987, ltm4675, ltm4676 };
+       ltc3883, ltc3886, ltc3887, ltm2987, ltm4675, ltm4676, ltm4686 };
 
 /* Common for all chips */
 #define LTC2978_MFR_VOUT_PEAK          0xdd
@@ -81,6 +82,7 @@ enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
 #define LTM4676_ID_REV1                        0x4400
 #define LTM4676_ID_REV2                        0x4480
 #define LTM4676A_ID                    0x47e0
+#define LTM4686_ID                     0x4770
 
 #define LTC2974_NUM_PAGES              4
 #define LTC2978_NUM_PAGES              8
@@ -512,6 +514,7 @@ static const struct i2c_device_id ltc2978_id[] = {
        {"ltm2987", ltm2987},
        {"ltm4675", ltm4675},
        {"ltm4676", ltm4676},
+       {"ltm4686", ltm4686},
        {}
 };
 MODULE_DEVICE_TABLE(i2c, ltc2978_id);
@@ -588,6 +591,8 @@ static int ltc2978_get_id(struct i2c_client *client)
        else if (chip_id == LTM4676_ID_REV1 || chip_id == LTM4676_ID_REV2 ||
                 chip_id == LTM4676A_ID)
                return ltm4676;
+       else if (chip_id == LTM4686_ID)
+               return ltm4686;
 
        dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
        return -ENODEV;
@@ -684,6 +689,7 @@ static int ltc2978_probe(struct i2c_client *client,
        case ltc3887:
        case ltm4675:
        case ltm4676:
+       case ltm4686:
                data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
                info->read_word_data = ltc3880_read_word_data;
                info->pages = LTC3880_NUM_PAGES;
@@ -770,6 +776,7 @@ static const struct of_device_id ltc2978_of_match[] = {
        { .compatible = "lltc,ltm2987" },
        { .compatible = "lltc,ltm4675" },
        { .compatible = "lltc,ltm4676" },
+       { .compatible = "lltc,ltm4686" },
        { }
 };
 MODULE_DEVICE_TABLE(of, ltc2978_of_match);
index 7718e58dbda543d0687af136c53e551f799f349d..7688dab32f6e6088725d75427d9dccabba99f1fd 100644 (file)
@@ -118,6 +118,8 @@ static int pmbus_identify(struct i2c_client *client,
                } else {
                        info->pages = 1;
                }
+
+               pmbus_clear_faults(client);
        }
 
        if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) {
index 82c3754e21e337c83b4d7e3a12236da78500f370..2e2b5851139c2f9612d52b2db7efe23f8e57c96b 100644 (file)
@@ -2015,7 +2015,10 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
        if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
                client->flags |= I2C_CLIENT_PEC;
 
-       pmbus_clear_faults(client);
+       if (data->info->pages)
+               pmbus_clear_faults(client);
+       else
+               pmbus_clear_fault_page(client, -1);
 
        if (info->identify) {
                ret = (*info->identify)(client, info);
index 7838af58f92d51639570d4134b3a95e488d91225..7da6a160d45aca605ef0271e975855b36977cfb6 100644 (file)
@@ -221,8 +221,12 @@ static int pwm_fan_probe(struct platform_device *pdev)
 
        ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL);
        if (IS_ERR(ctx->pwm)) {
-               dev_err(&pdev->dev, "Could not get PWM\n");
-               return PTR_ERR(ctx->pwm);
+               ret = PTR_ERR(ctx->pwm);
+
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "Could not get PWM: %d\n", ret);
+
+               return ret;
        }
 
        platform_set_drvdata(pdev, ctx);
@@ -290,9 +294,19 @@ static int pwm_fan_remove(struct platform_device *pdev)
 static int pwm_fan_suspend(struct device *dev)
 {
        struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+       struct pwm_args args;
+       int ret;
+
+       pwm_get_args(ctx->pwm, &args);
+
+       if (ctx->pwm_value) {
+               ret = pwm_config(ctx->pwm, 0, args.period);
+               if (ret < 0)
+                       return ret;
 
-       if (ctx->pwm_value)
                pwm_disable(ctx->pwm);
+       }
+
        return 0;
 }
 
index 91976b6ca30002b985ef6594f82fcf10aabf91db..2e005edee0c951cc91d10fd37652271764dacf25 100644 (file)
@@ -56,7 +56,7 @@ scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
        const struct scmi_sensors *scmi_sensors = drvdata;
 
        sensor = *(scmi_sensors->info[type] + channel);
-       if (sensor && sensor->name)
+       if (sensor)
                return S_IRUGO;
 
        return 0;
index 7e49da50bc69b38b8758984c52298cc4db26c311..111d521e21897574b252f6eddf4ad4bd454502f4 100644 (file)
@@ -286,10 +286,8 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
                 * any thermal zones or if the thermal subsystem is
                 * not configured.
                 */
-               if (IS_ERR(z)) {
+               if (IS_ERR(z))
                        devm_kfree(dev, zone);
-                       continue;
-               }
        }
 
        return 0;
index 2be77752cd56b4a154a3d6603bf17d08267ea65e..c878242f3486625f986e4e30b102ab98a99479ad 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * sht15.c - support for the SHT15 Temperature and Humidity Sensor
  *
@@ -9,10 +10,6 @@
  *
  * Copyright (c) 2007 Wouter Horre
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * For further information, see the Documentation/hwmon/sht15 file.
  */
 
index e36399213324d9ab99e6d59f1ac1621445e2a9e2..8844c9565d2a49eae8cd4fcbc9c7fa828e914ccb 100644 (file)
@@ -226,8 +226,10 @@ static int tmp421_detect(struct i2c_client *client,
 {
        enum chips kind;
        struct i2c_adapter *adapter = client->adapter;
-       const char * const names[] = { "TMP421", "TMP422", "TMP423",
-                                      "TMP441", "TMP442" };
+       static const char * const names[] = {
+               "TMP421", "TMP422", "TMP423",
+               "TMP441", "TMP442"
+       };
        int addr = client->addr;
        u8 reg;
 
index 9493d4a388dbb9a3ac71b0fe9e56566eb90c8327..99e0c1b0b5fb3df7bf0c8ddd0a65ad8ad564a85f 100644 (file)
@@ -118,6 +118,7 @@ enum hwmon_in_attributes {
        hwmon_in_max_alarm,
        hwmon_in_lcrit_alarm,
        hwmon_in_crit_alarm,
+       hwmon_in_enable,
 };
 
 #define HWMON_I_INPUT          BIT(hwmon_in_input)
@@ -135,6 +136,7 @@ enum hwmon_in_attributes {
 #define HWMON_I_MAX_ALARM      BIT(hwmon_in_max_alarm)
 #define HWMON_I_LCRIT_ALARM    BIT(hwmon_in_lcrit_alarm)
 #define HWMON_I_CRIT_ALARM     BIT(hwmon_in_crit_alarm)
+#define HWMON_I_ENABLE         BIT(hwmon_in_enable)
 
 enum hwmon_curr_attributes {
        hwmon_curr_input,
diff --git a/include/trace/events/hwmon.h b/include/trace/events/hwmon.h
new file mode 100644 (file)
index 0000000..d7a1d0f
--- /dev/null
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hwmon
+
+#if !defined(_TRACE_HWMON_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HWMON_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(hwmon_attr_class,
+
+       TP_PROTO(int index, const char *attr_name, long val),
+
+       TP_ARGS(index, attr_name, val),
+
+       TP_STRUCT__entry(
+               __field(int, index)
+               __string(attr_name, attr_name)
+               __field(long, val)
+       ),
+
+       TP_fast_assign(
+               __entry->index = index;
+               __assign_str(attr_name, attr_name);
+               __entry->val = val;
+       ),
+
+       TP_printk("index=%d, attr_name=%s, val=%ld",
+                 __entry->index,  __get_str(attr_name), __entry->val)
+);
+
+DEFINE_EVENT(hwmon_attr_class, hwmon_attr_show,
+
+       TP_PROTO(int index, const char *attr_name, long val),
+
+       TP_ARGS(index, attr_name, val)
+);
+
+DEFINE_EVENT(hwmon_attr_class, hwmon_attr_store,
+
+       TP_PROTO(int index, const char *attr_name, long val),
+
+       TP_ARGS(index, attr_name, val)
+);
+
+TRACE_EVENT(hwmon_attr_show_string,
+
+       TP_PROTO(int index, const char *attr_name, const char *s),
+
+       TP_ARGS(index, attr_name, s),
+
+       TP_STRUCT__entry(
+               __field(int, index)
+               __string(attr_name, attr_name)
+               __string(label, s)
+       ),
+
+       TP_fast_assign(
+               __entry->index = index;
+               __assign_str(attr_name, attr_name);
+               __assign_str(label, s);
+       ),
+
+       TP_printk("index=%d, attr_name=%s, val=%s",
+                 __entry->index, __get_str(attr_name), __get_str(label))
+);
+
+#endif /* _TRACE_HWMON_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>