From: Guenter Roeck <linux@roeck-us.net> To: Wolfram Sang <wsa@the-dreams.de> Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, Guenter Roeck <linux@roeck-us.net> Subject: [PATCH] eeprom: at24: Add support for large EEPROMs connected to SMBus adapters Date: Wed, 4 Feb 2015 08:23:37 -0800 [thread overview] Message-ID: <1423067017-27607-1-git-send-email-linux@roeck-us.net> (raw) Large EEPROMS (24c32 and larger) require a two-byte data address instead of just a single byte. Implement support for such EEPROMs with SMBus commands. Support has limitations (reads are not multi-master safe) and is slow, but it works. Practical use is for a system with 24c32 connected to Intel 82801I (ICH9). Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/misc/eeprom/at24.c | 52 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2d3db81..057d35c 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -198,6 +198,8 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, case I2C_SMBUS_BYTE_DATA: count = 1; break; + case I2C_SMBUS_BYTE: + break; default: /* * When we have a better choice than SMBus calls, use a @@ -249,6 +251,27 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, status = count; } break; + case I2C_SMBUS_BYTE: + /* + * 16-bit data address. Write data address as separate + * write operation, then read data without setting + * the address again. This is not multi-master safe, + * but the best we can do. + */ + status = i2c_smbus_write_byte_data(client, + offset >> 8, + offset & 0xff); + if (status < 0) + break; + for (i = 0; i < count; i++) { + status = i2c_smbus_read_byte(client); + if (status < 0) + break; + buf[i] = status; + } + if (status >= 0) + status = count; + break; default: status = i2c_transfer(client->adapter, msg, 2); if (status == 2) @@ -372,6 +395,16 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, status = i2c_smbus_write_i2c_block_data(client, offset, count, buf); break; + case I2C_SMBUS_WORD_DATA: + /* + * 16-bit data address. Transmit data address + * MSB as SMBus command, data address LSB as + * first data byte. + */ + status = i2c_smbus_write_word_data(client, + offset >> 8, + (offset & 0xff) | (buf[0] << 8)); + break; case I2C_SMBUS_BYTE_DATA: status = i2c_smbus_write_byte_data(client, offset, buf[0]); @@ -540,10 +573,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) /* 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, + if (chip.flags & AT24_FLAG_ADDR16) { + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA | + I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + use_smbus = I2C_SMBUS_BYTE; + } else 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, @@ -559,7 +595,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Use I2C operations unless we're stuck with SMBus extensions. */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, + if (chip.flags & AT24_FLAG_ADDR16) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA)) { + use_smbus_write = I2C_SMBUS_WORD_DATA; + chip.page_size = 1; + } + } else 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, -- 2.1.0
WARNING: multiple messages have this Message-ID (diff)
From: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> To: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> Subject: [PATCH] eeprom: at24: Add support for large EEPROMs connected to SMBus adapters Date: Wed, 4 Feb 2015 08:23:37 -0800 [thread overview] Message-ID: <1423067017-27607-1-git-send-email-linux@roeck-us.net> (raw) Large EEPROMS (24c32 and larger) require a two-byte data address instead of just a single byte. Implement support for such EEPROMs with SMBus commands. Support has limitations (reads are not multi-master safe) and is slow, but it works. Practical use is for a system with 24c32 connected to Intel 82801I (ICH9). Signed-off-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> --- drivers/misc/eeprom/at24.c | 52 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2d3db81..057d35c 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -198,6 +198,8 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, case I2C_SMBUS_BYTE_DATA: count = 1; break; + case I2C_SMBUS_BYTE: + break; default: /* * When we have a better choice than SMBus calls, use a @@ -249,6 +251,27 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, status = count; } break; + case I2C_SMBUS_BYTE: + /* + * 16-bit data address. Write data address as separate + * write operation, then read data without setting + * the address again. This is not multi-master safe, + * but the best we can do. + */ + status = i2c_smbus_write_byte_data(client, + offset >> 8, + offset & 0xff); + if (status < 0) + break; + for (i = 0; i < count; i++) { + status = i2c_smbus_read_byte(client); + if (status < 0) + break; + buf[i] = status; + } + if (status >= 0) + status = count; + break; default: status = i2c_transfer(client->adapter, msg, 2); if (status == 2) @@ -372,6 +395,16 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, status = i2c_smbus_write_i2c_block_data(client, offset, count, buf); break; + case I2C_SMBUS_WORD_DATA: + /* + * 16-bit data address. Transmit data address + * MSB as SMBus command, data address LSB as + * first data byte. + */ + status = i2c_smbus_write_word_data(client, + offset >> 8, + (offset & 0xff) | (buf[0] << 8)); + break; case I2C_SMBUS_BYTE_DATA: status = i2c_smbus_write_byte_data(client, offset, buf[0]); @@ -540,10 +573,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) /* 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, + if (chip.flags & AT24_FLAG_ADDR16) { + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA | + I2C_FUNC_SMBUS_READ_BYTE)) + return -EPFNOSUPPORT; + use_smbus = I2C_SMBUS_BYTE; + } else 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, @@ -559,7 +595,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Use I2C operations unless we're stuck with SMBus extensions. */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, + if (chip.flags & AT24_FLAG_ADDR16) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA)) { + use_smbus_write = I2C_SMBUS_WORD_DATA; + chip.page_size = 1; + } + } else 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, -- 2.1.0
next reply other threads:[~2015-02-04 16:23 UTC|newest] Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-02-04 16:23 Guenter Roeck [this message] 2015-02-04 16:23 ` [PATCH] eeprom: at24: Add support for large EEPROMs connected to SMBus adapters Guenter Roeck 2015-02-04 17:47 ` Wolfram Sang 2015-02-04 19:08 ` Guenter Roeck 2015-02-04 19:08 ` Guenter Roeck 2015-02-04 23:35 ` Wolfram Sang 2015-02-05 0:26 ` Guenter Roeck 2015-02-05 0:26 ` Guenter Roeck 2015-02-05 14:40 ` Wolfram Sang 2015-02-05 17:53 ` Guenter Roeck 2015-02-12 4:01 ` Guenter Roeck 2015-02-12 4:01 ` Guenter Roeck 2015-02-16 12:09 ` Wolfram Sang 2015-02-16 15:37 ` Guenter Roeck 2015-03-17 4:20 ` Guenter Roeck 2015-03-17 4:20 ` Guenter Roeck 2015-03-18 13:27 ` Wolfram Sang 2015-03-19 3:24 ` Guenter Roeck 2015-03-19 8:16 ` Wolfram Sang 2015-03-19 8:16 ` Wolfram Sang 2015-03-19 13:30 ` Guenter Roeck 2015-03-19 13:30 ` Guenter Roeck 2015-03-19 17:43 ` Guenter Roeck 2015-03-19 17:43 ` Guenter Roeck 2015-03-19 21:39 ` Wolfram Sang 2015-03-25 14:11 ` Guenter Roeck 2015-03-25 16:15 ` Wolfram Sang 2015-03-25 16:15 ` Wolfram Sang 2015-03-25 16:37 ` Guenter Roeck 2015-03-25 16:37 ` Guenter Roeck 2015-03-27 8:09 ` Wolfram Sang 2015-03-27 12:51 ` Guenter Roeck 2015-03-27 13:01 ` Wolfram Sang 2015-03-27 13:14 ` Guenter Roeck 2015-03-27 15:27 ` Wolfram Sang 2015-03-27 15:42 ` Guenter Roeck 2015-03-27 15:42 ` Guenter Roeck 2015-02-04 20:33 ` Guenter Roeck
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1423067017-27607-1-git-send-email-linux@roeck-us.net \ --to=linux@roeck-us.net \ --cc=linux-i2c@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=wsa@the-dreams.de \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.