|
@@ -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 = <c2978_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" },
|
|
|
{ }
|