Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756719AbbLHOFk (ORCPT ); Tue, 8 Dec 2015 09:05:40 -0500 Received: from vps0.lunn.ch ([178.209.37.122]:32811 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754516AbbLHOFh (ORCPT ); Tue, 8 Dec 2015 09:05:37 -0500 From: Andrew Lunn To: GregKH , srinivas.kandagatla@linaro.org, maxime.ripard@free-electrons.com, wsa@the-dreams.de, broonie@kernel.org, vz@mleia.com Cc: afd@ti.com, linux-kernel@vger.kernel.org, Andrew Lunn Subject: [PATCH 5/6] eeprom: at25: extend driver to plug into the NVMEM framework Date: Tue, 8 Dec 2015 15:05:10 +0100 Message-Id: <1449583511-22521-6-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1449583511-22521-1-git-send-email-andrew@lunn.ch> References: <1449583511-22521-1-git-send-email-andrew@lunn.ch> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7271 Lines: 236 Add a regmap for accessing the EEPROM, and then use that with the NVMEM framework. Use it backward compatibility register function, so that the 'eeprom' file in sys is provided by the framework. Signed-off-by: Andrew Lunn --- drivers/misc/eeprom/Kconfig | 3 ++ drivers/misc/eeprom/at25.c | 123 ++++++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 55 deletions(-) diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 21d409730221..ff3e1dd751ec 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -33,6 +33,9 @@ config EEPROM_AT24 config EEPROM_AT25 tristate "SPI EEPROMs from most vendors" depends on SPI && SYSFS + select REGMAP + select NVMEM + select NVMEM_COMPAT help Enable this driver to get read/write support to most SPI EEPROMs, after you configure the board init code to know about each eeprom diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 4732f6997289..327db31153ec 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -31,8 +33,10 @@ struct at25_data { struct spi_device *spi; struct mutex lock; struct spi_eeprom chip; - struct bin_attribute bin; unsigned addrlen; + struct regmap_config regmap_config; + struct nvmem_config nvmem_config; + struct nvmem_device *nvmem; }; #define AT25_WREN 0x06 /* latch the write enable */ @@ -76,10 +80,10 @@ at25_ee_read( struct spi_message m; u8 instr; - if (unlikely(offset >= at25->bin.size)) + if (unlikely(offset >= at25->chip.byte_len)) return 0; - if ((offset + count) > at25->bin.size) - count = at25->bin.size - offset; + if ((offset + count) > at25->chip.byte_len) + count = at25->chip.byte_len - offset; if (unlikely(!count)) return count; @@ -130,21 +134,19 @@ at25_ee_read( return status ? status : count; } -static ssize_t -at25_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static int at25_regmap_read(void *context, const void *reg, size_t reg_size, + void *val, size_t val_size) { - struct device *dev; - struct at25_data *at25; - - dev = container_of(kobj, struct device, kobj); - at25 = dev_get_drvdata(dev); + struct at25_data *at25 = context; + off_t offset = *(u32 *)reg; + int err; - return at25_ee_read(at25, buf, off, count); + err = at25_ee_read(at25, val, offset, val_size); + if (err) + return err; + return 0; } - static ssize_t at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, size_t count) @@ -154,10 +156,10 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, unsigned buf_size; u8 *bounce; - if (unlikely(off >= at25->bin.size)) + if (unlikely(off >= at25->chip.byte_len)) return -EFBIG; - if ((off + count) > at25->bin.size) - count = at25->bin.size - off; + if ((off + count) > at25->chip.byte_len) + count = at25->chip.byte_len - off; if (unlikely(!count)) return count; @@ -264,20 +266,30 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, return written ? written : status; } -static ssize_t -at25_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static int at25_regmap_write(void *context, const void *data, size_t count) { - struct device *dev; - struct at25_data *at25; + struct at25_data *at25 = context; + const char *buf; + u32 offset; + size_t len; + int err; - dev = container_of(kobj, struct device, kobj); - at25 = dev_get_drvdata(dev); + memcpy(&offset, data, sizeof(offset)); + buf = (const char *)data + sizeof(offset); + len = count - sizeof(offset); - return at25_ee_write(at25, buf, off, count); + err = at25_ee_write(at25, buf, offset, len); + if (err) + return err; + return 0; } +static const struct regmap_bus at25_regmap_bus = { + .read = at25_regmap_read, + .write = at25_regmap_write, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + /*-------------------------------------------------------------------------*/ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) @@ -337,6 +349,7 @@ static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; struct spi_eeprom chip; + struct regmap *regmap; int err; int sr; int addrlen; @@ -381,35 +394,34 @@ static int at25_probe(struct spi_device *spi) spi_set_drvdata(spi, at25); at25->addrlen = addrlen; - /* Export the EEPROM bytes through sysfs, since that's convenient. - * And maybe to other kernel code; it might hold a board's Ethernet - * address, or board-specific calibration data generated on the - * manufacturing floor. - * - * Default to root-only access to the data; EEPROMs often hold data - * that's sensitive for read and/or write, like ethernet addresses, - * security codes, board-specific manufacturing calibrations, etc. - */ - sysfs_bin_attr_init(&at25->bin); - at25->bin.attr.name = "eeprom"; - at25->bin.attr.mode = S_IRUSR; - at25->bin.read = at25_bin_read; - - at25->bin.size = at25->chip.byte_len; - if (!(chip.flags & EE_READONLY)) { - at25->bin.write = at25_bin_write; - at25->bin.attr.mode |= S_IWUSR; - } + at25->regmap_config.reg_bits = 32; + at25->regmap_config.val_bits = 8; + at25->regmap_config.reg_stride = 1; + at25->regmap_config.max_register = chip.byte_len - 1; - err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin); - if (err) - return err; + regmap = devm_regmap_init(&spi->dev, &at25_regmap_bus, at25, + &at25->regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "regmap init failed\n"); + return PTR_ERR(regmap); + } - dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n", - (at25->bin.size < 1024) - ? at25->bin.size - : (at25->bin.size / 1024), - (at25->bin.size < 1024) ? "Byte" : "KByte", + at25->nvmem_config.name = dev_name(&spi->dev); + at25->nvmem_config.dev = &spi->dev; + at25->nvmem_config.read_only = chip.flags & EE_READONLY; + at25->nvmem_config.root_only = true; + at25->nvmem_config.owner = THIS_MODULE; + + at25->nvmem = nvmem_register_compat(&at25->nvmem_config, + &spi->dev); + if (IS_ERR(at25->nvmem)) + return PTR_ERR(at25->nvmem); + + dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n", + (chip.byte_len < 1024) + ? chip.byte_len + : (chip.byte_len / 1024), + (chip.byte_len < 1024) ? "Byte" : "KByte", at25->chip.name, (chip.flags & EE_READONLY) ? " (readonly)" : "", at25->chip.page_size); @@ -421,7 +433,8 @@ static int at25_remove(struct spi_device *spi) struct at25_data *at25; at25 = spi_get_drvdata(spi); - sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin); + nvmem_unregister(at25->nvmem); + return 0; } -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/