hwmon: (pmbus/max34440) Add support for MAX34451.

MAX34451 is a 16-Channel Voltage/Current Monitor and 12-Channel
Sequencer.

Signed-off-by: Kun Yi <kunyi@google.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Kun Yi 2018-07-03 15:26:49 -07:00 committed by Guenter Roeck
parent fb41a710f8
commit 7a001dbab4
3 changed files with 103 additions and 8 deletions

View File

@ -16,6 +16,11 @@ Supported chips:
Prefixes: 'max34446'
Addresses scanned: -
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34446.pdf
* Maxim MAX34451
PMBus 16-Channel V/I Monitor and 12-Channel Sequencer/Marginer
Prefixes: 'max34451'
Addresses scanned: -
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34451.pdf
* Maxim MAX34460
PMBus 12-Channel Voltage Monitor & Sequencer
Prefix: 'max34460'
@ -36,9 +41,10 @@ Description
This driver supports hardware monitoring for Maxim MAX34440 PMBus 6-Channel
Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply Manager
and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data Logger.
It also supports the MAX34460 and MAX34461 PMBus Voltage Monitor & Sequencers.
The MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 voltage
channels.
It also supports the MAX34451, MAX34460, and MAX34461 PMBus Voltage Monitor &
Sequencers. The MAX34451 supports monitoring voltage or current of 12 channels
based on GIN pins. The MAX34460 supports 12 voltage channels, and the MAX34461
supports 16 voltage channels.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
@ -93,7 +99,7 @@ curr[1-6]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr[1-6]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
curr[1-6]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
curr[1-6]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
curr[1-4]_average Historical average current (MAX34446 only).
curr[1-4]_average Historical average current (MAX34446/34451 only).
curr[1-6]_highest Historical maximum current.
curr[1-6]_reset_history Write any value to reset history.
@ -123,5 +129,7 @@ temp[1-8]_reset_history Write any value to reset history.
temp7 and temp8 attributes only exist for MAX34440.
MAX34446 only supports temp[1-3].
MAX34451 supports attribute groups in[1-16] (or curr[1-16] based on input pins)
and temp[1-5].
MAX34460 supports attribute groups in[1-12] and temp[1-5].
MAX34461 supports attribute groups in[1-16] and temp[1-5].

View File

@ -130,7 +130,7 @@ config SENSORS_MAX34440
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX34440, MAX34441, MAX34446, MAX34460, and MAX34461.
MAX34440, MAX34441, MAX34446, MAX34451, MAX34460, and MAX34461.
This driver can also be built as a module. If so, the module will
be called max34440.

View File

@ -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 011)
* 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},
{}