Tested: No obvious hwmon directory entry or value reading changes after applying the patch 2 on MAX16601. Had to work around the pmbus_do_probe() in order to apply to the 5.1 kernel on my hand though. Thx! - Alex Qiu On Mon, Jan 25, 2021 at 10:53 AM Guenter Roeck <linux@xxxxxxxxxxxx> wrote: > > MAX16508 is quite similar to MAX16601, except that it does not support > the DEFAULT_NUM_POP register and we thus can not dynamically determine > the number of populated phases. > > Cc: Alex Qiu <xqiu@xxxxxxxxxx> > Cc: Ugur Usug <Ugur.Usug@xxxxxxxxxxxxxxxxxxx> > Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx> Reviewed-by: Alex Qiu <xqiu@xxxxxxxxxx> Tested-by: Alex Qiu <xqiu@xxxxxxxxxx> > --- > Tested with MAX16601 to ensure that it doesn't break existing support, > but untested on MAX16508. > > The most likely cause of failure is the chip detection string: The > datasheet suggests that it is "MAX16500" for all chips in the MAX165xx > series, but without hardware that is all but impossible to confirm. > > It should also be confirmed that REG_DEFAULT_NUM_POP (the expected > number of populated phases) is indeed not supported on MAX16508. > > Documentation/hwmon/max16601.rst | 12 +++++- > drivers/hwmon/pmbus/Kconfig | 4 +- > drivers/hwmon/pmbus/max16601.c | 74 +++++++++++++++++++++++--------- > 3 files changed, 66 insertions(+), 24 deletions(-) > > diff --git a/Documentation/hwmon/max16601.rst b/Documentation/hwmon/max16601.rst > index 93d25dfa028e..d16792be7533 100644 > --- a/Documentation/hwmon/max16601.rst > +++ b/Documentation/hwmon/max16601.rst > @@ -5,6 +5,14 @@ Kernel driver max16601 > > Supported chips: > > + * Maxim MAX16508 > + > + Prefix: 'max16508' > + > + Addresses scanned: - > + > + Datasheet: Not published > + > * Maxim MAX16601 > > Prefix: 'max16601' > @@ -19,8 +27,8 @@ Author: Guenter Roeck <linux@xxxxxxxxxxxx> > Description > ----------- > > -This driver supports the MAX16601 VR13.HC Dual-Output Voltage Regulator > -Chipset. > +This driver supports the MAX16508 VR13 Dual-Output Voltage Regulator > +as well as the MAX16601 VR13.HC Dual-Output Voltage Regulator chipsets. > > The driver is a client driver to the core PMBus driver. > Please see Documentation/hwmon/pmbus.rst for details on PMBus client drivers. > diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig > index 03606d4298a4..32d2fc850621 100644 > --- a/drivers/hwmon/pmbus/Kconfig > +++ b/drivers/hwmon/pmbus/Kconfig > @@ -158,10 +158,10 @@ config SENSORS_MAX16064 > be called max16064. > > config SENSORS_MAX16601 > - tristate "Maxim MAX16601" > + tristate "Maxim MAX16508, MAX16601" > help > If you say yes here you get hardware monitoring support for Maxim > - MAX16601. > + MAX16508 and MAX16601. > > This driver can also be built as a module. If so, the module will > be called max16601. > diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c > index efe6da3bc8d0..0d1204c2dd54 100644 > --- a/drivers/hwmon/pmbus/max16601.c > +++ b/drivers/hwmon/pmbus/max16601.c > @@ -1,11 +1,11 @@ > // SPDX-License-Identifier: GPL-2.0 > /* > - * Hardware monitoring driver for Maxim MAX16601 > + * Hardware monitoring driver for Maxim MAX16508 and MAX16601. > * > * Implementation notes: > * > - * Ths chip supports two rails, VCORE and VSA. Telemetry information for the > - * two rails is reported in two subsequent I2C addresses. The driver > + * This chip series supports two rails, VCORE and VSA. Telemetry information > + * for the two rails is reported in two subsequent I2C addresses. The driver > * instantiates a dummy I2C client at the second I2C address to report > * information for the VSA rail in a single instance of the driver. > * Telemetry for the VSA rail is reported to the PMBus core in PMBus page 2. > @@ -31,6 +31,8 @@ > > #include "pmbus.h" > > +enum chips { max16508, max16601 }; > + > #define REG_DEFAULT_NUM_POP 0xc4 > #define REG_SETPT_DVID 0xd1 > #define DAC_10MV_MODE BIT(4) > @@ -44,6 +46,7 @@ > #define MAX16601_NUM_PHASES 8 > > struct max16601_data { > + enum chips id; > struct pmbus_driver_info info; > struct i2c_client *vsa; > int iout_avg_pkg; > @@ -188,6 +191,7 @@ static int max16601_write_word(struct i2c_client *client, int page, int reg, > static int max16601_identify(struct i2c_client *client, > struct pmbus_driver_info *info) > { > + struct max16601_data *data = to_max16601_data(info); > int reg; > > reg = i2c_smbus_read_byte_data(client, REG_SETPT_DVID); > @@ -198,6 +202,9 @@ static int max16601_identify(struct i2c_client *client, > else > info->vrm_version[0] = vr12; > > + if (data->id != max16601) > + return 0; > + > reg = i2c_smbus_read_byte_data(client, REG_DEFAULT_NUM_POP); > if (reg < 0) > return reg; > @@ -254,28 +261,61 @@ static void max16601_remove(void *_data) > i2c_unregister_device(data->vsa); > } > > -static int max16601_probe(struct i2c_client *client) > +static const struct i2c_device_id max16601_id[] = { > + {"max16508", max16508}, > + {"max16601", max16601}, > + {} > +}; > +MODULE_DEVICE_TABLE(i2c, max16601_id); > + > +static int max16601_get_id(struct i2c_client *client) > { > struct device *dev = &client->dev; > u8 buf[I2C_SMBUS_BLOCK_MAX + 1]; > - struct max16601_data *data; > + enum chips id; > int ret; > > - if (!i2c_check_functionality(client->adapter, > - I2C_FUNC_SMBUS_READ_BYTE_DATA | > - I2C_FUNC_SMBUS_READ_BLOCK_DATA)) > - return -ENODEV; > - > ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf); > - if (ret < 0) > + if (ret < 0 || ret < 11) > return -ENODEV; > > - /* PMBUS_IC_DEVICE_ID is expected to return "MAX16601y.xx" */ > - if (ret < 11 || strncmp(buf, "MAX16601", 8)) { > + /* > + * PMBUS_IC_DEVICE_ID is expected to return "MAX16601y.xx" > + * or "MAX16500y.xx". > + */ > + if (!strncmp(buf, "MAX16500", 8)) { > + id = max16508; > + } else if (!strncmp(buf, "MAX16601", 8)) { > + id = max16601; > + } else { > buf[ret] = '\0'; > dev_err(dev, "Unsupported chip '%s'\n", buf); > return -ENODEV; > } > + return id; > +} > + > +static int max16601_probe(struct i2c_client *client) > +{ > + struct device *dev = &client->dev; > + const struct i2c_device_id *id; > + struct max16601_data *data; > + int ret, chip_id; > + > + if (!i2c_check_functionality(client->adapter, > + I2C_FUNC_SMBUS_READ_BYTE_DATA | > + I2C_FUNC_SMBUS_READ_BLOCK_DATA)) > + return -ENODEV; > + > + chip_id = max16601_get_id(client); > + if (chip_id < 0) > + return chip_id; > + > + id = i2c_match_id(max16601_id, client); > + if (chip_id != id->driver_data) > + dev_warn(&client->dev, > + "Device mismatch: Configured %s (%d), detected %d\n", > + id->name, (int) id->driver_data, chip_id); > > ret = i2c_smbus_read_byte_data(client, REG_PHASE_ID); > if (ret < 0) > @@ -290,6 +330,7 @@ static int max16601_probe(struct i2c_client *client) > if (!data) > return -ENOMEM; > > + data->id = chip_id; > data->iout_avg_pkg = 0xfc00; > data->vsa = i2c_new_dummy_device(client->adapter, client->addr + 1); > if (IS_ERR(data->vsa)) { > @@ -305,13 +346,6 @@ static int max16601_probe(struct i2c_client *client) > return pmbus_do_probe(client, &data->info); > } > > -static const struct i2c_device_id max16601_id[] = { > - {"max16601", 0}, > - {} > -}; > - > -MODULE_DEVICE_TABLE(i2c, max16601_id); > - > static struct i2c_driver max16601_driver = { > .driver = { > .name = "max16601", > -- > 2.17.1 >