aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus/ltc2978.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pmbus/ltc2978.c')
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 7e10fbf8e133..28e1e735b5c2 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -25,13 +25,13 @@
#include <linux/regulator/driver.h>
#include "pmbus.h"
-enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
+enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3882, ltc3883, 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 /* Not on LTC3882 */
/* LTC2974, LCT2977, and LTC2978 */
#define LTC2978_MFR_VOUT_MIN 0xfb
@@ -42,7 +42,7 @@ enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
#define LTC2974_MFR_IOUT_PEAK 0xd7
#define LTC2974_MFR_IOUT_MIN 0xd8
-/* LTC3880, LTC3883, and LTM4676 */
+/* LTC3880, LTC3882, LTC3883, and LTM4676 */
#define LTC3880_MFR_IOUT_PEAK 0xd7
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
@@ -313,7 +313,7 @@ static int ltc2978_clear_peaks(struct i2c_client *client, int page,
{
int ret;
- if (id == ltc3880 || id == ltc3883 || id == ltm4676)
+ if (id == ltc3880 || id == ltc3882 || id == ltc3883 || id == ltm4676)
ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
else
ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
@@ -369,6 +369,7 @@ static const struct i2c_device_id ltc2978_id[] = {
{"ltc2977", ltc2977},
{"ltc2978", ltc2978},
{"ltc3880", ltc3880},
+ {"ltc3882", ltc3882},
{"ltc3883", ltc3883},
{"ltm4676", ltm4676},
{}
@@ -393,8 +394,30 @@ 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)
- return chip_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;
+ }
if (chip_id == LTC2974_ID_REV1 || chip_id == LTC2974_ID_REV2)
return ltc2974;
@@ -498,6 +521,20 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
break;
+ case ltc3882:
+ 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:
info->read_word_data = ltc3883_read_word_data;
info->pages = LTC3883_NUM_PAGES;
@@ -530,6 +567,7 @@ static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc2977" },
{ .compatible = "lltc,ltc2978" },
{ .compatible = "lltc,ltc3880" },
+ { .compatible = "lltc,ltc3882" },
{ .compatible = "lltc,ltc3883" },
{ .compatible = "lltc,ltm4676" },
{ }