summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Wolf <W_Armin@gmx.de>2024-06-25 08:34:59 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-07-04 12:02:56 +0200
commit79d0df36b54179ac2192e56ad7fdb29c952f35e2 (patch)
tree1a77645361c2bb6113e6aa56b41e88a78ecae7b9
parent55d57ef6fa97ca631d393cccc641cbe1b16cc382 (diff)
eeprom: ee1004: Add nvmem support
Currently the driver does not register a nvmem provider, which means that userspace programs cannot access the ee1004 EEPROM through the standard nvmem sysfs API. Fix this by replacing the custom sysfs attribute with a standard nvmem interface, which also takes care of backwards compatibility. Tested on a Dell Inspiron 3505. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://lore.kernel.org/r/20240625063459.429953-2-W_Armin@gmx.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/eeprom/Kconfig2
-rw-r--r--drivers/misc/eeprom/ee1004.c58
2 files changed, 40 insertions, 20 deletions
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 4e61ac18cc96..9df12399bda3 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -109,6 +109,8 @@ config EEPROM_IDT_89HPESX
config EEPROM_EE1004
tristate "SPD EEPROMs on DDR4 memory modules"
depends on I2C && SYSFS
+ select NVMEM
+ select NVMEM_SYSFS
help
Enable this driver to get read support to SPD EEPROMs following
the JEDEC EE1004 standard. These are typically found on DDR4
diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c
index b1f760cc3be0..2e69024380b6 100644
--- a/drivers/misc/eeprom/ee1004.c
+++ b/drivers/misc/eeprom/ee1004.c
@@ -16,6 +16,7 @@
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/nvmem-provider.h>
/*
* DDR4 memory modules use special EEPROMs following the Jedec EE1004
@@ -145,13 +146,17 @@ static ssize_t ee1004_eeprom_read(struct i2c_client *client, char *buf,
return i2c_smbus_read_i2c_block_data_or_emulated(client, offset, count, buf);
}
-static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+static int ee1004_read(void *priv, unsigned int off, void *val, size_t count)
{
- struct i2c_client *client = kobj_to_i2c_client(kobj);
- size_t requested = count;
- int ret = 0;
+ struct i2c_client *client = priv;
+ char *buf = val;
+ int ret;
+
+ if (unlikely(!count))
+ return count;
+
+ if (off + count > EE1004_EEPROM_SIZE)
+ return -EINVAL;
/*
* Read data from chip, protecting against concurrent access to
@@ -161,28 +166,21 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
while (count) {
ret = ee1004_eeprom_read(client, buf, off, count);
- if (ret < 0)
- goto out;
+ if (ret < 0) {
+ mutex_unlock(&ee1004_bus_lock);
+ return ret;
+ }
buf += ret;
off += ret;
count -= ret;
}
-out:
+
mutex_unlock(&ee1004_bus_lock);
- return ret < 0 ? ret : requested;
+ return 0;
}
-static BIN_ATTR_RO(eeprom, EE1004_EEPROM_SIZE);
-
-static struct bin_attribute *ee1004_attrs[] = {
- &bin_attr_eeprom,
- NULL
-};
-
-BIN_ATTRIBUTE_GROUPS(ee1004);
-
static void ee1004_probe_temp_sensor(struct i2c_client *client)
{
struct i2c_board_info info = { .type = "jc42" };
@@ -220,7 +218,24 @@ static void ee1004_cleanup_bus_data(void *data)
static int ee1004_probe(struct i2c_client *client)
{
+ struct nvmem_config config = {
+ .dev = &client->dev,
+ .name = dev_name(&client->dev),
+ .id = NVMEM_DEVID_NONE,
+ .owner = THIS_MODULE,
+ .type = NVMEM_TYPE_EEPROM,
+ .read_only = true,
+ .root_only = false,
+ .reg_read = ee1004_read,
+ .size = EE1004_EEPROM_SIZE,
+ .word_size = 1,
+ .stride = 1,
+ .priv = client,
+ .compat = true,
+ .base_dev = &client->dev,
+ };
struct ee1004_bus_data *bd;
+ struct nvmem_device *ndev;
int err, cnr = 0;
/* Make sure we can operate on this adapter */
@@ -272,6 +287,10 @@ static int ee1004_probe(struct i2c_client *client)
mutex_unlock(&ee1004_bus_lock);
+ ndev = devm_nvmem_register(&client->dev, &config);
+ if (IS_ERR(ndev))
+ return PTR_ERR(ndev);
+
dev_info(&client->dev,
"%u byte EE1004-compliant SPD EEPROM, read-only\n",
EE1004_EEPROM_SIZE);
@@ -284,7 +303,6 @@ static int ee1004_probe(struct i2c_client *client)
static struct i2c_driver ee1004_driver = {
.driver = {
.name = "ee1004",
- .dev_groups = ee1004_groups,
},
.probe = ee1004_probe,
.id_table = ee1004_ids,