]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hwmon: (pmbus/max34440) Fix support for max34451
authorAlexis Czezar Torreno <alexisczezar.torreno@analog.com>
Mon, 7 Apr 2025 03:47:24 +0000 (11:47 +0800)
committerGuenter Roeck <linux@roeck-us.net>
Wed, 23 Apr 2025 14:18:27 +0000 (07:18 -0700)
The max344** family has an issue with some PMBUS address being switched.
This includes max34451 however version MAX34451-NA6 and later has this
issue fixed and this commit supports that update.

Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
Link: https://lore.kernel.org/r/20250407-dev_adpm12160-v3-1-9cd3095445c8@analog.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/max34440.c

index c9dda33831ff24e7b5e2fd1956a65e6bd2bfcbb9..d6d556b0138532f0a55ffe73eae760cf41aa4ab8 100644 (file)
@@ -34,16 +34,21 @@ enum chips { max34440, max34441, max34446, max34451, max34460, max34461 };
 /*
  * The whole max344* family have IOUT_OC_WARN_LIMIT and IOUT_OC_FAULT_LIMIT
  * swapped from the standard pmbus spec addresses.
+ * For max34451, version MAX34451ETNA6+ and later has this issue fixed.
  */
 #define MAX34440_IOUT_OC_WARN_LIMIT    0x46
 #define MAX34440_IOUT_OC_FAULT_LIMIT   0x4A
 
+#define MAX34451ETNA6_MFR_REV          0x0012
+
 #define MAX34451_MFR_CHANNEL_CONFIG    0xe4
 #define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK   0x3f
 
 struct max34440_data {
        int id;
        struct pmbus_driver_info info;
+       u8 iout_oc_warn_limit;
+       u8 iout_oc_fault_limit;
 };
 
 #define to_max34440_data(x)  container_of(x, struct max34440_data, info)
@@ -60,11 +65,11 @@ static int max34440_read_word_data(struct i2c_client *client, int page,
        switch (reg) {
        case PMBUS_IOUT_OC_FAULT_LIMIT:
                ret = pmbus_read_word_data(client, page, phase,
-                                          MAX34440_IOUT_OC_FAULT_LIMIT);
+                                          data->iout_oc_fault_limit);
                break;
        case PMBUS_IOUT_OC_WARN_LIMIT:
                ret = pmbus_read_word_data(client, page, phase,
-                                          MAX34440_IOUT_OC_WARN_LIMIT);
+                                          data->iout_oc_warn_limit);
                break;
        case PMBUS_VIRT_READ_VOUT_MIN:
                ret = pmbus_read_word_data(client, page, phase,
@@ -133,11 +138,11 @@ static int max34440_write_word_data(struct i2c_client *client, int page,
 
        switch (reg) {
        case PMBUS_IOUT_OC_FAULT_LIMIT:
-               ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_FAULT_LIMIT,
+               ret = pmbus_write_word_data(client, page, data->iout_oc_fault_limit,
                                            word);
                break;
        case PMBUS_IOUT_OC_WARN_LIMIT:
-               ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_WARN_LIMIT,
+               ret = pmbus_write_word_data(client, page, data->iout_oc_warn_limit,
                                            word);
                break;
        case PMBUS_VIRT_RESET_POUT_HISTORY:
@@ -235,6 +240,25 @@ static int max34451_set_supported_funcs(struct i2c_client *client,
         */
 
        int page, rv;
+       bool max34451_na6 = false;
+
+       rv = i2c_smbus_read_word_data(client, PMBUS_MFR_REVISION);
+       if (rv < 0)
+               return rv;
+
+       if (rv >= MAX34451ETNA6_MFR_REV) {
+               max34451_na6 = true;
+               data->info.format[PSC_VOLTAGE_IN] = direct;
+               data->info.format[PSC_CURRENT_IN] = direct;
+               data->info.m[PSC_VOLTAGE_IN] = 1;
+               data->info.b[PSC_VOLTAGE_IN] = 0;
+               data->info.R[PSC_VOLTAGE_IN] = 3;
+               data->info.m[PSC_CURRENT_IN] = 1;
+               data->info.b[PSC_CURRENT_IN] = 0;
+               data->info.R[PSC_CURRENT_IN] = 2;
+               data->iout_oc_fault_limit = PMBUS_IOUT_OC_FAULT_LIMIT;
+               data->iout_oc_warn_limit = PMBUS_IOUT_OC_WARN_LIMIT;
+       }
 
        for (page = 0; page < 16; page++) {
                rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
@@ -251,16 +275,30 @@ static int max34451_set_supported_funcs(struct i2c_client *client,
                case 0x20:
                        data->info.func[page] = PMBUS_HAVE_VOUT |
                                PMBUS_HAVE_STATUS_VOUT;
+
+                       if (max34451_na6)
+                               data->info.func[page] |= PMBUS_HAVE_VIN |
+                                       PMBUS_HAVE_STATUS_INPUT;
                        break;
                case 0x21:
                        data->info.func[page] = PMBUS_HAVE_VOUT;
+
+                       if (max34451_na6)
+                               data->info.func[page] |= PMBUS_HAVE_VIN;
                        break;
                case 0x22:
                        data->info.func[page] = PMBUS_HAVE_IOUT |
                                PMBUS_HAVE_STATUS_IOUT;
+
+                       if (max34451_na6)
+                               data->info.func[page] |= PMBUS_HAVE_IIN |
+                                       PMBUS_HAVE_STATUS_INPUT;
                        break;
                case 0x23:
                        data->info.func[page] = PMBUS_HAVE_IOUT;
+
+                       if (max34451_na6)
+                               data->info.func[page] |= PMBUS_HAVE_IIN;
                        break;
                default:
                        break;
@@ -494,6 +532,8 @@ static int max34440_probe(struct i2c_client *client)
                return -ENOMEM;
        data->id = i2c_match_id(max34440_id, client)->driver_data;
        data->info = max34440_info[data->id];
+       data->iout_oc_fault_limit = MAX34440_IOUT_OC_FAULT_LIMIT;
+       data->iout_oc_warn_limit = MAX34440_IOUT_OC_WARN_LIMIT;
 
        if (data->id == max34451) {
                rv = max34451_set_supported_funcs(client, data);