mirror of
https://github.com/torvalds/linux.git
synced 2024-12-12 14:12:51 +00:00
eeprom: at24: split at24_eeprom_write() into specialized functions
Split at24_eeprom_write() into three smaller functions - one for the i2c operations and two for the smbus extensions (separate routines for block and byte transfers). Assign them in at24_probe() depending on the bus capabilities. Also: in order to avoid duplications move code adjusting the count argument into a separate function and use it for i2c and smbus block writes (no need for a roll-over for byte writes as we're always writing one byte). Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
9afd6866bf
commit
cd0c861542
@ -281,21 +281,15 @@ static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
|
||||
* chip is normally write protected. But there are plenty of product
|
||||
* variants here, including OTP fuses and partial chip protect.
|
||||
*
|
||||
* We only use page mode writes; the alternative is sloooow. This routine
|
||||
* writes at most one page.
|
||||
* We only use page mode writes; the alternative is sloooow. These routines
|
||||
* write at most one page.
|
||||
*/
|
||||
static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
|
||||
|
||||
static size_t at24_adjust_write_count(struct at24_data *at24,
|
||||
unsigned int offset, size_t count)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct i2c_msg msg;
|
||||
ssize_t status = 0;
|
||||
unsigned long timeout, write_time;
|
||||
unsigned next_page;
|
||||
|
||||
/* Get corresponding I2C address and adjust offset */
|
||||
client = at24_translate_offset(at24, &offset);
|
||||
|
||||
/* write_max is at most a page */
|
||||
if (count > at24->write_max)
|
||||
count = at24->write_max;
|
||||
@ -305,10 +299,73 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
|
||||
if (offset + count > next_page)
|
||||
count = next_page - offset;
|
||||
|
||||
/* If we'll use I2C calls for I/O, set up the message */
|
||||
if (!at24->use_smbus) {
|
||||
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 i2c_client *client;
|
||||
ssize_t status = 0;
|
||||
|
||||
client = at24_translate_offset(at24, &offset);
|
||||
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 i2c_client *client;
|
||||
ssize_t status = 0;
|
||||
|
||||
client = at24_translate_offset(at24, &offset);
|
||||
|
||||
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_eeprom_write_i2c(struct at24_data *at24, const char *buf,
|
||||
unsigned int offset, size_t count)
|
||||
{
|
||||
unsigned long timeout, write_time;
|
||||
struct i2c_client *client;
|
||||
struct i2c_msg msg;
|
||||
ssize_t status = 0;
|
||||
int i = 0;
|
||||
|
||||
client = at24_translate_offset(at24, &offset);
|
||||
count = at24_adjust_write_count(at24, offset, count);
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = 0;
|
||||
|
||||
@ -320,28 +377,12 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
|
||||
msg.buf[i++] = offset;
|
||||
memcpy(&msg.buf[i], buf, count);
|
||||
msg.len = i + count;
|
||||
}
|
||||
|
||||
loop_until_timeout(timeout, write_time) {
|
||||
if (at24->use_smbus_write) {
|
||||
switch (at24->use_smbus_write) {
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
status = i2c_smbus_write_i2c_block_data(client,
|
||||
offset, count, buf);
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
status = i2c_smbus_write_byte_data(client,
|
||||
offset, buf[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
status = count;
|
||||
} else {
|
||||
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);
|
||||
|
||||
@ -538,7 +579,14 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
|
||||
at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
|
||||
: at24_eeprom_read_i2c;
|
||||
at24->write_func = at24_eeprom_write;
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user