at24 updates for linux v5.6
- minor maintenance: update the license tag, sort headers - move support for the write-protect pin into nvmem core - add a reference to the new wp-gpios property in nvmem to at25 bindings - add support for regulator and pm_runtime control -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAl4rHlAACgkQEacuoBRx 13J9Ug//dprb3sJZDiFrktJBVgCJ8+6l88gXwrkTNDGXGnrE3W4YGA12YO8NQPFR hGHLegV+LZCSebcxL7iY69UCMMCLQ5cGKUMXfIJqJQfSBV8em1+81DMHSFh0kJPn jVgPo4JAqq0JJPuXz7YQnqtJtksSsBVvxbglm7dSXpF61eqnFEO/Xi80IM3uoqSK 1FMgu+2PweH4CYPL272bgwRLFLGyzQaI8EQhCvzov+ye8Z1ctVXUmjojmtZCanTM 1XLTBdwNJKd6ogFpD6YGGBBg53mgANDY4P++DxO7yk7QjhyaculbDPDp43KvJcnO QR7PswnMT+78KmJOtxsShLMUCoaNe7aSgq+luby0Zdb2KwZY/K9gOUN6XbsqppEY qH3pQdzRZ6k8jZL8QWjemZ1g1B4z6qfbR10k0F5yg8bzXDFlpaRja2wFV63YZk6k ld9BHfGss/mR7XztfM4/Tb7Cj5asV6jnX4LGWvK4Va1UZE69QeUKTXYVQIc5v/fB hCzkYPW496Yoh0i785eJMwJ5PgwhYhXK+b/panMibFwGttIMxKf/sKejLeOxsMTv z20awOCCdo1soCcci6YkOrjN1Lj2EViWg/i0oWsV1FxkKUkPzR3fXRrPgSp0zZ7e vKIjU3Ej9QQyuMOxguVm2gB9gj6hB7oTBBlgNb1uQ7Zf1f9Z18Q= =jh24 -----END PGP SIGNATURE----- Merge tag 'at24-updates-for-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into i2c/for-5.6 at24 updates for linux v5.6 - minor maintenance: update the license tag, sort headers - move support for the write-protect pin into nvmem core - add a reference to the new wp-gpios property in nvmem to at25 bindings - add support for regulator and pm_runtime control
This commit is contained in:
commit
6810df46c4
|
@ -145,10 +145,7 @@ properties:
|
|||
over reads to the next slave address. Please consult the manual of
|
||||
your device.
|
||||
|
||||
wp-gpios:
|
||||
description:
|
||||
GPIO to which the write-protect pin of the chip is connected.
|
||||
maxItems: 1
|
||||
wp-gpios: true
|
||||
|
||||
address-width:
|
||||
allOf:
|
||||
|
@ -167,6 +164,10 @@ properties:
|
|||
minimum: 1
|
||||
maximum: 8
|
||||
|
||||
vcc-supply:
|
||||
description:
|
||||
phandle of the regulator that provides the supply voltage.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -20,6 +20,7 @@ Optional properties:
|
|||
- spi-cpha : SPI shifted clock phase, as per spi-bus bindings.
|
||||
- spi-cpol : SPI inverse clock polarity, as per spi-bus bindings.
|
||||
- read-only : this parameter-less property disables writes to the eeprom
|
||||
- wp-gpios : GPIO to which the write-protect pin of the chip is connected
|
||||
|
||||
Obsolete legacy properties can be used in place of "size", "pagesize",
|
||||
"address-width", and "read-only":
|
||||
|
@ -36,6 +37,7 @@ Example:
|
|||
spi-max-frequency = <5000000>;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
wp-gpios = <&gpio1 3 0>;
|
||||
|
||||
pagesize = <64>;
|
||||
size = <32768>;
|
||||
|
|
|
@ -34,6 +34,14 @@ properties:
|
|||
description:
|
||||
Mark the provider as read only.
|
||||
|
||||
wp-gpios:
|
||||
description:
|
||||
GPIO to which the write-protect pin of the chip is connected.
|
||||
The write-protect GPIO is asserted, when it's driven high
|
||||
(logical '1') to block the write operation. It's deasserted,
|
||||
when it's driven low (logical '0') to allow writing.
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
|
@ -63,9 +71,12 @@ patternProperties:
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
qfprom: eeprom@700000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
wp-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
/* ... */
|
||||
|
||||
|
|
|
@ -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/init.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/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/mutex.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),
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include "nvmem.h"
|
||||
|
@ -54,8 +55,14 @@ static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
|
|||
static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
if (nvmem->reg_write)
|
||||
return nvmem->reg_write(nvmem->priv, offset, val, bytes);
|
||||
int ret;
|
||||
|
||||
if (nvmem->reg_write) {
|
||||
gpiod_set_value_cansleep(nvmem->wp_gpio, 0);
|
||||
ret = nvmem->reg_write(nvmem->priv, offset, val, bytes);
|
||||
gpiod_set_value_cansleep(nvmem->wp_gpio, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -338,6 +345,14 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
|
|||
kfree(nvmem);
|
||||
return ERR_PTR(rval);
|
||||
}
|
||||
if (config->wp_gpio)
|
||||
nvmem->wp_gpio = config->wp_gpio;
|
||||
else
|
||||
nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(nvmem->wp_gpio))
|
||||
return ERR_CAST(nvmem->wp_gpio);
|
||||
|
||||
|
||||
kref_init(&nvmem->refcnt);
|
||||
INIT_LIST_HEAD(&nvmem->cells);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
struct nvmem_device {
|
||||
struct module *owner;
|
||||
|
@ -26,6 +27,7 @@ struct nvmem_device {
|
|||
struct list_head cells;
|
||||
nvmem_reg_read_t reg_read;
|
||||
nvmem_reg_write_t reg_write;
|
||||
struct gpio_desc *wp_gpio;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
struct nvmem_device;
|
||||
struct nvmem_cell_info;
|
||||
|
@ -45,6 +46,7 @@ enum nvmem_type {
|
|||
* @word_size: Minimum read/write access granularity.
|
||||
* @stride: Minimum read/write access stride.
|
||||
* @priv: User context passed to read/write callbacks.
|
||||
* @wp-gpio: Write protect pin
|
||||
*
|
||||
* Note: A default "nvmem<id>" name will be assigned to the device if
|
||||
* no name is specified in its configuration. In such case "<id>" is
|
||||
|
@ -58,6 +60,7 @@ struct nvmem_config {
|
|||
const char *name;
|
||||
int id;
|
||||
struct module *owner;
|
||||
struct gpio_desc *wp_gpio;
|
||||
const struct nvmem_cell_info *cells;
|
||||
int ncells;
|
||||
enum nvmem_type type;
|
||||
|
|
Loading…
Reference in New Issue