in pmbus/zl6100.c [318:458]
static int zl6100_probe(struct i2c_client *client)
{
int ret, i;
struct zl6100_data *data;
struct pmbus_driver_info *info;
u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
const struct i2c_device_id *mid;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_WORD_DATA
| I2C_FUNC_SMBUS_READ_BLOCK_DATA))
return -ENODEV;
ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
device_id);
if (ret < 0) {
dev_err(&client->dev, "Failed to read device ID\n");
return ret;
}
device_id[ret] = '\0';
dev_info(&client->dev, "Device ID %s\n", device_id);
mid = NULL;
for (mid = zl6100_id; mid->name[0]; mid++) {
if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
break;
}
if (!mid->name[0]) {
dev_err(&client->dev, "Unsupported device\n");
return -ENODEV;
}
if (strcmp(client->name, mid->name) != 0)
dev_notice(&client->dev,
"Device mismatch: Configured %s, detected %s\n",
client->name, mid->name);
data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
data->id = mid->driver_data;
/*
* According to information from the chip vendor, all currently
* supported chips are known to require a wait time between I2C
* accesses.
*/
data->delay = delay;
/*
* Since there was a direct I2C device access above, wait before
* accessing the chip again.
*/
data->access = ktime_get();
zl6100_wait(data);
info = &data->info;
info->pages = 1;
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_TEMP | PMBUS_HAVE_STATUS_TEMP;
/*
* ZL2004, ZL8802, ZL9101M, ZL9117M and ZLS4009 support monitoring
* an extra voltage (VMON for ZL2004, ZL8802 and ZLS4009,
* VDRV for ZL9101M and ZL9117M). Report it as vmon.
*/
if (data->id == zl2004 || data->id == zl8802 || data->id == zl9101 ||
data->id == zl9117 || data->id == zls4009)
info->func[0] |= PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON;
/*
* ZL8802 has two outputs that can be used either independently or in
* a current sharing configuration. The driver uses the DDC_CONFIG
* register to check if the module is running with independent or
* shared outputs. If the module is in shared output mode, only one
* output voltage will be reported.
*/
if (data->id == zl8802) {
info->pages = 2;
info->func[0] |= PMBUS_HAVE_IIN;
ret = i2c_smbus_read_word_data(client, ZL8802_MFR_DDC_CONFIG);
if (ret < 0)
return ret;
data->access = ktime_get();
zl6100_wait(data);
if (ret & ZL8802_MFR_PHASES_MASK)
info->func[1] |= PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
else
info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
for (i = 0; i < 2; i++) {
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
if (ret < 0)
return ret;
data->access = ktime_get();
zl6100_wait(data);
ret = i2c_smbus_read_word_data(client, ZL8802_MFR_USER_CONFIG);
if (ret < 0)
return ret;
if (ret & ZL8802_MFR_XTEMP_ENABLE_2)
info->func[i] |= PMBUS_HAVE_TEMP2;
data->access = ktime_get();
zl6100_wait(data);
}
ret = i2c_smbus_read_word_data(client, ZL8802_MFR_USER_GLOBAL_CONFIG);
if (ret < 0)
return ret;
if (ret & ZL8802_MFR_TMON_ENABLE)
info->func[0] |= PMBUS_HAVE_TEMP3;
} else {
ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
if (ret < 0)
return ret;
if (ret & ZL6100_MFR_XTEMP_ENABLE)
info->func[0] |= PMBUS_HAVE_TEMP2;
}
data->access = ktime_get();
zl6100_wait(data);
info->read_word_data = zl6100_read_word_data;
info->read_byte_data = zl6100_read_byte_data;
info->write_word_data = zl6100_write_word_data;
info->write_byte = zl6100_write_byte;
return pmbus_do_probe(client, info);
}