|
@@ -27,7 +27,7 @@
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c.h>
|
|
#include "pmbus.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_VOUT_PEAK 0xd4
|
|
#define MAX34440_MFR_IOUT_PEAK 0xd5
|
|
#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_FAULT BIT(5)
|
|
#define MAX34440_STATUS_OT_WARN BIT(6)
|
|
#define MAX34440_STATUS_OT_WARN BIT(6)
|
|
|
|
|
|
|
|
+#define MAX34451_MFR_CHANNEL_CONFIG 0xe4
|
|
|
|
+#define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK 0x3f
|
|
|
|
+
|
|
struct max34440_data {
|
|
struct max34440_data {
|
|
int id;
|
|
int id;
|
|
struct pmbus_driver_info info;
|
|
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);
|
|
MAX34440_MFR_VOUT_PEAK);
|
|
break;
|
|
break;
|
|
case PMBUS_VIRT_READ_IOUT_AVG:
|
|
case PMBUS_VIRT_READ_IOUT_AVG:
|
|
- if (data->id != max34446)
|
|
|
|
|
|
+ if (data->id != max34446 && data->id != max34451)
|
|
return -ENXIO;
|
|
return -ENXIO;
|
|
ret = pmbus_read_word_data(client, page,
|
|
ret = pmbus_read_word_data(client, page,
|
|
MAX34446_MFR_IOUT_AVG);
|
|
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:
|
|
case PMBUS_VIRT_RESET_IOUT_HISTORY:
|
|
ret = pmbus_write_word_data(client, page,
|
|
ret = pmbus_write_word_data(client, page,
|
|
MAX34440_MFR_IOUT_PEAK, 0);
|
|
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,
|
|
ret = pmbus_write_word_data(client, page,
|
|
MAX34446_MFR_IOUT_AVG, 0);
|
|
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;
|
|
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[] = {
|
|
static struct pmbus_driver_info max34440_info[] = {
|
|
[max34440] = {
|
|
[max34440] = {
|
|
.pages = 14,
|
|
.pages = 14,
|
|
@@ -325,6 +380,30 @@ static struct pmbus_driver_info max34440_info[] = {
|
|
.read_word_data = max34440_read_word_data,
|
|
.read_word_data = max34440_read_word_data,
|
|
.write_word_data = max34440_write_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] = {
|
|
[max34460] = {
|
|
.pages = 18,
|
|
.pages = 18,
|
|
.format[PSC_VOLTAGE_OUT] = direct,
|
|
.format[PSC_VOLTAGE_OUT] = direct,
|
|
@@ -398,6 +477,7 @@ static int max34440_probe(struct i2c_client *client,
|
|
const struct i2c_device_id *id)
|
|
const struct i2c_device_id *id)
|
|
{
|
|
{
|
|
struct max34440_data *data;
|
|
struct max34440_data *data;
|
|
|
|
+ int rv;
|
|
|
|
|
|
data = devm_kzalloc(&client->dev, sizeof(struct max34440_data),
|
|
data = devm_kzalloc(&client->dev, sizeof(struct max34440_data),
|
|
GFP_KERNEL);
|
|
GFP_KERNEL);
|
|
@@ -406,6 +486,12 @@ static int max34440_probe(struct i2c_client *client,
|
|
data->id = id->driver_data;
|
|
data->id = id->driver_data;
|
|
data->info = max34440_info[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);
|
|
return pmbus_do_probe(client, id, &data->info);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -413,6 +499,7 @@ static const struct i2c_device_id max34440_id[] = {
|
|
{"max34440", max34440},
|
|
{"max34440", max34440},
|
|
{"max34441", max34441},
|
|
{"max34441", max34441},
|
|
{"max34446", max34446},
|
|
{"max34446", max34446},
|
|
|
|
+ {"max34451", max34451},
|
|
{"max34460", max34460},
|
|
{"max34460", max34460},
|
|
{"max34461", max34461},
|
|
{"max34461", max34461},
|
|
{}
|
|
{}
|