* [PATCH v6 1/7] eeprom: at24: add basic regmap_i2c support
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 2/7] eeprom: at24: change at24_translate_offset return type Heiner Kallweit
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
This patch adds basic regmap support to be used by subsequent
patches of this series.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- no changes
v4:
- no changes
v5:
- no changes
v6:
- no changes
---
drivers/misc/eeprom/Kconfig | 1 +
drivers/misc/eeprom/at24.c | 53 +++++++++++++++++++++++++++++++++++----------
2 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index de5876209..68a1ac929 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -4,6 +4,7 @@ config EEPROM_AT24
tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
depends on I2C && SYSFS
select NVMEM
+ select REGMAP_I2C
help
Enable this driver to get read/write support to most I2C EEPROMs
and compatible devices like FRAMs, SRAMs, ROMs etc. After you
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 305a7a464..ed930dfbb 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -24,6 +24,7 @@
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
#include <linux/platform_data/at24.h>
#include <linux/pm_runtime.h>
@@ -55,6 +56,11 @@
* which won't work on pure SMBus systems.
*/
+struct at24_client {
+ struct i2c_client *client;
+ struct regmap *regmap;
+};
+
struct at24_data {
struct at24_platform_data chip;
int use_smbus;
@@ -81,7 +87,7 @@ struct at24_data {
* Some chips tie up multiple I2C addresses; dummy devices reserve
* them for us, and we'll use them with SMBus calls.
*/
- struct i2c_client *client[];
+ struct at24_client client[];
};
/*
@@ -274,7 +280,7 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
*offset &= 0xff;
}
- return at24->client[i];
+ return at24->client[i].client;
}
static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
@@ -680,6 +686,16 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
}
}
+static const struct regmap_config regmap_config_8 = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static const struct regmap_config regmap_config_16 = {
+ .reg_bits = 16,
+ .val_bits = 8,
+};
+
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct at24_platform_data chip;
@@ -690,6 +706,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct at24_data *at24;
int err;
unsigned i, num_addresses;
+ const struct regmap_config *config;
u8 test_byte;
if (client->dev.platform_data) {
@@ -781,8 +798,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
num_addresses = DIV_ROUND_UP(chip.byte_len,
(chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
+ if (chip.flags & AT24_FLAG_ADDR16)
+ config = ®map_config_16;
+ else
+ config = ®map_config_8;
+
at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) +
- num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
+ num_addresses * sizeof(struct at24_client), GFP_KERNEL);
if (!at24)
return -ENOMEM;
@@ -792,6 +814,11 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
at24->chip = chip;
at24->num_addresses = num_addresses;
+ at24->client[0].client = client;
+ at24->client[0].regmap = devm_regmap_init_i2c(client, config);
+ if (IS_ERR(at24->client[0].regmap))
+ return PTR_ERR(at24->client[0].regmap);
+
if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) {
dev_err(&client->dev,
"invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
@@ -839,18 +866,22 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
}
- at24->client[0] = client;
-
/* use dummy devices for multiple-address chips */
for (i = 1; i < num_addresses; i++) {
- at24->client[i] = i2c_new_dummy(client->adapter,
- client->addr + i);
- if (!at24->client[i]) {
+ at24->client[i].client = i2c_new_dummy(client->adapter,
+ client->addr + i);
+ if (!at24->client[i].client) {
dev_err(&client->dev, "address 0x%02x unavailable\n",
client->addr + i);
err = -EADDRINUSE;
goto err_clients;
}
+ at24->client[i].regmap = devm_regmap_init_i2c(
+ at24->client[i].client, config);
+ if (IS_ERR(at24->client[i].regmap)) {
+ err = PTR_ERR(at24->client[i].regmap);
+ goto err_clients;
+ }
}
i2c_set_clientdata(client, at24);
@@ -909,8 +940,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
err_clients:
for (i = 1; i < num_addresses; i++)
- if (at24->client[i])
- i2c_unregister_device(at24->client[i]);
+ if (at24->client[i].client)
+ i2c_unregister_device(at24->client[i].client);
pm_runtime_disable(&client->dev);
@@ -927,7 +958,7 @@ static int at24_remove(struct i2c_client *client)
nvmem_unregister(at24->nvmem);
for (i = 1; i < at24->num_addresses; i++)
- i2c_unregister_device(at24->client[i]);
+ i2c_unregister_device(at24->client[i].client);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v6 2/7] eeprom: at24: change at24_translate_offset return type
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 1/7] eeprom: at24: add basic regmap_i2c support Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 3/7] eeprom: at24: add regmap-based write function Heiner Kallweit
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
Change return type of at24_translate_offset to *at24_client to make
member regmap accessible for subsequent patches of this series.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- improve readability
v4:
- no changes
v5:
- no changes
v6:
- no changes
---
drivers/misc/eeprom/at24.c | 42 ++++++++++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index ed930dfbb..a16e8ca12 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -267,8 +267,8 @@ MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
* one "eeprom" file not four, but larger reads would fail when
* they crossed certain pages.
*/
-static struct i2c_client *at24_translate_offset(struct at24_data *at24,
- unsigned int *offset)
+static struct at24_client *at24_translate_offset(struct at24_data *at24,
+ unsigned int *offset)
{
unsigned i;
@@ -280,17 +280,19 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
*offset &= 0xff;
}
- return at24->client[i].client;
+ return &at24->client[i];
}
static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
unsigned int offset, size_t count)
{
unsigned long timeout, read_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
int status;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
if (count > io_limit)
count = io_limit;
@@ -318,13 +320,15 @@ static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
unsigned int offset, size_t count)
{
unsigned long timeout, read_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
struct i2c_msg msg[2];
int status, i;
u8 msgbuf[2];
memset(msg, 0, sizeof(msg));
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
if (count > io_limit)
count = io_limit;
@@ -368,12 +372,14 @@ static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf,
unsigned int offset, size_t count)
{
unsigned long timeout, read_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
struct i2c_msg msg[2];
u8 addrbuf[2];
int status;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
memset(msg, 0, sizeof(msg));
msg[0].addr = client->addr;
@@ -421,12 +427,14 @@ static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf,
unsigned int offset, size_t count)
{
unsigned long timeout, read_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
struct i2c_msg msg[2];
u8 addrbuf[2];
int status;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
memset(msg, 0, sizeof(msg));
msg[0].addr = client->addr;
@@ -479,10 +487,12 @@ static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24,
unsigned int offset, size_t count)
{
unsigned long timeout, write_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
ssize_t status = 0;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
count = at24_adjust_write_count(at24, offset, count);
loop_until_timeout(timeout, write_time) {
@@ -506,10 +516,12 @@ static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24,
unsigned int offset, size_t count)
{
unsigned long timeout, write_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
ssize_t status = 0;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
loop_until_timeout(timeout, write_time) {
status = i2c_smbus_write_byte_data(client, offset, buf[0]);
@@ -530,12 +542,14 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
unsigned int offset, size_t count)
{
unsigned long timeout, write_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
struct i2c_msg msg;
ssize_t status = 0;
int i = 0;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ client = at24_client->client;
count = at24_adjust_write_count(at24, offset, count);
msg.addr = client->addr;
@@ -568,6 +582,7 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
+ struct at24_client *at24_client;
struct i2c_client *client;
char *buf = val;
int ret;
@@ -578,7 +593,8 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
if (off + count > at24->chip.byte_len)
return -EINVAL;
- client = at24_translate_offset(at24, &off);
+ at24_client = at24_translate_offset(at24, &off);
+ client = at24_client->client;
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
@@ -616,6 +632,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
static int at24_write(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
+ struct at24_client *at24_client;
struct i2c_client *client;
char *buf = val;
int ret;
@@ -626,7 +643,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
if (off + count > at24->chip.byte_len)
return -EINVAL;
- client = at24_translate_offset(at24, &off);
+ at24_client = at24_translate_offset(at24, &off);
+ client = at24_client->client;
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v6 3/7] eeprom: at24: add regmap-based write function
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 1/7] eeprom: at24: add basic regmap_i2c support Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 2/7] eeprom: at24: change at24_translate_offset return type Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 4/7] eeprom: at24: remove old write functions Heiner Kallweit
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
Add a regmap-based write function.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- improve readability
- re-introduce debug message
v4:
- no changes
v5:
- no changes
v6:
- no changes
---
drivers/misc/eeprom/at24.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index a16e8ca12..c3c32ee88 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -538,6 +538,31 @@ static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24,
return -ETIMEDOUT;
}
+static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf,
+ unsigned int offset, size_t count)
+{
+ unsigned long timeout, write_time;
+ struct at24_client *at24_client;
+ struct i2c_client *client;
+ struct regmap *regmap;
+ int ret;
+
+ at24_client = at24_translate_offset(at24, &offset);
+ regmap = at24_client->regmap;
+ client = at24_client->client;
+ count = at24_adjust_write_count(at24, offset, count);
+
+ loop_until_timeout(timeout, write_time) {
+ ret = regmap_bulk_write(regmap, offset, buf, count);
+ dev_dbg(&client->dev, "write %zu@%d --> %d (%ld)\n",
+ count, offset, ret, jiffies);
+ if (!ret)
+ return count;
+ }
+
+ return -ETIMEDOUT;
+}
+
static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
unsigned int offset, size_t count)
{
@@ -661,7 +686,7 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
while (count) {
int status;
- status = at24->write_func(at24, buf, off, count);
+ status = at24_regmap_write(at24, buf, off, count);
if (status < 0) {
mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v6 4/7] eeprom: at24: remove old write functions
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
` (2 preceding siblings ...)
2017-11-28 20:51 ` [PATCH v6 3/7] eeprom: at24: add regmap-based write function Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 5/7] eeprom: at24: add regmap-based read function Heiner Kallweit
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
Remove the old and now unused write functions.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- rebased
v4:
- no changes
v5:
- no changes
v6:
- no changes
---
drivers/misc/eeprom/at24.c | 117 ---------------------------------------------
1 file changed, 117 deletions(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index c3c32ee88..fa28d87f7 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -64,11 +64,8 @@ struct at24_client {
struct at24_data {
struct at24_platform_data chip;
int use_smbus;
- int use_smbus_write;
ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t);
- ssize_t (*write_func)(struct at24_data *,
- const char *, unsigned int, size_t);
/*
* Lock protects against activities from other Linux tasks,
@@ -76,7 +73,6 @@ struct at24_data {
*/
struct mutex lock;
- u8 *writebuf;
unsigned write_max;
unsigned num_addresses;
@@ -482,62 +478,6 @@ static size_t at24_adjust_write_count(struct at24_data *at24,
return count;
}
-static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24,
- const char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, write_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- ssize_t status = 0;
-
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
- count = at24_adjust_write_count(at24, offset, count);
-
- loop_until_timeout(timeout, write_time) {
- status = i2c_smbus_write_i2c_block_data(client,
- offset, count, buf);
- if (status == 0)
- status = count;
-
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24,
- const char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, write_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- ssize_t status = 0;
-
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
-
- loop_until_timeout(timeout, write_time) {
- status = i2c_smbus_write_byte_data(client, offset, buf[0]);
- if (status == 0)
- status = count;
-
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf,
unsigned int offset, size_t count)
{
@@ -563,47 +503,6 @@ static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf,
return -ETIMEDOUT;
}
-static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, write_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- struct i2c_msg msg;
- ssize_t status = 0;
- int i = 0;
-
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
- count = at24_adjust_write_count(at24, offset, count);
-
- msg.addr = client->addr;
- msg.flags = 0;
-
- /* msg.buf is u8 and casts will mask the values */
- msg.buf = at24->writebuf;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msg.buf[i++] = offset >> 8;
-
- msg.buf[i++] = offset;
- memcpy(&msg.buf[i], buf, count);
- msg.len = i + count;
-
- loop_until_timeout(timeout, write_time) {
- status = i2c_transfer(client->adapter, &msg, 1);
- if (status == 1)
- status = count;
-
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
@@ -853,7 +752,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
mutex_init(&at24->lock);
at24->use_smbus = use_smbus;
- at24->use_smbus_write = use_smbus_write;
at24->chip = chip;
at24->num_addresses = num_addresses;
@@ -877,15 +775,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
: at24_eeprom_read_i2c;
}
- if (at24->use_smbus) {
- if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA)
- at24->write_func = at24_eeprom_write_smbus_block;
- else
- at24->write_func = at24_eeprom_write_smbus_byte;
- } else {
- at24->write_func = at24_eeprom_write_i2c;
- }
-
writable = !(chip.flags & AT24_FLAG_READONLY);
if (writable) {
if (!use_smbus || use_smbus_write) {
@@ -897,12 +786,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
write_max = I2C_SMBUS_BLOCK_MAX;
at24->write_max = write_max;
-
- /* buffer (data + address at the beginning) */
- at24->writebuf = devm_kzalloc(&client->dev,
- write_max + 2, GFP_KERNEL);
- if (!at24->writebuf)
- return -ENOMEM;
} else {
dev_warn(&client->dev,
"cannot write due to controller restrictions.");
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v6 5/7] eeprom: at24: add regmap-based read function
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
` (3 preceding siblings ...)
2017-11-28 20:51 ` [PATCH v6 4/7] eeprom: at24: remove old write functions Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 6/7] eeprom: at24: remove old read functions Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 7/7] eeprom: at24: remove now unneeded smbus-related code Heiner Kallweit
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
Add regmap-based read function and instead of using three different
read functions (standard, mac, serial) use just one and factor out the
read offset adjustment for mac and serial to at24_adjust_read_offset.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- improve readability
- re-introduce debug message
- introduce at24_adjust_read_offset
v4:
- move offset adjustment calculation to probe function
v5:
- small style improvements to at24_get_offset_adj
v6:
- rebased
- add byte_len parameter to at24_get_offset_adj
---
drivers/misc/eeprom/at24.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index fa28d87f7..8172ca627 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -75,6 +75,7 @@ struct at24_data {
unsigned write_max;
unsigned num_addresses;
+ unsigned int offset_adj;
struct nvmem_config nvmem_config;
struct nvmem_device *nvmem;
@@ -312,6 +313,36 @@ static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
return -ETIMEDOUT;
}
+static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,
+ unsigned int offset, size_t count)
+{
+ unsigned long timeout, read_time;
+ struct at24_client *at24_client;
+ struct i2c_client *client;
+ struct regmap *regmap;
+ int ret;
+
+ at24_client = at24_translate_offset(at24, &offset);
+ regmap = at24_client->regmap;
+ client = at24_client->client;
+
+ if (count > io_limit)
+ count = io_limit;
+
+ /* adjust offset for mac and serial read ops */
+ offset += at24->offset_adj;
+
+ loop_until_timeout(timeout, read_time) {
+ ret = regmap_bulk_read(regmap, offset, buf, count);
+ dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+ count, offset, ret, jiffies);
+ if (!ret)
+ return count;
+ }
+
+ return -ETIMEDOUT;
+}
+
static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
unsigned int offset, size_t count)
{
@@ -535,7 +566,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
while (count) {
int status;
- status = at24->read_func(at24, buf, off, count);
+ status = at24_regmap_read(at24, buf, off, count);
if (status < 0) {
mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
@@ -628,6 +659,29 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
}
}
+static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
+{
+ if (flags & AT24_FLAG_MAC) {
+ /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
+ return 0xa0 - byte_len;
+ } else if (flags & AT24_FLAG_SERIAL && flags & AT24_FLAG_ADDR16) {
+ /*
+ * For 16 bit address pointers, the word address must contain
+ * a '10' sequence in bits 11 and 10 regardless of the
+ * intended position of the address pointer.
+ */
+ return 0x0800;
+ } else if (flags & AT24_FLAG_SERIAL) {
+ /*
+ * Otherwise the word address must begin with a '10' sequence,
+ * regardless of the intended address.
+ */
+ return 0x0080;
+ } else {
+ return 0;
+ }
+}
+
static const struct regmap_config regmap_config_8 = {
.reg_bits = 8,
.val_bits = 8,
@@ -754,6 +808,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
at24->use_smbus = use_smbus;
at24->chip = chip;
at24->num_addresses = num_addresses;
+ at24->offset_adj = at24_get_offset_adj(chip.flags, chip.byte_len);
at24->client[0].client = client;
at24->client[0].regmap = devm_regmap_init_i2c(client, config);
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v6 6/7] eeprom: at24: remove old read functions
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
` (4 preceding siblings ...)
2017-11-28 20:51 ` [PATCH v6 5/7] eeprom: at24: add regmap-based read function Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
2017-11-28 20:51 ` [PATCH v6 7/7] eeprom: at24: remove now unneeded smbus-related code Heiner Kallweit
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
Remove the old and now unused read functions.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- rebased
v4:
- rebased
v5:
- no changes
v6:
- no changes
---
drivers/misc/eeprom/at24.c | 186 ---------------------------------------------
1 file changed, 186 deletions(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 8172ca627..ad43f4ca1 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -63,9 +63,6 @@ struct at24_client {
struct at24_data {
struct at24_platform_data chip;
- int use_smbus;
-
- ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t);
/*
* Lock protects against activities from other Linux tasks,
@@ -280,39 +277,6 @@ static struct at24_client *at24_translate_offset(struct at24_data *at24,
return &at24->client[i];
}
-static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, read_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- int status;
-
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
-
- if (count > io_limit)
- count = io_limit;
-
- /* Smaller eeproms can work given some SMBus extension calls */
- if (count > I2C_SMBUS_BLOCK_MAX)
- count = I2C_SMBUS_BLOCK_MAX;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_smbus_read_i2c_block_data_or_emulated(client,
- offset,
- count, buf);
-
- dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,
unsigned int offset, size_t count)
{
@@ -343,146 +307,6 @@ static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,
return -ETIMEDOUT;
}
-static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, read_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- struct i2c_msg msg[2];
- int status, i;
- u8 msgbuf[2];
-
- memset(msg, 0, sizeof(msg));
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
-
- if (count > io_limit)
- count = io_limit;
-
- /*
- * When we have a better choice than SMBus calls, use a combined I2C
- * message. Write address; then read up to io_limit data bytes. Note
- * that read page rollover helps us here (unlike writes). msgbuf is
- * u8 and will cast to our needs.
- */
- i = 0;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msgbuf[i++] = offset >> 8;
- msgbuf[i++] = offset;
-
- msg[0].addr = client->addr;
- msg[0].buf = msgbuf;
- msg[0].len = i;
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_transfer(client->adapter, msg, 2);
- if (status == 2)
- status = count;
-
- dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, read_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- struct i2c_msg msg[2];
- u8 addrbuf[2];
- int status;
-
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
-
- memset(msg, 0, sizeof(msg));
- msg[0].addr = client->addr;
- msg[0].buf = addrbuf;
-
- /*
- * The address pointer of the device is shared between the regular
- * EEPROM array and the serial number block. The dummy write (part of
- * the sequential read protocol) ensures the address pointer is reset
- * to the desired position.
- */
- if (at24->chip.flags & AT24_FLAG_ADDR16) {
- /*
- * For 16 bit address pointers, the word address must contain
- * a '10' sequence in bits 11 and 10 regardless of the
- * intended position of the address pointer.
- */
- addrbuf[0] = 0x08;
- addrbuf[1] = offset;
- msg[0].len = 2;
- } else {
- /*
- * Otherwise the word address must begin with a '10' sequence,
- * regardless of the intended address.
- */
- addrbuf[0] = 0x80 + offset;
- msg[0].len = 1;
- }
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_transfer(client->adapter, msg, 2);
- if (status == 2)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, read_time;
- struct at24_client *at24_client;
- struct i2c_client *client;
- struct i2c_msg msg[2];
- u8 addrbuf[2];
- int status;
-
- at24_client = at24_translate_offset(at24, &offset);
- client = at24_client->client;
-
- memset(msg, 0, sizeof(msg));
- msg[0].addr = client->addr;
- msg[0].buf = addrbuf;
- /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
- addrbuf[0] = 0xa0 - at24->chip.byte_len + offset;
- msg[0].len = 1;
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_transfer(client->adapter, msg, 2);
- if (status == 2)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
/*
* Note that if the hardware write-protect pin is pulled high, the whole
* chip is normally write protected. But there are plenty of product
@@ -805,7 +629,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -ENOMEM;
mutex_init(&at24->lock);
- at24->use_smbus = use_smbus;
at24->chip = chip;
at24->num_addresses = num_addresses;
at24->offset_adj = at24_get_offset_adj(chip.flags, chip.byte_len);
@@ -821,15 +644,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -EINVAL;
}
- if (chip.flags & AT24_FLAG_SERIAL) {
- at24->read_func = at24_eeprom_read_serial;
- } else if (chip.flags & AT24_FLAG_MAC) {
- at24->read_func = at24_eeprom_read_mac;
- } else {
- at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
- : at24_eeprom_read_i2c;
- }
-
writable = !(chip.flags & AT24_FLAG_READONLY);
if (writable) {
if (!use_smbus || use_smbus_write) {
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v6 7/7] eeprom: at24: remove now unneeded smbus-related code
2017-11-28 20:40 [PATCH v6 0/7] eeprom: at24: switch driver to regmap_i2c Heiner Kallweit
` (5 preceding siblings ...)
2017-11-28 20:51 ` [PATCH v6 6/7] eeprom: at24: remove old read functions Heiner Kallweit
@ 2017-11-28 20:51 ` Heiner Kallweit
6 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-11-28 20:51 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-i2c@vger.kernel.org
Remove remaining now unneeded code dealing with SMBUS details.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- rebased
v4:
- rebased
v5:
- rebased
v6:
- re-introduce check for I2C_SMBUS_BLOCK_MAX
---
drivers/misc/eeprom/at24.c | 56 +++++++---------------------------------------
1 file changed, 8 insertions(+), 48 deletions(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index ad43f4ca1..cd87f1b21 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -521,8 +521,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct at24_platform_data chip;
kernel_ulong_t magic = 0;
bool writable;
- int use_smbus = 0;
- int use_smbus_write = 0;
struct at24_data *at24;
int err;
unsigned i, num_addresses;
@@ -584,33 +582,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4)
chip.byte_len = 6;
- /* Use I2C operations unless we're stuck with SMBus extensions. */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- if (chip.flags & AT24_FLAG_ADDR16)
- return -EPFNOSUPPORT;
-
- if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- use_smbus = I2C_SMBUS_I2C_BLOCK_DATA;
- } else if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_WORD_DATA)) {
- use_smbus = I2C_SMBUS_WORD_DATA;
- } else if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
- use_smbus = I2C_SMBUS_BYTE_DATA;
- } else {
- return -EPFNOSUPPORT;
- }
-
- if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
- use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA;
- } else if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
- use_smbus_write = I2C_SMBUS_BYTE_DATA;
- chip.page_size = 1;
- }
- }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) &&
+ !i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
+ chip.page_size = 1;
if (chip.flags & AT24_FLAG_TAKE8ADDR)
num_addresses = 8;
@@ -646,19 +621,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
writable = !(chip.flags & AT24_FLAG_READONLY);
if (writable) {
- if (!use_smbus || use_smbus_write) {
-
- unsigned write_max = chip.page_size;
-
- if (write_max > io_limit)
- write_max = io_limit;
- if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
- write_max = I2C_SMBUS_BLOCK_MAX;
- at24->write_max = write_max;
- } else {
- dev_warn(&client->dev,
- "cannot write due to controller restrictions.");
- }
+ at24->write_max = min_t(unsigned int, chip.page_size, io_limit);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) &&
+ at24->write_max > I2C_SMBUS_BLOCK_MAX)
+ at24->write_max = I2C_SMBUS_BLOCK_MAX;
}
/* use dummy devices for multiple-address chips */
@@ -720,12 +686,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
chip.byte_len, client->name,
writable ? "writable" : "read-only", at24->write_max);
- if (use_smbus == I2C_SMBUS_WORD_DATA ||
- use_smbus == I2C_SMBUS_BYTE_DATA) {
- dev_notice(&client->dev, "Falling back to %s reads, "
- "performance will suffer\n", use_smbus ==
- I2C_SMBUS_WORD_DATA ? "word" : "byte");
- }
/* export data to kernel code */
if (chip.setup)
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread