hwmon: (pmbus/mp2975) Fix IRQ masking
authorPatrick Rudolph <patrick.rudolph@9elements.com>
Mon, 18 Mar 2024 17:44:05 +0000 (23:14 +0530)
committerGuenter Roeck <linux@roeck-us.net>
Sun, 28 Apr 2024 17:07:34 +0000 (10:07 -0700)
The MP2971/MP2973 use a custom 16bit register format for
SMBALERT_MASK which doesn't follow the PMBUS specification.

Map the PMBUS defined bits used by the common code onto the custom
format used by MPS and since the SMBALERT_MASK is currently never read
by common code only implement the mapping for write transactions.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Signed-off-by: Naresh Solanki <naresh.solanki@9elements.com>
Link: https://lore.kernel.org/r/20240318174406.3782306-1-naresh.solanki@9elements.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/mp2975.c

index e5fa10b3b8bc7184e03e6caa0701e34f81bcb7cb..953c02a2aeb596c66079a3d050fdd22831ea3876 100644 (file)
@@ -392,6 +392,82 @@ static int mp2973_read_word_data(struct i2c_client *client, int page,
        return ret;
 }
 
+static int mp2973_write_word_data(struct i2c_client *client, int page,
+                                 int reg, u16 word)
+{
+       u8 target, mask;
+       int ret;
+
+       if (reg != PMBUS_SMBALERT_MASK)
+               return -ENODATA;
+
+       /*
+        * Vendor-specific SMBALERT_MASK register with 16 maskable bits.
+        */
+       ret = pmbus_read_word_data(client, 0, 0, PMBUS_SMBALERT_MASK);
+       if (ret < 0)
+               return ret;
+
+       target = word & 0xff;
+       mask = word >> 8;
+
+/*
+ * Set/Clear 'bit' in 'ret' based on condition followed by define for each bit in SMBALERT_MASK.
+ * Also bit 2 & 15 are reserved.
+ */
+#define SWAP(val, mask, cond, bit) (((mask) & (cond)) ? ((val) & ~BIT(bit)) : ((val) | BIT(bit)))
+
+#define MP2973_TEMP_OT         0
+#define MP2973_VIN_UVLO                1
+#define MP2973_VIN_OVP         3
+#define MP2973_MTP_FAULT       4
+#define MP2973_OTHER_COMM      5
+#define MP2973_MTP_BLK_TRIG    6
+#define MP2973_PACKET_ERROR    7
+#define MP2973_INVALID_DATA    8
+#define MP2973_INVALID_COMMAND 9
+#define MP2973_IOUT_OC_LV      10
+#define MP2973_IOUT_OC         11
+#define MP2973_VOUT_MAX_MIN_WARNING 12
+#define MP2973_VOLTAGE_UV      13
+#define MP2973_VOLTAGE_OV      14
+
+       switch (target) {
+       case PMBUS_STATUS_CML:
+               ret = SWAP(ret, mask, PB_CML_FAULT_INVALID_DATA, MP2973_INVALID_DATA);
+               ret = SWAP(ret, mask, PB_CML_FAULT_INVALID_COMMAND,  MP2973_INVALID_COMMAND);
+               ret = SWAP(ret, mask, PB_CML_FAULT_OTHER_COMM, MP2973_OTHER_COMM);
+               ret = SWAP(ret, mask, PB_CML_FAULT_PACKET_ERROR, MP2973_PACKET_ERROR);
+               break;
+       case PMBUS_STATUS_VOUT:
+               ret = SWAP(ret, mask, PB_VOLTAGE_UV_FAULT, MP2973_VOLTAGE_UV);
+               ret = SWAP(ret, mask, PB_VOLTAGE_OV_FAULT, MP2973_VOLTAGE_OV);
+               break;
+       case PMBUS_STATUS_IOUT:
+               ret = SWAP(ret, mask, PB_IOUT_OC_FAULT, MP2973_IOUT_OC);
+               ret = SWAP(ret, mask, PB_IOUT_OC_LV_FAULT, MP2973_IOUT_OC_LV);
+               break;
+       case PMBUS_STATUS_TEMPERATURE:
+               ret = SWAP(ret, mask, PB_TEMP_OT_FAULT, MP2973_TEMP_OT);
+               break;
+       /*
+        * Map remaining bits to MFR specific to let the PMBUS core mask
+        * those bits by default.
+        */
+       case PMBUS_STATUS_MFR_SPECIFIC:
+               ret = SWAP(ret, mask, BIT(1), MP2973_VIN_UVLO);
+               ret = SWAP(ret, mask, BIT(3), MP2973_VIN_OVP);
+               ret = SWAP(ret, mask, BIT(4), MP2973_MTP_FAULT);
+               ret = SWAP(ret, mask, BIT(6), MP2973_MTP_BLK_TRIG);
+               break;
+       default:
+               return 0;
+       }
+#undef SWAP
+
+       return pmbus_write_word_data(client, 0, PMBUS_SMBALERT_MASK, ret);
+}
+
 static int mp2975_read_word_data(struct i2c_client *client, int page,
                                 int phase, int reg)
 {
@@ -907,6 +983,7 @@ static struct pmbus_driver_info mp2973_info = {
                PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
                PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
        .read_word_data = mp2973_read_word_data,
+       .write_word_data = mp2973_write_word_data,
 #if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
        .num_regulators = 1,
        .reg_desc = mp2975_reg_desc,