Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9afd6866 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Wolfram Sang
Browse files

eeprom: at24: split at24_eeprom_read() into specialized functions



Split at24_eeprom_read() into two smaller functions - one for the
i2c operations and one for the smbus extensions. Assign them in
at24_probe() depending on the bus capabilities.

Also: in order to avoid duplications move the comments related to
offset calculations above the at24_translate_offset() routine.

Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 9344a81e
Loading
Loading
Loading
Loading
+71 −54
Original line number Original line Diff line number Diff line
@@ -165,6 +165,19 @@ MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
 * This routine supports chips which consume multiple I2C addresses. It
 * This routine supports chips which consume multiple I2C addresses. It
 * computes the addressing information to be used for a given r/w request.
 * computes the addressing information to be used for a given r/w request.
 * Assumes that sanity checks for offset happened at sysfs-layer.
 * Assumes that sanity checks for offset happened at sysfs-layer.
 *
 * Slave address and byte offset derive from the offset. Always
 * set the byte address; on a multi-master board, another master
 * may have changed the chip's "current" address pointer.
 *
 * REVISIT some multi-address chips don't rollover page reads to
 * the next slave address, so we may need to truncate the count.
 * Those chips might need another quirk flag.
 *
 * If the real hardware used four adjacent 24c02 chips and that
 * were misconfigured as one 24c08, that would be a similar effect:
 * 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,
static struct i2c_client *at24_translate_offset(struct at24_data *at24,
						unsigned int *offset)
						unsigned int *offset)
@@ -182,49 +195,57 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
	return at24->client[i];
	return at24->client[i];
}
}


static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
				      unsigned int offset, size_t count)
				      unsigned int offset, size_t count)
{
{
	struct i2c_msg msg[2];
	u8 msgbuf[2];
	struct i2c_client *client;
	unsigned long timeout, read_time;
	unsigned long timeout, read_time;
	int status, i;
	struct i2c_client *client;

	int status;
	memset(msg, 0, sizeof(msg));

	/*
	 * REVISIT some multi-address chips don't rollover page reads to
	 * the next slave address, so we may need to truncate the count.
	 * Those chips might need another quirk flag.
	 *
	 * If the real hardware used four adjacent 24c02 chips and that
	 * were misconfigured as one 24c08, that would be a similar effect:
	 * one "eeprom" file not four, but larger reads would fail when
	 * they crossed certain pages.
	 */


	/*
	 * Slave address and byte offset derive from the offset. Always
	 * set the byte address; on a multi-master board, another master
	 * may have changed the chip's "current" address pointer.
	 */
	client = at24_translate_offset(at24, &offset);
	client = at24_translate_offset(at24, &offset);


	if (count > io_limit)
	if (count > io_limit)
		count = io_limit;
		count = io_limit;


	if (at24->use_smbus) {
	/* Smaller eeproms can work given some SMBus extension calls */
	/* Smaller eeproms can work given some SMBus extension calls */
	if (count > I2C_SMBUS_BLOCK_MAX)
	if (count > I2C_SMBUS_BLOCK_MAX)
		count = I2C_SMBUS_BLOCK_MAX;
		count = I2C_SMBUS_BLOCK_MAX;
	} else {

	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_eeprom_read_i2c(struct at24_data *at24, char *buf,
				    unsigned int offset, size_t count)
{
	unsigned long timeout, read_time;
	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);

	if (count > io_limit)
		count = io_limit;

	/*
	/*
		 * When we have a better choice than SMBus calls, use a
	 * When we have a better choice than SMBus calls, use a combined I2C
		 * combined I2C message. Write address; then read up to
	 * message. Write address; then read up to io_limit data bytes. Note
		 * io_limit data bytes. Note that read page rollover helps us
	 * that read page rollover helps us here (unlike writes). msgbuf is
		 * here (unlike writes). msgbuf is u8 and will cast to our
	 * u8 and will cast to our needs.
		 * needs.
	 */
	 */
	i = 0;
	i = 0;
	if (at24->chip.flags & AT24_FLAG_ADDR16)
	if (at24->chip.flags & AT24_FLAG_ADDR16)
@@ -239,17 +260,12 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
	msg[1].flags = I2C_M_RD;
	msg[1].flags = I2C_M_RD;
	msg[1].buf = buf;
	msg[1].buf = buf;
	msg[1].len = count;
	msg[1].len = count;
	}


	loop_until_timeout(timeout, read_time) {
	loop_until_timeout(timeout, read_time) {
		if (at24->use_smbus) {
			status = i2c_smbus_read_i2c_block_data_or_emulated(client, offset,
									   count, buf);
		} else {
		status = i2c_transfer(client->adapter, msg, 2);
		status = i2c_transfer(client->adapter, msg, 2);
		if (status == 2)
		if (status == 2)
			status = count;
			status = count;
		}

		dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
		dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
				count, offset, status, jiffies);
				count, offset, status, jiffies);


@@ -520,7 +536,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
	at24->chip = chip;
	at24->chip = chip;
	at24->num_addresses = num_addresses;
	at24->num_addresses = num_addresses;


	at24->read_func = at24_eeprom_read;
	at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
					  : at24_eeprom_read_i2c;
	at24->write_func = at24_eeprom_write;
	at24->write_func = at24_eeprom_write;


	writable = !(chip.flags & AT24_FLAG_READONLY);
	writable = !(chip.flags & AT24_FLAG_READONLY);