aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus/ltc2978.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2015-06-08 10:29:45 -0700
committerGuenter Roeck <linux@roeck-us.net>2015-08-12 12:29:22 -0700
commitbf89386f166b18c21b2b7a2c5b6e496726c4f25f (patch)
tree2b85e7be65eb6815ecf03ca24bd3723f17368863 /drivers/hwmon/pmbus/ltc2978.c
parenthwmon: (ltc2978) Move code to read chip ID into separate function (diff)
downloadlinux-dev-bf89386f166b18c21b2b7a2c5b6e496726c4f25f.tar.xz
linux-dev-bf89386f166b18c21b2b7a2c5b6e496726c4f25f.zip
hwmon: (ltc2978) Add support for LTC3882
LTC3882 is mostly compatible with LTC3880. Major differences are that it does not measure the input current, and it no longer supports LTC's legacy mechanism to identify the chip. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
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" },
{ }