hwmon: (pmbus) Detect if chip is write protected
authorGuenter Roeck <linux@roeck-us.net>
Thu, 12 Dec 2019 17:14:34 +0000 (09:14 -0800)
committerGuenter Roeck <linux@roeck-us.net>
Thu, 23 Jan 2020 21:15:09 +0000 (13:15 -0800)
If a chip is write protected, we can not change any limits, and we can
not clear status flags. This may be the reason why clearing status flags
is reported to not work for some chips. Detect the condition in the pmbus
core. If the chip is write protected, set limit attributes as read-only,
and set the flag indicating that the status flag should be ignored.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/pmbus.h
drivers/hwmon/pmbus/pmbus_core.c
include/linux/pmbus.h

index d198af3a92b6fd03a18f4b0a6f15a69f03dd6cc9..90d6c9e23d5fcfdba13d45a8df4aed6a7f7b48b8 100644 (file)
@@ -22,6 +22,8 @@ enum pmbus_regs {
        PMBUS_CLEAR_FAULTS              = 0x03,
        PMBUS_PHASE                     = 0x04,
 
+       PMBUS_WRITE_PROTECT             = 0x10,
+
        PMBUS_CAPABILITY                = 0x19,
        PMBUS_QUERY                     = 0x1A,
 
@@ -225,6 +227,15 @@ enum pmbus_regs {
  */
 #define PB_OPERATION_CONTROL_ON                BIT(7)
 
+/*
+ * WRITE_PROTECT
+ */
+#define PB_WP_ALL      BIT(7)  /* all but WRITE_PROTECT */
+#define PB_WP_OP       BIT(6)  /* all but WP, OPERATION, PAGE */
+#define PB_WP_VOUT     BIT(5)  /* all but WP, OPERATION, PAGE, VOUT, ON_OFF */
+
+#define PB_WP_ANY      (PB_WP_ALL | PB_WP_OP | PB_WP_VOUT)
+
 /*
  * CAPABILITY
  */
index 8470097907bc20d9bf7189793056e3b8e9754efd..2c196eddbb8d8700637b99e8fdbdf56a14572d1e 100644 (file)
@@ -1088,6 +1088,9 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
                snprintf(sensor->name, sizeof(sensor->name), "%s%d",
                         name, seq);
 
+       if (data->flags & PMBUS_WRITE_PROTECTED)
+               readonly = true;
+
        sensor->page = page;
        sensor->reg = reg;
        sensor->class = class;
@@ -2141,6 +2144,15 @@ 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;
 
+       /*
+        * Check if the chip is write protected. If it is, we can not clear
+        * faults, and we should not try it. Also, in that case, writes into
+        * limit registers need to be disabled.
+        */
+       ret = i2c_smbus_read_byte_data(client, PMBUS_WRITE_PROTECT);
+       if (ret > 0 && (ret & PB_WP_ANY))
+               data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
+
        if (data->info->pages)
                pmbus_clear_faults(client);
        else
index 08468fca5ea2e18619346e07dc0b3e76e6779d86..1ea5bae708a154c739d40c64c716128513adb84f 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _PMBUS_H_
 #define _PMBUS_H_
 
+#include <linux/bits.h>
+
 /* flags */
 
 /*
  * communication errors for no explicable reason. For such chips, checking
  * the status register must be disabled.
  */
-#define PMBUS_SKIP_STATUS_CHECK        (1 << 0)
+#define PMBUS_SKIP_STATUS_CHECK        BIT(0)
+
+/*
+ * PMBUS_WRITE_PROTECTED
+ * Set if the chip is write protected and write protection is not determined
+ * by the standard WRITE_PROTECT command.
+ */
+#define PMBUS_WRITE_PROTECTED  BIT(1)
 
 struct pmbus_platform_data {
        u32 flags;              /* Device specific flags */