summaryrefslogtreecommitdiff
path: root/drivers/hwmon/pmbus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r--drivers/hwmon/pmbus/Kconfig20
-rw-r--r--drivers/hwmon/pmbus/Makefile1
-rw-r--r--drivers/hwmon/pmbus/adm1275.c358
-rw-r--r--drivers/hwmon/pmbus/lm25066.c7
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c482
-rw-r--r--drivers/hwmon/pmbus/max20751.c64
-rw-r--r--drivers/hwmon/pmbus/max34440.c9
-rw-r--r--drivers/hwmon/pmbus/max8688.c19
-rw-r--r--drivers/hwmon/pmbus/pmbus.c5
-rw-r--r--drivers/hwmon/pmbus/pmbus.h448
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c31
-rw-r--r--drivers/hwmon/pmbus/zl6100.c11
12 files changed, 989 insertions, 466 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 9f7dbd189..df6ebb2b8 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -20,7 +20,8 @@ config SENSORS_PMBUS
help
If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
- MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, and TPS40400.
+ MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, TPS40400, TPS544B20,
+ TPS544B25, TPS544C20, TPS544C25, and UDT020.
This driver can also be built as a module. If so, the module will
be called pmbus.
@@ -30,8 +31,8 @@ config SENSORS_ADM1275
default n
help
If you say yes here you get hardware monitoring support for Analog
- Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital
- Power Monitors.
+ Devices ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 Hot-Swap
+ Controller and Digital Power Monitors.
This driver can also be built as a module. If so, the module will
be called adm1275.
@@ -51,7 +52,8 @@ config SENSORS_LTC2978
default n
help
If you say yes here you get hardware monitoring support for Linear
- Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
+ Technology LTC2974, LTC2975, LTC2977, LTC2978, LTC2980, LTC3880,
+ LTC3883, LTC3886, LTC3887, LTCM2987, LTM4675, and LTM4676.
This driver can also be built as a module. If so, the module will
be called ltc2978.
@@ -73,6 +75,16 @@ config SENSORS_MAX16064
This driver can also be built as a module. If so, the module will
be called max16064.
+config SENSORS_MAX20751
+ tristate "Maxim MAX20751"
+ default n
+ help
+ If you say yes here you get hardware monitoring support for Maxim
+ MAX20751.
+
+ This driver can also be built as a module. If so, the module will
+ be called max20751.
+
config SENSORS_MAX34440
tristate "Maxim MAX34440 and compatibles"
default n
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 1454293e9..bce046d37 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
+obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index 60aad9570..188af4c89 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -21,46 +21,120 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/bitops.h>
#include "pmbus.h"
-enum chips { adm1075, adm1275, adm1276 };
+enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
+
+#define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0)
+#define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5)
+#define ADM1293_MFR_STATUS_VAUX_OV_WARN BIT(6)
#define ADM1275_PEAK_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1
#define ADM1275_PEAK_VOUT 0xd2
#define ADM1275_PMON_CONFIG 0xd4
-#define ADM1275_VIN_VOUT_SELECT (1 << 6)
-#define ADM1275_VRANGE (1 << 5)
-#define ADM1075_IRANGE_50 (1 << 4)
-#define ADM1075_IRANGE_25 (1 << 3)
-#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4))
+#define ADM1275_VIN_VOUT_SELECT BIT(6)
+#define ADM1275_VRANGE BIT(5)
+#define ADM1075_IRANGE_50 BIT(4)
+#define ADM1075_IRANGE_25 BIT(3)
+#define ADM1075_IRANGE_MASK (BIT(3) | BIT(4))
+
+#define ADM1293_IRANGE_25 0
+#define ADM1293_IRANGE_50 BIT(6)
+#define ADM1293_IRANGE_100 BIT(7)
+#define ADM1293_IRANGE_200 (BIT(6) | BIT(7))
+#define ADM1293_IRANGE_MASK (BIT(6) | BIT(7))
+
+#define ADM1293_VIN_SEL_012 BIT(2)
+#define ADM1293_VIN_SEL_074 BIT(3)
+#define ADM1293_VIN_SEL_210 (BIT(2) | BIT(3))
+#define ADM1293_VIN_SEL_MASK (BIT(2) | BIT(3))
+
+#define ADM1293_VAUX_EN BIT(1)
#define ADM1275_IOUT_WARN2_LIMIT 0xd7
#define ADM1275_DEVICE_CONFIG 0xd8
-#define ADM1275_IOUT_WARN2_SELECT (1 << 4)
+#define ADM1275_IOUT_WARN2_SELECT BIT(4)
#define ADM1276_PEAK_PIN 0xda
-
-#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
-
#define ADM1075_READ_VAUX 0xdd
#define ADM1075_VAUX_OV_WARN_LIMIT 0xde
#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf
+#define ADM1293_IOUT_MIN 0xe3
+#define ADM1293_PIN_MIN 0xe4
#define ADM1075_VAUX_STATUS 0xf6
-#define ADM1075_VAUX_OV_WARN (1<<7)
-#define ADM1075_VAUX_UV_WARN (1<<6)
+#define ADM1075_VAUX_OV_WARN BIT(7)
+#define ADM1075_VAUX_UV_WARN BIT(6)
struct adm1275_data {
int id;
bool have_oc_fault;
+ bool have_uc_fault;
+ bool have_vout;
+ bool have_vaux_status;
+ bool have_mfr_vaux_status;
+ bool have_iout_min;
+ bool have_pin_min;
+ bool have_pin_max;
struct pmbus_driver_info info;
};
#define to_adm1275_data(x) container_of(x, struct adm1275_data, info)
+struct coefficients {
+ s16 m;
+ s16 b;
+ s16 R;
+};
+
+static const struct coefficients adm1075_coefficients[] = {
+ [0] = { 27169, 0, -1 }, /* voltage */
+ [1] = { 806, 20475, -1 }, /* current, irange25 */
+ [2] = { 404, 20475, -1 }, /* current, irange50 */
+ [3] = { 0, -1, 8549 }, /* power, irange25 */
+ [4] = { 0, -1, 4279 }, /* power, irange50 */
+};
+
+static const struct coefficients adm1275_coefficients[] = {
+ [0] = { 19199, 0, -2 }, /* voltage, vrange set */
+ [1] = { 6720, 0, -1 }, /* voltage, vrange not set */
+ [2] = { 807, 20475, -1 }, /* current */
+};
+
+static const struct coefficients adm1276_coefficients[] = {
+ [0] = { 19199, 0, -2 }, /* voltage, vrange set */
+ [1] = { 6720, 0, -1 }, /* voltage, vrange not set */
+ [2] = { 807, 20475, -1 }, /* current */
+ [3] = { 6043, 0, -2 }, /* power, vrange set */
+ [4] = { 2115, 0, -1 }, /* power, vrange not set */
+};
+
+static const struct coefficients adm1293_coefficients[] = {
+ [0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */
+ [1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */
+ [2] = { 19604, -50, -2 }, /* voltage, vrange 21V */
+ [3] = { 8000, -100, -2 }, /* current, irange25 */
+ [4] = { 4000, -100, -2 }, /* current, irange50 */
+ [5] = { 20000, -1000, -3 }, /* current, irange100 */
+ [6] = { 10000, -1000, -3 }, /* current, irange200 */
+ [7] = { 10417, 0, -1 }, /* power, 1.2V, irange25 */
+ [8] = { 5208, 0, -1 }, /* power, 1.2V, irange50 */
+ [9] = { 26042, 0, -2 }, /* power, 1.2V, irange100 */
+ [10] = { 13021, 0, -2 }, /* power, 1.2V, irange200 */
+ [11] = { 17351, 0, -2 }, /* power, 7.4V, irange25 */
+ [12] = { 8676, 0, -2 }, /* power, 7.4V, irange50 */
+ [13] = { 4338, 0, -2 }, /* power, 7.4V, irange100 */
+ [14] = { 21689, 0, -3 }, /* power, 7.4V, irange200 */
+ [15] = { 6126, 0, -2 }, /* power, 21V, irange25 */
+ [16] = { 30631, 0, -3 }, /* power, 21V, irange50 */
+ [17] = { 15316, 0, -3 }, /* power, 21V, irange100 */
+ [18] = { 7658, 0, -3 }, /* power, 21V, irange200 */
+};
+
static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -72,42 +146,37 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_IOUT_UC_FAULT_LIMIT:
- if (data->have_oc_fault) {
- ret = -ENXIO;
- break;
- }
+ if (!data->have_uc_fault)
+ return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
break;
case PMBUS_IOUT_OC_FAULT_LIMIT:
- if (!data->have_oc_fault) {
- ret = -ENXIO;
- break;
- }
+ if (!data->have_oc_fault)
+ return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
break;
case PMBUS_VOUT_OV_WARN_LIMIT:
- if (data->id != adm1075) {
- ret = -ENODATA;
- break;
- }
+ if (data->have_vout)
+ return -ENODATA;
ret = pmbus_read_word_data(client, 0,
ADM1075_VAUX_OV_WARN_LIMIT);
break;
case PMBUS_VOUT_UV_WARN_LIMIT:
- if (data->id != adm1075) {
- ret = -ENODATA;
- break;
- }
+ if (data->have_vout)
+ return -ENODATA;
ret = pmbus_read_word_data(client, 0,
ADM1075_VAUX_UV_WARN_LIMIT);
break;
case PMBUS_READ_VOUT:
- if (data->id != adm1075) {
- ret = -ENODATA;
- break;
- }
+ if (data->have_vout)
+ return -ENODATA;
ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
break;
+ case PMBUS_VIRT_READ_IOUT_MIN:
+ if (!data->have_iout_min)
+ return -ENXIO;
+ ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN);
+ break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
break;
@@ -117,11 +186,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
break;
+ case PMBUS_VIRT_READ_PIN_MIN:
+ if (!data->have_pin_min)
+ return -ENXIO;
+ ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN);
+ break;
case PMBUS_VIRT_READ_PIN_MAX:
- if (data->id == adm1275) {
- ret = -ENXIO;
- break;
- }
+ if (!data->have_pin_max)
+ return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
@@ -129,8 +201,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_RESET_VIN_HISTORY:
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
- if (data->id == adm1275)
- ret = -ENXIO;
+ if (!data->have_pin_max)
+ return -ENXIO;
break;
default:
ret = -ENODATA;
@@ -142,6 +214,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
u16 word)
{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct adm1275_data *data = to_adm1275_data(info);
int ret;
if (page)
@@ -155,6 +229,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
+ if (!ret && data->have_iout_min)
+ ret = pmbus_write_word_data(client, 0,
+ ADM1293_IOUT_MIN, 0);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0);
@@ -164,6 +241,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
+ if (!ret && data->have_pin_min)
+ ret = pmbus_write_word_data(client, 0,
+ ADM1293_PIN_MIN, 0);
break;
default:
ret = -ENODATA;
@@ -186,29 +266,40 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
if (ret < 0)
break;
+ if (!data->have_oc_fault && !data->have_uc_fault)
+ break;
mfr_status = pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC);
- if (mfr_status < 0) {
- ret = mfr_status;
- break;
- }
+ if (mfr_status < 0)
+ return mfr_status;
if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
ret |= data->have_oc_fault ?
PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
}
break;
case PMBUS_STATUS_VOUT:
- if (data->id != adm1075) {
- ret = -ENODATA;
- break;
- }
+ if (data->have_vout)
+ return -ENODATA;
ret = 0;
- mfr_status = pmbus_read_byte_data(client, 0,
- ADM1075_VAUX_STATUS);
- if (mfr_status & ADM1075_VAUX_OV_WARN)
- ret |= PB_VOLTAGE_OV_WARNING;
- if (mfr_status & ADM1075_VAUX_UV_WARN)
- ret |= PB_VOLTAGE_UV_WARNING;
+ if (data->have_vaux_status) {
+ mfr_status = pmbus_read_byte_data(client, 0,
+ ADM1075_VAUX_STATUS);
+ if (mfr_status < 0)
+ return mfr_status;
+ if (mfr_status & ADM1075_VAUX_OV_WARN)
+ ret |= PB_VOLTAGE_OV_WARNING;
+ if (mfr_status & ADM1075_VAUX_UV_WARN)
+ ret |= PB_VOLTAGE_UV_WARNING;
+ } else if (data->have_mfr_vaux_status) {
+ mfr_status = pmbus_read_byte_data(client, page,
+ PMBUS_STATUS_MFR_SPECIFIC);
+ if (mfr_status < 0)
+ return mfr_status;
+ if (mfr_status & ADM1293_MFR_STATUS_VAUX_OV_WARN)
+ ret |= PB_VOLTAGE_OV_WARNING;
+ if (mfr_status & ADM1293_MFR_STATUS_VAUX_UV_WARN)
+ ret |= PB_VOLTAGE_UV_WARNING;
+ }
break;
default:
ret = -ENODATA;
@@ -221,6 +312,8 @@ static const struct i2c_device_id adm1275_id[] = {
{ "adm1075", adm1075 },
{ "adm1275", adm1275 },
{ "adm1276", adm1276 },
+ { "adm1293", adm1293 },
+ { "adm1294", adm1294 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1275_id);
@@ -234,6 +327,8 @@ static int adm1275_probe(struct i2c_client *client,
struct pmbus_driver_info *info;
struct adm1275_data *data;
const struct i2c_device_id *mid;
+ const struct coefficients *coefficients;
+ int vindex = -1, voindex = -1, cindex = -1, pindex = -1;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA
@@ -290,61 +385,38 @@ static int adm1275_probe(struct i2c_client *client,
info->format[PSC_VOLTAGE_IN] = direct;
info->format[PSC_VOLTAGE_OUT] = direct;
info->format[PSC_CURRENT_OUT] = direct;
- info->m[PSC_CURRENT_OUT] = 807;
- info->b[PSC_CURRENT_OUT] = 20475;
- info->R[PSC_CURRENT_OUT] = -1;
+ info->format[PSC_POWER] = direct;
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
info->read_word_data = adm1275_read_word_data;
info->read_byte_data = adm1275_read_byte_data;
info->write_word_data = adm1275_write_word_data;
- if (data->id == adm1075) {
- info->m[PSC_VOLTAGE_IN] = 27169;
- info->b[PSC_VOLTAGE_IN] = 0;
- info->R[PSC_VOLTAGE_IN] = -1;
- info->m[PSC_VOLTAGE_OUT] = 27169;
- info->b[PSC_VOLTAGE_OUT] = 0;
- info->R[PSC_VOLTAGE_OUT] = -1;
- } else if (config & ADM1275_VRANGE) {
- info->m[PSC_VOLTAGE_IN] = 19199;
- info->b[PSC_VOLTAGE_IN] = 0;
- info->R[PSC_VOLTAGE_IN] = -2;
- info->m[PSC_VOLTAGE_OUT] = 19199;
- info->b[PSC_VOLTAGE_OUT] = 0;
- info->R[PSC_VOLTAGE_OUT] = -2;
- } else {
- info->m[PSC_VOLTAGE_IN] = 6720;
- info->b[PSC_VOLTAGE_IN] = 0;
- info->R[PSC_VOLTAGE_IN] = -1;
- info->m[PSC_VOLTAGE_OUT] = 6720;
- info->b[PSC_VOLTAGE_OUT] = 0;
- info->R[PSC_VOLTAGE_OUT] = -1;
- }
-
- if (device_config & ADM1275_IOUT_WARN2_SELECT)
- data->have_oc_fault = true;
-
switch (data->id) {
case adm1075:
- info->format[PSC_POWER] = direct;
- info->b[PSC_POWER] = 0;
- info->R[PSC_POWER] = -1;
+ if (device_config & ADM1275_IOUT_WARN2_SELECT)
+ data->have_oc_fault = true;
+ else
+ data->have_uc_fault = true;
+ data->have_pin_max = true;
+ data->have_vaux_status = true;
+
+ coefficients = adm1075_coefficients;
+ vindex = 0;
switch (config & ADM1075_IRANGE_MASK) {
case ADM1075_IRANGE_25:
- info->m[PSC_POWER] = 8549;
- info->m[PSC_CURRENT_OUT] = 806;
+ cindex = 1;
+ pindex = 3;
break;
case ADM1075_IRANGE_50:
- info->m[PSC_POWER] = 4279;
- info->m[PSC_CURRENT_OUT] = 404;
+ cindex = 2;
+ pindex = 4;
break;
default:
dev_err(&client->dev, "Invalid input current range");
- info->m[PSC_POWER] = 0;
- info->m[PSC_CURRENT_OUT] = 0;
break;
}
+
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT;
if (config & ADM1275_VIN_VOUT_SELECT)
@@ -352,6 +424,16 @@ static int adm1275_probe(struct i2c_client *client,
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
break;
case adm1275:
+ if (device_config & ADM1275_IOUT_WARN2_SELECT)
+ data->have_oc_fault = true;
+ else
+ data->have_uc_fault = true;
+ data->have_vout = true;
+
+ coefficients = adm1275_coefficients;
+ vindex = (config & ADM1275_VRANGE) ? 0 : 1;
+ cindex = 2;
+
if (config & ADM1275_VIN_VOUT_SELECT)
info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
@@ -360,22 +442,100 @@ static int adm1275_probe(struct i2c_client *client,
PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
break;
case adm1276:
- info->format[PSC_POWER] = direct;
+ if (device_config & ADM1275_IOUT_WARN2_SELECT)
+ data->have_oc_fault = true;
+ else
+ data->have_uc_fault = true;
+ data->have_vout = true;
+ data->have_pin_max = true;
+
+ coefficients = adm1276_coefficients;
+ vindex = (config & ADM1275_VRANGE) ? 0 : 1;
+ cindex = 2;
+ pindex = (config & ADM1275_VRANGE) ? 3 : 4;
+
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT;
if (config & ADM1275_VIN_VOUT_SELECT)
info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
- if (config & ADM1275_VRANGE) {
- info->m[PSC_POWER] = 6043;
- info->b[PSC_POWER] = 0;
- info->R[PSC_POWER] = -2;
- } else {
- info->m[PSC_POWER] = 2115;
- info->b[PSC_POWER] = 0;
- info->R[PSC_POWER] = -1;
+ break;
+ case adm1293:
+ case adm1294:
+ data->have_iout_min = true;
+ data->have_pin_min = true;
+ data->have_pin_max = true;
+ data->have_mfr_vaux_status = true;
+
+ coefficients = adm1293_coefficients;
+
+ voindex = 0;
+ switch (config & ADM1293_VIN_SEL_MASK) {
+ case ADM1293_VIN_SEL_012: /* 1.2V */
+ vindex = 0;
+ break;
+ case ADM1293_VIN_SEL_074: /* 7.4V */
+ vindex = 1;
+ break;
+ case ADM1293_VIN_SEL_210: /* 21V */
+ vindex = 2;
+ break;
+ default: /* disabled */
+ break;
}
+
+ switch (config & ADM1293_IRANGE_MASK) {
+ case ADM1293_IRANGE_25:
+ cindex = 3;
+ break;
+ case ADM1293_IRANGE_50:
+ cindex = 4;
+ break;
+ case ADM1293_IRANGE_100:
+ cindex = 5;
+ break;
+ case ADM1293_IRANGE_200:
+ cindex = 6;
+ break;
+ }
+
+ if (vindex >= 0)
+ pindex = 7 + vindex * 4 + (cindex - 3);
+
+ if (config & ADM1293_VAUX_EN)
+ info->func[0] |=
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+
+ info->func[0] |= PMBUS_HAVE_PIN |
+ PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+
break;
+ default:
+ dev_err(&client->dev, "Unsupported device\n");
+ return -ENODEV;
+ }
+
+ if (voindex < 0)
+ voindex = vindex;
+ if (vindex >= 0) {
+ info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m;
+ info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b;
+ info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R;
+ }
+ if (voindex >= 0) {
+ info->m[PSC_VOLTAGE_OUT] = coefficients[voindex].m;
+ info->b[PSC_VOLTAGE_OUT] = coefficients[voindex].b;
+ info->R[PSC_VOLTAGE_OUT] = coefficients[voindex].R;
+ }
+ if (cindex >= 0) {
+ info->m[PSC_CURRENT_OUT] = coefficients[cindex].m;
+ info->b[PSC_CURRENT_OUT] = coefficients[cindex].b;
+ info->R[PSC_CURRENT_OUT] = coefficients[cindex].R;
+ }
+ if (pindex >= 0) {
+ info->m[PSC_POWER] = coefficients[pindex].m;
+ info->b[PSC_POWER] = coefficients[pindex].b;
+ info->R[PSC_POWER] = coefficients[pindex].R;
}
return pmbus_do_probe(client, id, info);
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index a26b1d1d9..a3d912cd3 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -42,15 +43,15 @@ enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 };
#define LM25066_READ_AVG_IIN 0xde
#define LM25066_READ_AVG_PIN 0xdf
-#define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */
+#define LM25066_DEV_SETUP_CL BIT(4) /* Current limit */
/* LM25056 only */
#define LM25056_VAUX_OV_WARN_LIMIT 0xe3
#define LM25056_VAUX_UV_WARN_LIMIT 0xe4
-#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1)
-#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0)
+#define LM25056_MFR_STS_VAUX_OV_WARN BIT(1)
+#define LM25056_MFR_STS_VAUX_UV_WARN BIT(0)
/* LM25063 only */
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 0835050ec..58b789c28 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -1,9 +1,9 @@
/*
- * Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880,
- * LTC3883, and LTM4676
+ * Hardware monitoring driver for LTC2978 and compatible chips.
*
* Copyright (c) 2011 Ericsson AB.
- * Copyright (c) 2013, 2014 Guenter Roeck
+ * Copyright (c) 2013, 2014, 2015 Guenter Roeck
+ * Copyright (c) 2015 Linear Technology
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,6 +16,8 @@
* GNU General Public License for more details.
*/
+#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -25,49 +27,71 @@
#include <linux/regulator/driver.h>
#include "pmbus.h"
-enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
+enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
+ ltc3883, ltc3886, ltc3887, ltm2987, ltm4675, ltm4676 };
/* Common for all chips */
#define LTC2978_MFR_VOUT_PEAK 0xdd
#define LTC2978_MFR_VIN_PEAK 0xde
#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
-#define LTC2978_MFR_SPECIAL_ID 0xe7
+#define LTC2978_MFR_SPECIAL_ID 0xe7 /* Undocumented on LTC3882 */
+#define LTC2978_MFR_COMMON 0xef
-/* LTC2974, LCT2977, and LTC2978 */
+/* LTC2974, LTC2975, LCT2977, LTC2980, LTC2978, and LTM2987 */
#define LTC2978_MFR_VOUT_MIN 0xfb
#define LTC2978_MFR_VIN_MIN 0xfc
#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
-/* LTC2974 only */
+/* LTC2974, LTC2975 */
#define LTC2974_MFR_IOUT_PEAK 0xd7
#define LTC2974_MFR_IOUT_MIN 0xd8
-/* LTC3880, LTC3883, and LTM4676 */
+/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, and LTM4676 */
#define LTC3880_MFR_IOUT_PEAK 0xd7
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
-/* LTC3883 only */
+/* LTC3883 and LTC3886 only */
#define LTC3883_MFR_IIN_PEAK 0xe1
-#define LTC2974_ID_REV1 0x0212
-#define LTC2974_ID_REV2 0x0213
+/* LTC2975 only */
+#define LTC2975_MFR_IIN_PEAK 0xc4
+#define LTC2975_MFR_IIN_MIN 0xc5
+#define LTC2975_MFR_PIN_PEAK 0xc6
+#define LTC2975_MFR_PIN_MIN 0xc7
+
+#define LTC2978_ID_MASK 0xfff0
+
+#define LTC2974_ID 0x0210
+#define LTC2975_ID 0x0220
#define LTC2977_ID 0x0130
-#define LTC2978_ID_REV1 0x0121
-#define LTC2978_ID_REV2 0x0122
-#define LTC2978A_ID 0x0124
-#define LTC3880_ID 0x4000
-#define LTC3880_ID_MASK 0xff00
+#define LTC2978_ID_REV1 0x0110 /* Early revision */
+#define LTC2978_ID_REV2 0x0120
+#define LTC2980_ID_A 0x8030 /* A/B for two die IDs */
+#define LTC2980_ID_B 0x8040
+#define LTC3880_ID 0x4020
+#define LTC3882_ID 0x4200
+#define LTC3882_ID_D1 0x4240 /* Dash 1 */
#define LTC3883_ID 0x4300
-#define LTC3883_ID_MASK 0xff00
-#define LTM4676_ID 0x4480 /* datasheet claims 0x440X */
-#define LTM4676_ID_MASK 0xfff0
+#define LTC3886_ID 0x4600
+#define LTC3887_ID 0x4700
+#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
+#define LTM2987_ID_B 0x8020
+#define LTM4675_ID 0x47a0
+#define LTM4676_ID_REV1 0x4400
+#define LTM4676_ID_REV2 0x4480
+#define LTM4676A_ID 0x47e0
#define LTC2974_NUM_PAGES 4
#define LTC2978_NUM_PAGES 8
#define LTC3880_NUM_PAGES 2
#define LTC3883_NUM_PAGES 1
+#define LTC_POLL_TIMEOUT 100 /* in milli-seconds */
+
+#define LTC_NOT_BUSY BIT(5)
+#define LTC_NOT_PENDING BIT(4)
+
/*
* LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
* happens pretty much each time chip data is updated. Raw peak data therefore
@@ -82,13 +106,91 @@ struct ltc2978_data {
u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES];
- u16 iin_max;
+ u16 iin_min, iin_max;
+ u16 pin_min, pin_max;
u16 temp2_max;
struct pmbus_driver_info info;
+ u32 features;
};
-
#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info)
+#define FEAT_CLEAR_PEAKS BIT(0)
+#define FEAT_NEEDS_POLLING BIT(1)
+
+#define has_clear_peaks(d) ((d)->features & FEAT_CLEAR_PEAKS)
+#define needs_polling(d) ((d)->features & FEAT_NEEDS_POLLING)
+
+static int ltc_wait_ready(struct i2c_client *client)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(LTC_POLL_TIMEOUT);
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct ltc2978_data *data = to_ltc2978_data(info);
+ int status;
+ u8 mask;
+
+ if (!needs_polling(data))
+ return 0;
+
+ /*
+ * LTC3883 does not support LTC_NOT_PENDING, even though
+ * the datasheet claims that it does.
+ */
+ mask = LTC_NOT_BUSY;
+ if (data->id != ltc3883)
+ mask |= LTC_NOT_PENDING;
+
+ do {
+ status = pmbus_read_byte_data(client, 0, LTC2978_MFR_COMMON);
+ if (status == -EBADMSG || status == -ENXIO) {
+ /* PEC error or NACK: chip may be busy, try again */
+ usleep_range(50, 100);
+ continue;
+ }
+ if (status < 0)
+ return status;
+
+ if ((status & mask) == mask)
+ return 0;
+
+ usleep_range(50, 100);
+ } while (time_before(jiffies, timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int ltc_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ int ret;
+
+ ret = ltc_wait_ready(client);
+ if (ret < 0)
+ return ret;
+
+ return pmbus_read_word_data(client, page, reg);
+}
+
+static int ltc_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ int ret;
+
+ ret = ltc_wait_ready(client);
+ if (ret < 0)
+ return ret;
+
+ return pmbus_read_byte_data(client, page, reg);
+}
+
+static int ltc_write_byte(struct i2c_client *client, int page, u8 byte)
+{
+ int ret;
+
+ ret = ltc_wait_ready(client);
+ if (ret < 0)
+ return ret;
+
+ return pmbus_write_byte(client, page, byte);
+}
+
static inline int lin11_to_val(int data)
{
s16 e = ((s16)data) >> 11;
@@ -102,6 +204,34 @@ static inline int lin11_to_val(int data)
return (e < 0 ? m >> -e : m << e);
}
+static int ltc_get_max(struct ltc2978_data *data, struct i2c_client *client,
+ int page, int reg, u16 *pmax)
+{
+ int ret;
+
+ ret = ltc_read_word_data(client, page, reg);
+ if (ret >= 0) {
+ if (lin11_to_val(ret) > lin11_to_val(*pmax))
+ *pmax = ret;
+ ret = *pmax;
+ }
+ return ret;
+}
+
+static int ltc_get_min(struct ltc2978_data *data, struct i2c_client *client,
+ int page, int reg, u16 *pmin)
+{
+ int ret;
+
+ ret = ltc_read_word_data(client, page, reg);
+ if (ret >= 0) {
+ if (lin11_to_val(ret) < lin11_to_val(*pmin))
+ *pmin = ret;
+ ret = *pmin;
+ }
+ return ret;
+}
+
static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
int reg)
{
@@ -111,15 +241,11 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
switch (reg) {
case PMBUS_VIRT_READ_VIN_MAX:
- ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
- if (ret >= 0) {
- if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
- data->vin_max = ret;
- ret = data->vin_max;
- }
+ ret = ltc_get_max(data, client, page, LTC2978_MFR_VIN_PEAK,
+ &data->vin_max);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
- ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
+ ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
if (ret >= 0) {
/*
* VOUT is 16 bit unsigned with fixed exponent,
@@ -131,14 +257,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
}
break;
case PMBUS_VIRT_READ_TEMP_MAX:
- ret = pmbus_read_word_data(client, page,
- LTC2978_MFR_TEMPERATURE_PEAK);
- if (ret >= 0) {
- if (lin11_to_val(ret)
- > lin11_to_val(data->temp_max[page]))
- data->temp_max[page] = ret;
- ret = data->temp_max[page];
- }
+ ret = ltc_get_max(data, client, page,
+ LTC2978_MFR_TEMPERATURE_PEAK,
+ &data->temp_max[page]);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_VIN_HISTORY:
@@ -146,6 +267,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
ret = 0;
break;
default:
+ ret = ltc_wait_ready(client);
+ if (ret < 0)
+ return ret;
ret = -ENODATA;
break;
}
@@ -160,15 +284,11 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_VIN_MIN:
- ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
- if (ret >= 0) {
- if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
- data->vin_min = ret;
- ret = data->vin_min;
- }
+ ret = ltc_get_min(data, client, page, LTC2978_MFR_VIN_MIN,
+ &data->vin_min);
break;
case PMBUS_VIRT_READ_VOUT_MIN:
- ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
+ ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
if (ret >= 0) {
/*
* VOUT_MIN is known to not be supported on some lots
@@ -184,14 +304,9 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
}
break;
case PMBUS_VIRT_READ_TEMP_MIN:
- ret = pmbus_read_word_data(client, page,
- LTC2978_MFR_TEMPERATURE_MIN);
- if (ret >= 0) {
- if (lin11_to_val(ret)
- < lin11_to_val(data->temp_min[page]))
- data->temp_min[page] = ret;
- ret = data->temp_min[page];
- }
+ ret = ltc_get_min(data, client, page,
+ LTC2978_MFR_TEMPERATURE_MIN,
+ &data->temp_min[page]);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
case PMBUS_VIRT_RESET_IOUT_HISTORY:
@@ -214,22 +329,12 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_IOUT_MAX:
- ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK);
- if (ret >= 0) {
- if (lin11_to_val(ret)
- > lin11_to_val(data->iout_max[page]))
- data->iout_max[page] = ret;
- ret = data->iout_max[page];
- }
+ ret = ltc_get_max(data, client, page, LTC2974_MFR_IOUT_PEAK,
+ &data->iout_max[page]);
break;
case PMBUS_VIRT_READ_IOUT_MIN:
- ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN);
- if (ret >= 0) {
- if (lin11_to_val(ret)
- < lin11_to_val(data->iout_min[page]))
- data->iout_min[page] = ret;
- ret = data->iout_min[page];
- }
+ ret = ltc_get_min(data, client, page, LTC2974_MFR_IOUT_MIN,
+ &data->iout_min[page]);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = 0;
@@ -241,6 +346,40 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
+static int ltc2975_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct ltc2978_data *data = to_ltc2978_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_READ_IIN_MAX:
+ ret = ltc_get_max(data, client, page, LTC2975_MFR_IIN_PEAK,
+ &data->iin_max);
+ break;
+ case PMBUS_VIRT_READ_IIN_MIN:
+ ret = ltc_get_min(data, client, page, LTC2975_MFR_IIN_MIN,
+ &data->iin_min);
+ break;
+ case PMBUS_VIRT_READ_PIN_MAX:
+ ret = ltc_get_max(data, client, page, LTC2975_MFR_PIN_PEAK,
+ &data->pin_max);
+ break;
+ case PMBUS_VIRT_READ_PIN_MIN:
+ ret = ltc_get_min(data, client, page, LTC2975_MFR_PIN_MIN,
+ &data->pin_min);
+ break;
+ case PMBUS_VIRT_RESET_IIN_HISTORY:
+ case PMBUS_VIRT_RESET_PIN_HISTORY:
+ ret = 0;
+ break;
+ default:
+ ret = ltc2978_read_word_data(client, page, reg);
+ break;
+ }
+ return ret;
+}
+
static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -249,22 +388,13 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_IOUT_MAX:
- ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
- if (ret >= 0) {
- if (lin11_to_val(ret)
- > lin11_to_val(data->iout_max[page]))
- data->iout_max[page] = ret;
- ret = data->iout_max[page];
- }
+ ret = ltc_get_max(data, client, page, LTC3880_MFR_IOUT_PEAK,
+ &data->iout_max[page]);
break;
case PMBUS_VIRT_READ_TEMP2_MAX:
- ret = pmbus_read_word_data(client, page,
- LTC3880_MFR_TEMPERATURE2_PEAK);
- if (ret >= 0) {
- if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
- data->temp2_max = ret;
- ret = data->temp2_max;
- }
+ ret = ltc_get_max(data, client, page,
+ LTC3880_MFR_TEMPERATURE2_PEAK,
+ &data->temp2_max);
break;
case PMBUS_VIRT_READ_VIN_MIN:
case PMBUS_VIRT_READ_VOUT_MIN:
@@ -290,13 +420,8 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_IIN_MAX:
- ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK);
- if (ret >= 0) {
- if (lin11_to_val(ret)
- > lin11_to_val(data->iin_max))
- data->iin_max = ret;
- ret = data->iin_max;
- }
+ ret = ltc_get_max(data, client, page, LTC3883_MFR_IIN_PEAK,
+ &data->iin_max);
break;
case PMBUS_VIRT_RESET_IIN_HISTORY:
ret = 0;
@@ -308,15 +433,15 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
-static int ltc2978_clear_peaks(struct i2c_client *client, int page,
- enum chips id)
+static int ltc2978_clear_peaks(struct ltc2978_data *data,
+ struct i2c_client *client, int page)
{
int ret;
- if (id == ltc3880 || id == ltc3883)
- ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
+ if (has_clear_peaks(data))
+ ret = ltc_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
else
- ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+ ret = ltc_write_byte(client, page, PMBUS_CLEAR_FAULTS);
return ret;
}
@@ -331,33 +456,42 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
switch (reg) {
case PMBUS_VIRT_RESET_IIN_HISTORY:
data->iin_max = 0x7c00;
- ret = ltc2978_clear_peaks(client, page, data->id);
+ data->iin_min = 0x7bff;
+ ret = ltc2978_clear_peaks(data, client, 0);
+ break;
+ case PMBUS_VIRT_RESET_PIN_HISTORY:
+ data->pin_max = 0x7c00;
+ data->pin_min = 0x7bff;
+ ret = ltc2978_clear_peaks(data, client, 0);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
data->iout_max[page] = 0x7c00;
data->iout_min[page] = 0xfbff;
- ret = ltc2978_clear_peaks(client, page, data->id);
+ ret = ltc2978_clear_peaks(data, client, page);
break;
case PMBUS_VIRT_RESET_TEMP2_HISTORY:
data->temp2_max = 0x7c00;
- ret = ltc2978_clear_peaks(client, page, data->id);
+ ret = ltc2978_clear_peaks(data, client, page);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
data->vout_min[page] = 0xffff;
data->vout_max[page] = 0;
- ret = ltc2978_clear_peaks(client, page, data->id);
+ ret = ltc2978_clear_peaks(data, client, page);
break;
case PMBUS_VIRT_RESET_VIN_HISTORY:
data->vin_min = 0x7bff;
data->vin_max = 0x7c00;
- ret = ltc2978_clear_peaks(client, page, data->id);
+ ret = ltc2978_clear_peaks(data, client, page);
break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
data->temp_min[page] = 0x7bff;
data->temp_max[page] = 0x7c00;
- ret = ltc2978_clear_peaks(client, page, data->id);
+ ret = ltc2978_clear_peaks(data, client, page);
break;
default:
+ ret = ltc_wait_ready(client);
+ if (ret < 0)
+ return ret;
ret = -ENODATA;
break;
}
@@ -366,10 +500,17 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
static const struct i2c_device_id ltc2978_id[] = {
{"ltc2974", ltc2974},
+ {"ltc2975", ltc2975},
{"ltc2977", ltc2977},
{"ltc2978", ltc2978},
+ {"ltc2980", ltc2980},
{"ltc3880", ltc3880},
+ {"ltc3882", ltc3882},
{"ltc3883", ltc3883},
+ {"ltc3886", ltc3886},
+ {"ltc3887", ltc3887},
+ {"ltm2987", ltm2987},
+ {"ltm4675", ltm4675},
{"ltm4676", ltm4676},
{}
};
@@ -388,10 +529,74 @@ static const struct regulator_desc ltc2978_reg_desc[] = {
};
#endif /* CONFIG_SENSORS_LTC2978_REGULATOR */
+static int ltc2978_get_id(struct i2c_client *client)
+{
+ int chip_id;
+
+ chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+ if (chip_id < 0) {
+ const struct i2c_device_id *id;
+ u8 buf[I2C_SMBUS_BLOCK_MAX];
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+ return -ENODEV;
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
+ if (ret < 0)
+ return ret;
+ if (ret < 3 || strncmp(buf, "LTC", 3))
+ return -ENODEV;
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
+ if (ret < 0)
+ return ret;
+ for (id = &ltc2978_id[0]; strlen(id->name); id++) {
+ if (!strncasecmp(id->name, buf, strlen(id->name)))
+ return (int)id->driver_data;
+ }
+ return -ENODEV;
+ }
+
+ chip_id &= LTC2978_ID_MASK;
+
+ if (chip_id == LTC2974_ID)
+ return ltc2974;
+ else if (chip_id == LTC2975_ID)
+ return ltc2975;
+ else if (chip_id == LTC2977_ID)
+ return ltc2977;
+ else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2)
+ return ltc2978;
+ else if (chip_id == LTC2980_ID_A || chip_id == LTC2980_ID_B)
+ return ltc2980;
+ else if (chip_id == LTC3880_ID)
+ return ltc3880;
+ else if (chip_id == LTC3882_ID || chip_id == LTC3882_ID_D1)
+ return ltc3882;
+ else if (chip_id == LTC3883_ID)
+ return ltc3883;
+ else if (chip_id == LTC3886_ID)
+ return ltc3886;
+ else if (chip_id == LTC3887_ID)
+ return ltc3887;
+ else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
+ return ltm2987;
+ else if (chip_id == LTM4675_ID)
+ return ltm4675;
+ else if (chip_id == LTM4676_ID_REV1 || chip_id == LTM4676_ID_REV2 ||
+ chip_id == LTM4676A_ID)
+ return ltm4676;
+
+ dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
+ return -ENODEV;
+}
+
static int ltc2978_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int chip_id, i;
+ int i, chip_id;
struct ltc2978_data *data;
struct pmbus_driver_info *info;
@@ -404,27 +609,11 @@ static int ltc2978_probe(struct i2c_client *client,
if (!data)
return -ENOMEM;
- chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+ chip_id = ltc2978_get_id(client);
if (chip_id < 0)
return chip_id;
- if (chip_id == LTC2974_ID_REV1 || chip_id == LTC2974_ID_REV2) {
- data->id = ltc2974;
- } else if (chip_id == LTC2977_ID) {
- data->id = ltc2977;
- } else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2 ||
- chip_id == LTC2978A_ID) {
- data->id = ltc2978;
- } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
- data->id = ltc3880;
- } else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) {
- data->id = ltc3883;
- } else if ((chip_id & LTM4676_ID_MASK) == LTM4676_ID) {
- data->id = ltm4676;
- } else {
- dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
- return -ENODEV;
- }
+ data->id = chip_id;
if (data->id != id->driver_data)
dev_warn(&client->dev,
"Device mismatch: Configured %s, detected %s\n",
@@ -433,6 +622,9 @@ static int ltc2978_probe(struct i2c_client *client,
info = &data->info;
info->write_word_data = ltc2978_write_word_data;
+ info->write_byte = ltc_write_byte;
+ info->read_word_data = ltc_read_word_data;
+ info->read_byte_data = ltc_read_byte_data;
data->vin_min = 0x7bff;
data->vin_max = 0x7c00;
@@ -461,8 +653,23 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
}
break;
+ case ltc2975:
+ info->read_word_data = ltc2975_read_word_data;
+ info->pages = LTC2974_NUM_PAGES;
+ info->func[0] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_TEMP2;
+ for (i = 0; i < info->pages; i++) {
+ info->func[i] |= PMBUS_HAVE_VOUT
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
+ }
+ break;
case ltc2977:
case ltc2978:
+ case ltc2980:
+ case ltm2987:
info->read_word_data = ltc2978_read_word_data;
info->pages = LTC2978_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
@@ -474,7 +681,10 @@ static int ltc2978_probe(struct i2c_client *client,
}
break;
case ltc3880:
+ case ltc3887:
+ case ltm4675:
case ltm4676:
+ data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
info->read_word_data = ltc3880_read_word_data;
info->pages = LTC3880_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
@@ -488,7 +698,23 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
break;
+ case ltc3882:
+ data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
+ info->read_word_data = ltc3880_read_word_data;
+ info->pages = LTC3880_NUM_PAGES;
+ info->func[0] = PMBUS_HAVE_VIN
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+ info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ break;
case ltc3883:
+ data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
info->read_word_data = ltc3883_read_word_data;
info->pages = LTC3883_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
@@ -498,6 +724,21 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
break;
+ case ltc3886:
+ data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
+ info->read_word_data = ltc3883_read_word_data;
+ info->pages = LTC3880_NUM_PAGES;
+ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+ info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ break;
default:
return -ENODEV;
}
@@ -517,10 +758,17 @@ static int ltc2978_probe(struct i2c_client *client,
#ifdef CONFIG_OF
static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc2974" },
+ { .compatible = "lltc,ltc2975" },
{ .compatible = "lltc,ltc2977" },
{ .compatible = "lltc,ltc2978" },
+ { .compatible = "lltc,ltc2980" },
{ .compatible = "lltc,ltc3880" },
+ { .compatible = "lltc,ltc3882" },
{ .compatible = "lltc,ltc3883" },
+ { .compatible = "lltc,ltc3886" },
+ { .compatible = "lltc,ltc3887" },
+ { .compatible = "lltc,ltm2987" },
+ { .compatible = "lltc,ltm4675" },
{ .compatible = "lltc,ltm4676" },
{ }
};
@@ -540,5 +788,5 @@ static struct i2c_driver ltc2978_driver = {
module_i2c_driver(ltc2978_driver);
MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, LTC3883, and LTM4676");
+MODULE_DESCRIPTION("PMBus driver for LTC2978 and comppatible chips");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c
new file mode 100644
index 000000000..ab74aeae8
--- /dev/null
+++ b/drivers/hwmon/pmbus/max20751.c
@@ -0,0 +1,64 @@
+/*
+ * Hardware monitoring driver for Maxim MAX20751
+ *
+ * Copyright (c) 2015 Guenter Roeck
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info max20751_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = vid,
+ .vrm_version = vr12,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT,
+};
+
+static int max20751_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return pmbus_do_probe(client, id, &max20751_info);
+}
+
+static const struct i2c_device_id max20751_id[] = {
+ {"max20751", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, max20751_id);
+
+static struct i2c_driver max20751_driver = {
+ .driver = {
+ .name = "max20751",
+ },
+ .probe = max20751_probe,
+ .remove = pmbus_do_remove,
+ .id_table = max20751_id,
+};
+
+module_i2c_driver(max20751_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX20751");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
index 7e930c3ce..74a1f6f68 100644
--- a/drivers/hwmon/pmbus/max34440.c
+++ b/drivers/hwmon/pmbus/max34440.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -38,10 +39,10 @@ enum chips { max34440, max34441, max34446, max34460, max34461 };
#define MAX34446_MFR_IOUT_AVG 0xe2
#define MAX34446_MFR_TEMPERATURE_AVG 0xe3
-#define MAX34440_STATUS_OC_WARN (1 << 0)
-#define MAX34440_STATUS_OC_FAULT (1 << 1)
-#define MAX34440_STATUS_OT_FAULT (1 << 5)
-#define MAX34440_STATUS_OT_WARN (1 << 6)
+#define MAX34440_STATUS_OC_WARN BIT(0)
+#define MAX34440_STATUS_OC_FAULT BIT(1)
+#define MAX34440_STATUS_OT_FAULT BIT(5)
+#define MAX34440_STATUS_OT_WARN BIT(6)
struct max34440_data {
int id;
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
index f04454a42..dd4883a19 100644
--- a/drivers/hwmon/pmbus/max8688.c
+++ b/drivers/hwmon/pmbus/max8688.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -30,15 +31,15 @@
#define MAX8688_MFR_TEMPERATURE_PEAK 0xd6
#define MAX8688_MFG_STATUS 0xd8
-#define MAX8688_STATUS_OC_FAULT (1 << 4)
-#define MAX8688_STATUS_OV_FAULT (1 << 5)
-#define MAX8688_STATUS_OV_WARNING (1 << 8)
-#define MAX8688_STATUS_UV_FAULT (1 << 9)
-#define MAX8688_STATUS_UV_WARNING (1 << 10)
-#define MAX8688_STATUS_UC_FAULT (1 << 11)
-#define MAX8688_STATUS_OC_WARNING (1 << 12)
-#define MAX8688_STATUS_OT_FAULT (1 << 13)
-#define MAX8688_STATUS_OT_WARNING (1 << 14)
+#define MAX8688_STATUS_OC_FAULT BIT(4)
+#define MAX8688_STATUS_OV_FAULT BIT(5)
+#define MAX8688_STATUS_OV_WARNING BIT(8)
+#define MAX8688_STATUS_UV_FAULT BIT(9)
+#define MAX8688_STATUS_UV_WARNING BIT(10)
+#define MAX8688_STATUS_UC_FAULT BIT(11)
+#define MAX8688_STATUS_OC_WARNING BIT(12)
+#define MAX8688_STATUS_OT_FAULT BIT(13)
+#define MAX8688_STATUS_OT_WARNING BIT(14)
static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
{
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index 554d0249d..0a74991a6 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -129,6 +129,7 @@ static int pmbus_identify(struct i2c_client *client,
break;
case 1:
info->format[PSC_VOLTAGE_OUT] = vid;
+ info->vrm_version = vr11;
break;
case 2:
info->format[PSC_VOLTAGE_OUT] = direct;
@@ -193,6 +194,10 @@ static const struct i2c_device_id pmbus_id[] = {
{"pdt012", 1},
{"pmbus", 0},
{"tps40400", 1},
+ {"tps544b20", 1},
+ {"tps544b25", 1},
+ {"tps544c20", 1},
+ {"tps544c25", 1},
{"udt020", 1},
{}
};
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index 89a23ff83..bfcb13bae 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -19,114 +19,116 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/regulator/driver.h>
-
#ifndef PMBUS_H
#define PMBUS_H
+#include <linux/bitops.h>
+#include <linux/regulator/driver.h>
+
/*
* Registers
*/
-#define PMBUS_PAGE 0x00
-#define PMBUS_OPERATION 0x01
-#define PMBUS_ON_OFF_CONFIG 0x02
-#define PMBUS_CLEAR_FAULTS 0x03
-#define PMBUS_PHASE 0x04
-
-#define PMBUS_CAPABILITY 0x19
-#define PMBUS_QUERY 0x1A
-
-#define PMBUS_VOUT_MODE 0x20
-#define PMBUS_VOUT_COMMAND 0x21
-#define PMBUS_VOUT_TRIM 0x22
-#define PMBUS_VOUT_CAL_OFFSET 0x23
-#define PMBUS_VOUT_MAX 0x24
-#define PMBUS_VOUT_MARGIN_HIGH 0x25
-#define PMBUS_VOUT_MARGIN_LOW 0x26
-#define PMBUS_VOUT_TRANSITION_RATE 0x27
-#define PMBUS_VOUT_DROOP 0x28
-#define PMBUS_VOUT_SCALE_LOOP 0x29
-#define PMBUS_VOUT_SCALE_MONITOR 0x2A
-
-#define PMBUS_COEFFICIENTS 0x30
-#define PMBUS_POUT_MAX 0x31
-
-#define PMBUS_FAN_CONFIG_12 0x3A
-#define PMBUS_FAN_COMMAND_1 0x3B
-#define PMBUS_FAN_COMMAND_2 0x3C
-#define PMBUS_FAN_CONFIG_34 0x3D
-#define PMBUS_FAN_COMMAND_3 0x3E
-#define PMBUS_FAN_COMMAND_4 0x3F
-
-#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40
-#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41
-#define PMBUS_VOUT_OV_WARN_LIMIT 0x42
-#define PMBUS_VOUT_UV_WARN_LIMIT 0x43
-#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44
-#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45
-#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46
-#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47
-#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48
-#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49
-#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A
-#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B
-#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C
-
-#define PMBUS_OT_FAULT_LIMIT 0x4F
-#define PMBUS_OT_FAULT_RESPONSE 0x50
-#define PMBUS_OT_WARN_LIMIT 0x51
-#define PMBUS_UT_WARN_LIMIT 0x52
-#define PMBUS_UT_FAULT_LIMIT 0x53
-#define PMBUS_UT_FAULT_RESPONSE 0x54
-#define PMBUS_VIN_OV_FAULT_LIMIT 0x55
-#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56
-#define PMBUS_VIN_OV_WARN_LIMIT 0x57
-#define PMBUS_VIN_UV_WARN_LIMIT 0x58
-#define PMBUS_VIN_UV_FAULT_LIMIT 0x59
-
-#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B
-#define PMBUS_IIN_OC_WARN_LIMIT 0x5D
-
-#define PMBUS_POUT_OP_FAULT_LIMIT 0x68
-#define PMBUS_POUT_OP_WARN_LIMIT 0x6A
-#define PMBUS_PIN_OP_WARN_LIMIT 0x6B
-
-#define PMBUS_STATUS_BYTE 0x78
-#define PMBUS_STATUS_WORD 0x79
-#define PMBUS_STATUS_VOUT 0x7A
-#define PMBUS_STATUS_IOUT 0x7B
-#define PMBUS_STATUS_INPUT 0x7C
-#define PMBUS_STATUS_TEMPERATURE 0x7D
-#define PMBUS_STATUS_CML 0x7E
-#define PMBUS_STATUS_OTHER 0x7F
-#define PMBUS_STATUS_MFR_SPECIFIC 0x80
-#define PMBUS_STATUS_FAN_12 0x81
-#define PMBUS_STATUS_FAN_34 0x82
-
-#define PMBUS_READ_VIN 0x88
-#define PMBUS_READ_IIN 0x89
-#define PMBUS_READ_VCAP 0x8A
-#define PMBUS_READ_VOUT 0x8B
-#define PMBUS_READ_IOUT 0x8C
-#define PMBUS_READ_TEMPERATURE_1 0x8D
-#define PMBUS_READ_TEMPERATURE_2 0x8E
-#define PMBUS_READ_TEMPERATURE_3 0x8F
-#define PMBUS_READ_FAN_SPEED_1 0x90
-#define PMBUS_READ_FAN_SPEED_2 0x91
-#define PMBUS_READ_FAN_SPEED_3 0x92
-#define PMBUS_READ_FAN_SPEED_4 0x93
-#define PMBUS_READ_DUTY_CYCLE 0x94
-#define PMBUS_READ_FREQUENCY 0x95
-#define PMBUS_READ_POUT 0x96
-#define PMBUS_READ_PIN 0x97
-
-#define PMBUS_REVISION 0x98
-#define PMBUS_MFR_ID 0x99
-#define PMBUS_MFR_MODEL 0x9A
-#define PMBUS_MFR_REVISION 0x9B
-#define PMBUS_MFR_LOCATION 0x9C
-#define PMBUS_MFR_DATE 0x9D
-#define PMBUS_MFR_SERIAL 0x9E
+enum pmbus_regs {
+ PMBUS_PAGE = 0x00,
+ PMBUS_OPERATION = 0x01,
+ PMBUS_ON_OFF_CONFIG = 0x02,
+ PMBUS_CLEAR_FAULTS = 0x03,
+ PMBUS_PHASE = 0x04,
+
+ PMBUS_CAPABILITY = 0x19,
+ PMBUS_QUERY = 0x1A,
+
+ PMBUS_VOUT_MODE = 0x20,
+ PMBUS_VOUT_COMMAND = 0x21,
+ PMBUS_VOUT_TRIM = 0x22,
+ PMBUS_VOUT_CAL_OFFSET = 0x23,
+ PMBUS_VOUT_MAX = 0x24,
+ PMBUS_VOUT_MARGIN_HIGH = 0x25,
+ PMBUS_VOUT_MARGIN_LOW = 0x26,
+ PMBUS_VOUT_TRANSITION_RATE = 0x27,
+ PMBUS_VOUT_DROOP = 0x28,
+ PMBUS_VOUT_SCALE_LOOP = 0x29,
+ PMBUS_VOUT_SCALE_MONITOR = 0x2A,
+
+ PMBUS_COEFFICIENTS = 0x30,
+ PMBUS_POUT_MAX = 0x31,
+
+ PMBUS_FAN_CONFIG_12 = 0x3A,
+ PMBUS_FAN_COMMAND_1 = 0x3B,
+ PMBUS_FAN_COMMAND_2 = 0x3C,
+ PMBUS_FAN_CONFIG_34 = 0x3D,
+ PMBUS_FAN_COMMAND_3 = 0x3E,
+ PMBUS_FAN_COMMAND_4 = 0x3F,
+
+ PMBUS_VOUT_OV_FAULT_LIMIT = 0x40,
+ PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41,
+ PMBUS_VOUT_OV_WARN_LIMIT = 0x42,
+ PMBUS_VOUT_UV_WARN_LIMIT = 0x43,
+ PMBUS_VOUT_UV_FAULT_LIMIT = 0x44,
+ PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45,
+ PMBUS_IOUT_OC_FAULT_LIMIT = 0x46,
+ PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47,
+ PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48,
+ PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
+ PMBUS_IOUT_OC_WARN_LIMIT = 0x4A,
+ PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B,
+ PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C,
+
+ PMBUS_OT_FAULT_LIMIT = 0x4F,
+ PMBUS_OT_FAULT_RESPONSE = 0x50,
+ PMBUS_OT_WARN_LIMIT = 0x51,
+ PMBUS_UT_WARN_LIMIT = 0x52,
+ PMBUS_UT_FAULT_LIMIT = 0x53,
+ PMBUS_UT_FAULT_RESPONSE = 0x54,
+ PMBUS_VIN_OV_FAULT_LIMIT = 0x55,
+ PMBUS_VIN_OV_FAULT_RESPONSE = 0x56,
+ PMBUS_VIN_OV_WARN_LIMIT = 0x57,
+ PMBUS_VIN_UV_WARN_LIMIT = 0x58,
+ PMBUS_VIN_UV_FAULT_LIMIT = 0x59,
+
+ PMBUS_IIN_OC_FAULT_LIMIT = 0x5B,
+ PMBUS_IIN_OC_WARN_LIMIT = 0x5D,
+
+ PMBUS_POUT_OP_FAULT_LIMIT = 0x68,
+ PMBUS_POUT_OP_WARN_LIMIT = 0x6A,
+ PMBUS_PIN_OP_WARN_LIMIT = 0x6B,
+
+ PMBUS_STATUS_BYTE = 0x78,
+ PMBUS_STATUS_WORD = 0x79,
+ PMBUS_STATUS_VOUT = 0x7A,
+ PMBUS_STATUS_IOUT = 0x7B,
+ PMBUS_STATUS_INPUT = 0x7C,
+ PMBUS_STATUS_TEMPERATURE = 0x7D,
+ PMBUS_STATUS_CML = 0x7E,
+ PMBUS_STATUS_OTHER = 0x7F,
+ PMBUS_STATUS_MFR_SPECIFIC = 0x80,
+ PMBUS_STATUS_FAN_12 = 0x81,
+ PMBUS_STATUS_FAN_34 = 0x82,
+
+ PMBUS_READ_VIN = 0x88,
+ PMBUS_READ_IIN = 0x89,
+ PMBUS_READ_VCAP = 0x8A,
+ PMBUS_READ_VOUT = 0x8B,
+ PMBUS_READ_IOUT = 0x8C,
+ PMBUS_READ_TEMPERATURE_1 = 0x8D,
+ PMBUS_READ_TEMPERATURE_2 = 0x8E,
+ PMBUS_READ_TEMPERATURE_3 = 0x8F,
+ PMBUS_READ_FAN_SPEED_1 = 0x90,
+ PMBUS_READ_FAN_SPEED_2 = 0x91,
+ PMBUS_READ_FAN_SPEED_3 = 0x92,
+ PMBUS_READ_FAN_SPEED_4 = 0x93,
+ PMBUS_READ_DUTY_CYCLE = 0x94,
+ PMBUS_READ_FREQUENCY = 0x95,
+ PMBUS_READ_POUT = 0x96,
+ PMBUS_READ_PIN = 0x97,
+
+ PMBUS_REVISION = 0x98,
+ PMBUS_MFR_ID = 0x99,
+ PMBUS_MFR_MODEL = 0x9A,
+ PMBUS_MFR_REVISION = 0x9B,
+ PMBUS_MFR_LOCATION = 0x9C,
+ PMBUS_MFR_DATE = 0x9D,
+ PMBUS_MFR_SERIAL = 0x9E,
/*
* Virtual registers.
@@ -148,55 +150,58 @@
* the calling PMBus core code will abort if the chip driver returns an error
* code when reading or writing virtual registers.
*/
-#define PMBUS_VIRT_BASE 0x100
-#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0)
-#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1)
-#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2)
-#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3)
-#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4)
-#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5)
-#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6)
-#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7)
-#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8)
-#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9)
-#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10)
-#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11)
-#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12)
-#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13)
-#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14)
-#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15)
-#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16)
-#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17)
-#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18)
-#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19)
-#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20)
-#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21)
-#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22)
-#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23)
-#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24)
-#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25)
-#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26)
-#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27)
-#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28)
-#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29)
-
-#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30)
-#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31)
-#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32)
-#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33)
-#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
-#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35)
+ PMBUS_VIRT_BASE = 0x100,
+ PMBUS_VIRT_READ_TEMP_AVG,
+ PMBUS_VIRT_READ_TEMP_MIN,
+ PMBUS_VIRT_READ_TEMP_MAX,
+ PMBUS_VIRT_RESET_TEMP_HISTORY,
+ PMBUS_VIRT_READ_VIN_AVG,
+ PMBUS_VIRT_READ_VIN_MIN,
+ PMBUS_VIRT_READ_VIN_MAX,
+ PMBUS_VIRT_RESET_VIN_HISTORY,
+ PMBUS_VIRT_READ_IIN_AVG,
+ PMBUS_VIRT_READ_IIN_MIN,
+ PMBUS_VIRT_READ_IIN_MAX,
+ PMBUS_VIRT_RESET_IIN_HISTORY,
+ PMBUS_VIRT_READ_PIN_AVG,
+ PMBUS_VIRT_READ_PIN_MIN,
+ PMBUS_VIRT_READ_PIN_MAX,
+ PMBUS_VIRT_RESET_PIN_HISTORY,
+ PMBUS_VIRT_READ_POUT_AVG,
+ PMBUS_VIRT_READ_POUT_MIN,
+ PMBUS_VIRT_READ_POUT_MAX,
+ PMBUS_VIRT_RESET_POUT_HISTORY,
+ PMBUS_VIRT_READ_VOUT_AVG,
+ PMBUS_VIRT_READ_VOUT_MIN,
+ PMBUS_VIRT_READ_VOUT_MAX,
+ PMBUS_VIRT_RESET_VOUT_HISTORY,
+ PMBUS_VIRT_READ_IOUT_AVG,
+ PMBUS_VIRT_READ_IOUT_MIN,
+ PMBUS_VIRT_READ_IOUT_MAX,
+ PMBUS_VIRT_RESET_IOUT_HISTORY,
+ PMBUS_VIRT_READ_TEMP2_AVG,
+ PMBUS_VIRT_READ_TEMP2_MIN,
+ PMBUS_VIRT_READ_TEMP2_MAX,
+ PMBUS_VIRT_RESET_TEMP2_HISTORY,
+
+ PMBUS_VIRT_READ_VMON,
+ PMBUS_VIRT_VMON_UV_WARN_LIMIT,
+ PMBUS_VIRT_VMON_OV_WARN_LIMIT,
+ PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
+ PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
+ PMBUS_VIRT_STATUS_VMON,
+};
/*
* OPERATION
*/
-#define PB_OPERATION_CONTROL_ON (1<<7)
+#define PB_OPERATION_CONTROL_ON BIT(7)
/*
* CAPABILITY
*/
-#define PB_CAPABILITY_SMBALERT (1<<4)
-#define PB_CAPABILITY_ERROR_CHECK (1<<7)
+#define PB_CAPABILITY_SMBALERT BIT(4)
+#define PB_CAPABILITY_ERROR_CHECK BIT(7)
/*
* VOUT_MODE
@@ -211,94 +216,94 @@
/*
* Fan configuration
*/
-#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1))
-#define PB_FAN_2_RPM (1 << 2)
-#define PB_FAN_2_INSTALLED (1 << 3)
-#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5))
-#define PB_FAN_1_RPM (1 << 6)
-#define PB_FAN_1_INSTALLED (1 << 7)
+#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1))
+#define PB_FAN_2_RPM BIT(2)
+#define PB_FAN_2_INSTALLED BIT(3)
+#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5))
+#define PB_FAN_1_RPM BIT(6)
+#define PB_FAN_1_INSTALLED BIT(7)
/*
* STATUS_BYTE, STATUS_WORD (lower)
*/
-#define PB_STATUS_NONE_ABOVE (1<<0)
-#define PB_STATUS_CML (1<<1)
-#define PB_STATUS_TEMPERATURE (1<<2)
-#define PB_STATUS_VIN_UV (1<<3)
-#define PB_STATUS_IOUT_OC (1<<4)
-#define PB_STATUS_VOUT_OV (1<<5)
-#define PB_STATUS_OFF (1<<6)
-#define PB_STATUS_BUSY (1<<7)
+#define PB_STATUS_NONE_ABOVE BIT(0)
+#define PB_STATUS_CML BIT(1)
+#define PB_STATUS_TEMPERATURE BIT(2)
+#define PB_STATUS_VIN_UV BIT(3)
+#define PB_STATUS_IOUT_OC BIT(4)
+#define PB_STATUS_VOUT_OV BIT(5)
+#define PB_STATUS_OFF BIT(6)
+#define PB_STATUS_BUSY BIT(7)
/*
* STATUS_WORD (upper)
*/
-#define PB_STATUS_UNKNOWN (1<<8)
-#define PB_STATUS_OTHER (1<<9)
-#define PB_STATUS_FANS (1<<10)
-#define PB_STATUS_POWER_GOOD_N (1<<11)
-#define PB_STATUS_WORD_MFR (1<<12)
-#define PB_STATUS_INPUT (1<<13)
-#define PB_STATUS_IOUT_POUT (1<<14)
-#define PB_STATUS_VOUT (1<<15)
+#define PB_STATUS_UNKNOWN BIT(8)
+#define PB_STATUS_OTHER BIT(9)
+#define PB_STATUS_FANS BIT(10)
+#define PB_STATUS_POWER_GOOD_N BIT(11)
+#define PB_STATUS_WORD_MFR BIT(12)
+#define PB_STATUS_INPUT BIT(13)
+#define PB_STATUS_IOUT_POUT BIT(14)
+#define PB_STATUS_VOUT BIT(15)
/*
* STATUS_IOUT
*/
-#define PB_POUT_OP_WARNING (1<<0)
-#define PB_POUT_OP_FAULT (1<<1)
-#define PB_POWER_LIMITING (1<<2)
-#define PB_CURRENT_SHARE_FAULT (1<<3)
-#define PB_IOUT_UC_FAULT (1<<4)
-#define PB_IOUT_OC_WARNING (1<<5)
-#define PB_IOUT_OC_LV_FAULT (1<<6)
-#define PB_IOUT_OC_FAULT (1<<7)
+#define PB_POUT_OP_WARNING BIT(0)
+#define PB_POUT_OP_FAULT BIT(1)
+#define PB_POWER_LIMITING BIT(2)
+#define PB_CURRENT_SHARE_FAULT BIT(3)
+#define PB_IOUT_UC_FAULT BIT(4)
+#define PB_IOUT_OC_WARNING BIT(5)
+#define PB_IOUT_OC_LV_FAULT BIT(6)
+#define PB_IOUT_OC_FAULT BIT(7)
/*
* STATUS_VOUT, STATUS_INPUT
*/
-#define PB_VOLTAGE_UV_FAULT (1<<4)
-#define PB_VOLTAGE_UV_WARNING (1<<5)
-#define PB_VOLTAGE_OV_WARNING (1<<6)
-#define PB_VOLTAGE_OV_FAULT (1<<7)
+#define PB_VOLTAGE_UV_FAULT BIT(4)
+#define PB_VOLTAGE_UV_WARNING BIT(5)
+#define PB_VOLTAGE_OV_WARNING BIT(6)
+#define PB_VOLTAGE_OV_FAULT BIT(7)
/*
* STATUS_INPUT
*/
-#define PB_PIN_OP_WARNING (1<<0)
-#define PB_IIN_OC_WARNING (1<<1)
-#define PB_IIN_OC_FAULT (1<<2)
+#define PB_PIN_OP_WARNING BIT(0)
+#define PB_IIN_OC_WARNING BIT(1)
+#define PB_IIN_OC_FAULT BIT(2)
/*
* STATUS_TEMPERATURE
*/
-#define PB_TEMP_UT_FAULT (1<<4)
-#define PB_TEMP_UT_WARNING (1<<5)
-#define PB_TEMP_OT_WARNING (1<<6)
-#define PB_TEMP_OT_FAULT (1<<7)
+#define PB_TEMP_UT_FAULT BIT(4)
+#define PB_TEMP_UT_WARNING BIT(5)
+#define PB_TEMP_OT_WARNING BIT(6)
+#define PB_TEMP_OT_FAULT BIT(7)
/*
* STATUS_FAN
*/
-#define PB_FAN_AIRFLOW_WARNING (1<<0)
-#define PB_FAN_AIRFLOW_FAULT (1<<1)
-#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2)
-#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3)
-#define PB_FAN_FAN2_WARNING (1<<4)
-#define PB_FAN_FAN1_WARNING (1<<5)
-#define PB_FAN_FAN2_FAULT (1<<6)
-#define PB_FAN_FAN1_FAULT (1<<7)
+#define PB_FAN_AIRFLOW_WARNING BIT(0)
+#define PB_FAN_AIRFLOW_FAULT BIT(1)
+#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2)
+#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3)
+#define PB_FAN_FAN2_WARNING BIT(4)
+#define PB_FAN_FAN1_WARNING BIT(5)
+#define PB_FAN_FAN2_FAULT BIT(6)
+#define PB_FAN_FAN1_FAULT BIT(7)
/*
* CML_FAULT_STATUS
*/
-#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0)
-#define PB_CML_FAULT_OTHER_COMM (1<<1)
-#define PB_CML_FAULT_PROCESSOR (1<<3)
-#define PB_CML_FAULT_MEMORY (1<<4)
-#define PB_CML_FAULT_PACKET_ERROR (1<<5)
-#define PB_CML_FAULT_INVALID_DATA (1<<6)
-#define PB_CML_FAULT_INVALID_COMMAND (1<<7)
+#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0)
+#define PB_CML_FAULT_OTHER_COMM BIT(1)
+#define PB_CML_FAULT_PROCESSOR BIT(3)
+#define PB_CML_FAULT_MEMORY BIT(4)
+#define PB_CML_FAULT_PACKET_ERROR BIT(5)
+#define PB_CML_FAULT_INVALID_DATA BIT(6)
+#define PB_CML_FAULT_INVALID_COMMAND BIT(7)
enum pmbus_sensor_classes {
PSC_VOLTAGE_IN = 0,
@@ -314,32 +319,34 @@ enum pmbus_sensor_classes {
#define PMBUS_PAGES 32 /* Per PMBus specification */
/* Functionality bit mask */
-#define PMBUS_HAVE_VIN (1 << 0)
-#define PMBUS_HAVE_VCAP (1 << 1)
-#define PMBUS_HAVE_VOUT (1 << 2)
-#define PMBUS_HAVE_IIN (1 << 3)
-#define PMBUS_HAVE_IOUT (1 << 4)
-#define PMBUS_HAVE_PIN (1 << 5)
-#define PMBUS_HAVE_POUT (1 << 6)
-#define PMBUS_HAVE_FAN12 (1 << 7)
-#define PMBUS_HAVE_FAN34 (1 << 8)
-#define PMBUS_HAVE_TEMP (1 << 9)
-#define PMBUS_HAVE_TEMP2 (1 << 10)
-#define PMBUS_HAVE_TEMP3 (1 << 11)
-#define PMBUS_HAVE_STATUS_VOUT (1 << 12)
-#define PMBUS_HAVE_STATUS_IOUT (1 << 13)
-#define PMBUS_HAVE_STATUS_INPUT (1 << 14)
-#define PMBUS_HAVE_STATUS_TEMP (1 << 15)
-#define PMBUS_HAVE_STATUS_FAN12 (1 << 16)
-#define PMBUS_HAVE_STATUS_FAN34 (1 << 17)
-#define PMBUS_HAVE_VMON (1 << 18)
-#define PMBUS_HAVE_STATUS_VMON (1 << 19)
+#define PMBUS_HAVE_VIN BIT(0)
+#define PMBUS_HAVE_VCAP BIT(1)
+#define PMBUS_HAVE_VOUT BIT(2)
+#define PMBUS_HAVE_IIN BIT(3)
+#define PMBUS_HAVE_IOUT BIT(4)
+#define PMBUS_HAVE_PIN BIT(5)
+#define PMBUS_HAVE_POUT BIT(6)
+#define PMBUS_HAVE_FAN12 BIT(7)
+#define PMBUS_HAVE_FAN34 BIT(8)
+#define PMBUS_HAVE_TEMP BIT(9)
+#define PMBUS_HAVE_TEMP2 BIT(10)
+#define PMBUS_HAVE_TEMP3 BIT(11)
+#define PMBUS_HAVE_STATUS_VOUT BIT(12)
+#define PMBUS_HAVE_STATUS_IOUT BIT(13)
+#define PMBUS_HAVE_STATUS_INPUT BIT(14)
+#define PMBUS_HAVE_STATUS_TEMP BIT(15)
+#define PMBUS_HAVE_STATUS_FAN12 BIT(16)
+#define PMBUS_HAVE_STATUS_FAN34 BIT(17)
+#define PMBUS_HAVE_VMON BIT(18)
+#define PMBUS_HAVE_STATUS_VMON BIT(19)
enum pmbus_data_format { linear = 0, direct, vid };
+enum vrm_version { vr11 = 0, vr12 };
struct pmbus_driver_info {
int pages; /* Total number of pages */
enum pmbus_data_format format[PSC_NUM_CLASSES];
+ enum vrm_version vrm_version;
/*
* Support one set of coefficients for each sensor type
* Used for chips providing data in direct mode.
@@ -380,7 +387,7 @@ struct pmbus_driver_info {
/* Regulator ops */
-extern struct regulator_ops pmbus_regulator_ops;
+extern const struct regulator_ops pmbus_regulator_ops;
/* Macro for filling in array of struct regulator_desc */
#define PMBUS_REGULATOR(_name, _id) \
@@ -390,6 +397,7 @@ extern struct regulator_ops pmbus_regulator_ops;
.of_match = of_match_ptr(_name # _id), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &pmbus_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index f2e47c7dd..ba59eaef2 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -515,16 +515,24 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
/*
* Convert VID sensor values to milli- or micro-units
* depending on sensor type.
- * We currently only support VR11.
*/
static long pmbus_reg2data_vid(struct pmbus_data *data,
struct pmbus_sensor *sensor)
{
long val = sensor->data;
+ long rv = 0;
- if (val < 0x02 || val > 0xb2)
- return 0;
- return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
+ switch (data->info->vrm_version) {
+ case vr11:
+ if (val >= 0x02 && val <= 0xb2)
+ rv = DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
+ break;
+ case vr12:
+ if (val >= 0x01)
+ rv = 250 + (val - 1) * 5;
+ break;
+ }
+ return rv;
}
static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
@@ -1329,6 +1337,10 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
.update = true,
.attr = "average",
}, {
+ .reg = PMBUS_VIRT_READ_PIN_MIN,
+ .update = true,
+ .attr = "input_lowest",
+ }, {
.reg = PMBUS_VIRT_READ_PIN_MAX,
.update = true,
.attr = "input_highest",
@@ -1359,6 +1371,10 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
.update = true,
.attr = "average",
}, {
+ .reg = PMBUS_VIRT_READ_POUT_MIN,
+ .update = true,
+ .attr = "input_lowest",
+ }, {
.reg = PMBUS_VIRT_READ_POUT_MAX,
.update = true,
.attr = "input_highest",
@@ -1735,6 +1751,11 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
}
}
+ /* Enable PEC if the controller supports it */
+ ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
+ if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
+ client->flags |= I2C_CLIENT_PEC;
+
pmbus_clear_faults(client);
if (info->identify) {
@@ -1796,7 +1817,7 @@ static int pmbus_regulator_disable(struct regulator_dev *rdev)
return _pmbus_regulator_on_off(rdev, 0);
}
-struct regulator_ops pmbus_regulator_ops = {
+const struct regulator_ops pmbus_regulator_ops = {
.enable = pmbus_regulator_enable,
.disable = pmbus_regulator_disable,
.is_enabled = pmbus_regulator_is_enabled,
diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c
index 819644121..771802d7e 100644
--- a/drivers/hwmon/pmbus/zl6100.c
+++ b/drivers/hwmon/pmbus/zl6100.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -44,16 +45,16 @@ struct zl6100_data {
#define ZL6100_MFR_CONFIG 0xd0
#define ZL6100_DEVICE_ID 0xe4
-#define ZL6100_MFR_XTEMP_ENABLE (1 << 7)
+#define ZL6100_MFR_XTEMP_ENABLE BIT(7)
#define MFR_VMON_OV_FAULT_LIMIT 0xf5
#define MFR_VMON_UV_FAULT_LIMIT 0xf6
#define MFR_READ_VMON 0xf7
-#define VMON_UV_WARNING (1 << 5)
-#define VMON_OV_WARNING (1 << 4)
-#define VMON_UV_FAULT (1 << 1)
-#define VMON_OV_FAULT (1 << 0)
+#define VMON_UV_WARNING BIT(5)
+#define VMON_OV_WARNING BIT(4)
+#define VMON_UV_FAULT BIT(1)
+#define VMON_OV_FAULT BIT(0)
#define ZL6100_WAIT_TIME 1000 /* uS */