diff options
Diffstat (limited to 'drivers/hwmon/pmbus/max34440.c')
-rw-r--r-- | drivers/hwmon/pmbus/max34440.c | 93 |
1 files changed, 90 insertions, 3 deletions
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c index 74a1f6f68fb3..47576c460010 100644 --- a/drivers/hwmon/pmbus/max34440.c +++ b/drivers/hwmon/pmbus/max34440.c @@ -27,7 +27,7 @@ #include <linux/i2c.h> #include "pmbus.h" -enum chips { max34440, max34441, max34446, max34460, max34461 }; +enum chips { max34440, max34441, max34446, max34451, max34460, max34461 }; #define MAX34440_MFR_VOUT_PEAK 0xd4 #define MAX34440_MFR_IOUT_PEAK 0xd5 @@ -44,6 +44,9 @@ enum chips { max34440, max34441, max34446, max34460, max34461 }; #define MAX34440_STATUS_OT_FAULT BIT(5) #define MAX34440_STATUS_OT_WARN BIT(6) +#define MAX34451_MFR_CHANNEL_CONFIG 0xe4 +#define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK 0x3f + struct max34440_data { int id; struct pmbus_driver_info info; @@ -67,7 +70,7 @@ static int max34440_read_word_data(struct i2c_client *client, int page, int reg) MAX34440_MFR_VOUT_PEAK); break; case PMBUS_VIRT_READ_IOUT_AVG: - if (data->id != max34446) + if (data->id != max34446 && data->id != max34451) return -ENXIO; ret = pmbus_read_word_data(client, page, MAX34446_MFR_IOUT_AVG); @@ -143,7 +146,7 @@ static int max34440_write_word_data(struct i2c_client *client, int page, case PMBUS_VIRT_RESET_IOUT_HISTORY: ret = pmbus_write_word_data(client, page, MAX34440_MFR_IOUT_PEAK, 0); - if (!ret && data->id == max34446) + if (!ret && (data->id == max34446 || data->id == max34451)) ret = pmbus_write_word_data(client, page, MAX34446_MFR_IOUT_AVG, 0); @@ -202,6 +205,58 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) return ret; } +static int max34451_set_supported_funcs(struct i2c_client *client, + struct max34440_data *data) +{ + /* + * Each of the channel 0-15 can be configured to monitor the following + * functions based on MFR_CHANNEL_CONFIG[5:0] + * 0x10: Sequencing + voltage monitoring (only valid for PAGES 0–11) + * 0x20: Voltage monitoring (no sequencing) + * 0x21: Voltage read only + * 0x22: Current monitoring + * 0x23: Current read only + * 0x30: General-purpose input active low + * 0x34: General-purpose input active high + * 0x00: Disabled + */ + + int page, rv; + + for (page = 0; page < 16; page++) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + if (rv < 0) + return rv; + + rv = i2c_smbus_read_word_data(client, + MAX34451_MFR_CHANNEL_CONFIG); + if (rv < 0) + return rv; + + switch (rv & MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK) { + case 0x10: + case 0x20: + data->info.func[page] = PMBUS_HAVE_VOUT | + PMBUS_HAVE_STATUS_VOUT; + break; + case 0x21: + data->info.func[page] = PMBUS_HAVE_VOUT; + break; + case 0x22: + data->info.func[page] = PMBUS_HAVE_IOUT | + PMBUS_HAVE_STATUS_IOUT; + break; + case 0x23: + data->info.func[page] = PMBUS_HAVE_IOUT; + break; + default: + break; + } + } + + return 0; +} + static struct pmbus_driver_info max34440_info[] = { [max34440] = { .pages = 14, @@ -325,6 +380,30 @@ static struct pmbus_driver_info max34440_info[] = { .read_word_data = max34440_read_word_data, .write_word_data = max34440_write_word_data, }, + [max34451] = { + .pages = 21, + .format[PSC_VOLTAGE_OUT] = direct, + .format[PSC_TEMPERATURE] = direct, + .format[PSC_CURRENT_OUT] = direct, + .m[PSC_VOLTAGE_OUT] = 1, + .b[PSC_VOLTAGE_OUT] = 0, + .R[PSC_VOLTAGE_OUT] = 3, + .m[PSC_CURRENT_OUT] = 1, + .b[PSC_CURRENT_OUT] = 0, + .R[PSC_CURRENT_OUT] = 2, + .m[PSC_TEMPERATURE] = 1, + .b[PSC_TEMPERATURE] = 0, + .R[PSC_TEMPERATURE] = 2, + /* func 0-15 is set dynamically before probing */ + .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .read_byte_data = max34440_read_byte_data, + .read_word_data = max34440_read_word_data, + .write_word_data = max34440_write_word_data, + }, [max34460] = { .pages = 18, .format[PSC_VOLTAGE_OUT] = direct, @@ -398,6 +477,7 @@ static int max34440_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max34440_data *data; + int rv; data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), GFP_KERNEL); @@ -406,6 +486,12 @@ static int max34440_probe(struct i2c_client *client, data->id = id->driver_data; data->info = max34440_info[id->driver_data]; + if (data->id == max34451) { + rv = max34451_set_supported_funcs(client, data); + if (rv) + return rv; + } + return pmbus_do_probe(client, id, &data->info); } @@ -413,6 +499,7 @@ static const struct i2c_device_id max34440_id[] = { {"max34440", max34440}, {"max34441", max34441}, {"max34446", max34446}, + {"max34451", max34451}, {"max34460", max34460}, {"max34461", max34461}, {} |