diff options
Diffstat (limited to 'drivers/misc/eeprom/at24.c')
| -rw-r--r-- | drivers/misc/eeprom/at24.c | 72 | 
1 files changed, 51 insertions, 21 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 0681d5fdd538..031eb64549af 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later  /*   * at24.c - handle most I2C EEPROMs   * @@ -6,23 +6,23 @@   * Copyright (C) 2008 Wolfram Sang, Pengutronix   */ -#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/i2c.h>  #include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h>  #include <linux/module.h> -#include <linux/of_device.h> -#include <linux/slab.h> -#include <linux/delay.h>  #include <linux/mutex.h> -#include <linux/mod_devicetable.h> -#include <linux/bitops.h> -#include <linux/jiffies.h> -#include <linux/property.h> -#include <linux/acpi.h> -#include <linux/i2c.h>  #include <linux/nvmem-provider.h> -#include <linux/regmap.h> +#include <linux/of_device.h>  #include <linux/pm_runtime.h> -#include <linux/gpio/consumer.h> +#include <linux/property.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h>  /* Address pointer is 16 bit. */  #define AT24_FLAG_ADDR16	BIT(7) @@ -88,8 +88,7 @@ struct at24_data {  	u8 flags;  	struct nvmem_device *nvmem; - -	struct gpio_desc *wp_gpio; +	struct regulator *vcc_reg;  	/*  	 * Some chips tie up multiple I2C addresses; dummy devices reserve @@ -457,12 +456,10 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)  	 * from this host, but not from other I2C masters.  	 */  	mutex_lock(&at24->lock); -	gpiod_set_value_cansleep(at24->wp_gpio, 0);  	while (count) {  		ret = at24_regmap_write(at24, buf, off, count);  		if (ret < 0) { -			gpiod_set_value_cansleep(at24->wp_gpio, 1);  			mutex_unlock(&at24->lock);  			pm_runtime_put(dev);  			return ret; @@ -472,7 +469,6 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)  		count -= ret;  	} -	gpiod_set_value_cansleep(at24->wp_gpio, 1);  	mutex_unlock(&at24->lock);  	pm_runtime_put(dev); @@ -662,9 +658,9 @@ static int at24_probe(struct i2c_client *client)  	at24->client[0].client = client;  	at24->client[0].regmap = regmap; -	at24->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH); -	if (IS_ERR(at24->wp_gpio)) -		return PTR_ERR(at24->wp_gpio); +	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) { @@ -701,6 +697,12 @@ static int at24_probe(struct i2c_client *client)  	i2c_set_clientdata(client, at24); +	err = regulator_enable(at24->vcc_reg); +	if (err) { +		dev_err(dev, "Failed to enable vcc regulator\n"); +		return err; +	} +  	/* enable runtime pm */  	pm_runtime_set_active(dev);  	pm_runtime_enable(dev); @@ -713,6 +715,7 @@ static int at24_probe(struct i2c_client *client)  	pm_runtime_idle(dev);  	if (err) {  		pm_runtime_disable(dev); +		regulator_disable(at24->vcc_reg);  		return -ENODEV;  	} @@ -728,15 +731,42 @@ static int at24_probe(struct i2c_client *client)  static int at24_remove(struct i2c_client *client)  { +	struct at24_data *at24 = i2c_get_clientdata(client); +  	pm_runtime_disable(&client->dev); +	if (!pm_runtime_status_suspended(&client->dev)) +		regulator_disable(at24->vcc_reg);  	pm_runtime_set_suspended(&client->dev);  	return 0;  } +static int __maybe_unused at24_suspend(struct device *dev) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct at24_data *at24 = i2c_get_clientdata(client); + +	return regulator_disable(at24->vcc_reg); +} + +static int __maybe_unused at24_resume(struct device *dev) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct at24_data *at24 = i2c_get_clientdata(client); + +	return regulator_enable(at24->vcc_reg); +} + +static const struct dev_pm_ops at24_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, +				pm_runtime_force_resume) +	SET_RUNTIME_PM_OPS(at24_suspend, at24_resume, NULL) +}; +  static struct i2c_driver at24_driver = {  	.driver = {  		.name = "at24", +		.pm = &at24_pm_ops,  		.of_match_table = at24_of_match,  		.acpi_match_table = ACPI_PTR(at24_acpi_ids),  	},  |