In certain use cases (where the chip is part of a camera module, and the camera module is wired together with a camera privacy LED), powering on the device during probe is undesirable. Add support for the at24 to execute probe while being powered off. For this to happen, a hint in form of a device property is required from the firmware. Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> --- drivers/misc/eeprom/at24.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 63aa541c96088..b9dbe5b6a97be 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -579,6 +579,7 @@ static int at24_probe(struct i2c_client *client) bool i2c_fn_i2c, i2c_fn_block; unsigned int i, num_addresses; struct at24_data *at24; + bool powered_off; struct regmap *regmap; size_t at24_size; bool writable; @@ -701,19 +702,24 @@ static int at24_probe(struct i2c_client *client) i2c_set_clientdata(client, at24); - /* enable runtime pm */ - pm_runtime_set_active(dev); + powered_off = acpi_dev_powered_off_for_probe(&client->dev); + if (!powered_off) + pm_runtime_set_active(dev); + pm_runtime_enable(dev); /* - * Perform a one-byte test read to verify that the - * chip is functional. + * 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). */ - err = at24_read(at24, 0, &test_byte, 1); - pm_runtime_idle(dev); - if (err) { - err = -ENODEV; - goto err_clients; + if (!powered_off) { + err = at24_read(at24, 0, &test_byte, 1); + pm_runtime_idle(dev); + if (err) { + err = -ENODEV; + goto err_clients; + } } nvmem_config.name = dev_name(dev); @@ -752,12 +758,15 @@ static int at24_probe(struct i2c_client *client) static int at24_remove(struct i2c_client *client) { struct at24_data *at24; + bool powered_off; at24 = i2c_get_clientdata(client); at24_remove_dummy_clients(at24); pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + powered_off = acpi_dev_powered_off_for_probe(&client->dev); + if (!powered_off) + pm_runtime_set_suspended(&client->dev); return 0; } @@ -765,6 +774,7 @@ static int at24_remove(struct i2c_client *client) static struct i2c_driver at24_driver = { .driver = { .name = "at24", + .probe_powered_off = true, .of_match_table = at24_of_match, .acpi_match_table = ACPI_PTR(at24_acpi_ids), }, -- 2.11.0