in eeprom/at24.c [584:792]
static int at24_probe(struct i2c_client *client)
{
struct regmap_config regmap_config = { };
struct nvmem_config nvmem_config = { };
u32 byte_len, page_size, flags, addrw;
const struct at24_chip_data *cdata;
struct device *dev = &client->dev;
bool i2c_fn_i2c, i2c_fn_block;
unsigned int i, num_addresses;
struct at24_data *at24;
bool full_power;
struct regmap *regmap;
bool writable;
u8 test_byte;
int err;
i2c_fn_i2c = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
i2c_fn_block = i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK);
cdata = at24_get_chip_data(dev);
if (IS_ERR(cdata))
return PTR_ERR(cdata);
err = device_property_read_u32(dev, "pagesize", &page_size);
if (err)
/*
* This is slow, but we can't know all eeproms, so we better
* play safe. Specifying custom eeprom-types via device tree
* or properties is recommended anyhow.
*/
page_size = 1;
flags = cdata->flags;
if (device_property_present(dev, "read-only"))
flags |= AT24_FLAG_READONLY;
if (device_property_present(dev, "no-read-rollover"))
flags |= AT24_FLAG_NO_RDROL;
err = device_property_read_u32(dev, "address-width", &addrw);
if (!err) {
switch (addrw) {
case 8:
if (flags & AT24_FLAG_ADDR16)
dev_warn(dev,
"Override address width to be 8, while default is 16\n");
flags &= ~AT24_FLAG_ADDR16;
break;
case 16:
flags |= AT24_FLAG_ADDR16;
break;
default:
dev_warn(dev, "Bad \"address-width\" property: %u\n",
addrw);
}
}
err = device_property_read_u32(dev, "size", &byte_len);
if (err)
byte_len = cdata->byte_len;
if (!i2c_fn_i2c && !i2c_fn_block)
page_size = 1;
if (!page_size) {
dev_err(dev, "page_size must not be 0!\n");
return -EINVAL;
}
if (!is_power_of_2(page_size))
dev_warn(dev, "page_size looks suspicious (no power of 2)!\n");
err = device_property_read_u32(dev, "num-addresses", &num_addresses);
if (err) {
if (flags & AT24_FLAG_TAKE8ADDR)
num_addresses = 8;
else
num_addresses = DIV_ROUND_UP(byte_len,
(flags & AT24_FLAG_ADDR16) ? 65536 : 256);
}
if ((flags & AT24_FLAG_SERIAL) && (flags & AT24_FLAG_MAC)) {
dev_err(dev,
"invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
return -EINVAL;
}
regmap_config.val_bits = 8;
regmap_config.reg_bits = (flags & AT24_FLAG_ADDR16) ? 16 : 8;
regmap_config.disable_locking = true;
regmap = devm_regmap_init_i2c(client, ®map_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
at24 = devm_kzalloc(dev, struct_size(at24, client_regmaps, num_addresses),
GFP_KERNEL);
if (!at24)
return -ENOMEM;
mutex_init(&at24->lock);
at24->byte_len = byte_len;
at24->page_size = page_size;
at24->flags = flags;
at24->read_post = cdata->read_post;
at24->bank_addr_shift = cdata->bank_addr_shift;
at24->num_addresses = num_addresses;
at24->offset_adj = at24_get_offset_adj(flags, byte_len);
at24->client_regmaps[0] = regmap;
at24->vcc_reg = devm_regulator_get(dev, "vcc");
if (IS_ERR(at24->vcc_reg))
return PTR_ERR(at24->vcc_reg);
writable = !(flags & AT24_FLAG_READONLY);
if (writable) {
at24->write_max = min_t(unsigned int,
page_size, at24_io_limit);
if (!i2c_fn_i2c && at24->write_max > I2C_SMBUS_BLOCK_MAX)
at24->write_max = I2C_SMBUS_BLOCK_MAX;
}
/* use dummy devices for multiple-address chips */
for (i = 1; i < num_addresses; i++) {
err = at24_make_dummy_client(at24, i, client, ®map_config);
if (err)
return err;
}
/*
* We initialize nvmem_config.id to NVMEM_DEVID_AUTO even if the
* label property is set as some platform can have multiple eeproms
* with same label and we can not register each of those with same
* label. Failing to register those eeproms trigger cascade failure
* on such platform.
*/
nvmem_config.id = NVMEM_DEVID_AUTO;
if (device_property_present(dev, "label")) {
err = device_property_read_string(dev, "label",
&nvmem_config.name);
if (err)
return err;
} else {
nvmem_config.name = dev_name(dev);
}
nvmem_config.type = NVMEM_TYPE_EEPROM;
nvmem_config.dev = dev;
nvmem_config.read_only = !writable;
nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
nvmem_config.owner = THIS_MODULE;
nvmem_config.compat = true;
nvmem_config.base_dev = dev;
nvmem_config.reg_read = at24_read;
nvmem_config.reg_write = at24_write;
nvmem_config.priv = at24;
nvmem_config.stride = 1;
nvmem_config.word_size = 1;
nvmem_config.size = byte_len;
i2c_set_clientdata(client, at24);
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
err = regulator_enable(at24->vcc_reg);
if (err) {
dev_err(dev, "Failed to enable vcc regulator\n");
return err;
}
pm_runtime_set_active(dev);
}
pm_runtime_enable(dev);
at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
if (IS_ERR(at24->nvmem)) {
pm_runtime_disable(dev);
if (!pm_runtime_status_suspended(dev))
regulator_disable(at24->vcc_reg);
return PTR_ERR(at24->nvmem);
}
/*
* Perform a one-byte test read to verify that the chip is functional,
* unless powering on the device is to be avoided during probe (i.e.
* it's powered off right now).
*/
if (full_power) {
err = at24_read(at24, 0, &test_byte, 1);
if (err) {
pm_runtime_disable(dev);
if (!pm_runtime_status_suspended(dev))
regulator_disable(at24->vcc_reg);
return -ENODEV;
}
}
pm_runtime_idle(dev);
if (writable)
dev_info(dev, "%u byte %s EEPROM, writable, %u bytes/write\n",
byte_len, client->name, at24->write_max);
else
dev_info(dev, "%u byte %s EEPROM, read-only\n",
byte_len, client->name);
return 0;
}