Commit 93ade343 authored by Luben Tuikov's avatar Luben Tuikov Committed by Alex Deucher
Browse files

drm/amdgpu: EEPROM respects I2C quirks



Consult the i2c_adapter.quirks table for
the maximum read/write data length per bus
transaction. Do not exceed this transaction
limit.

Cc: Jean Delvare <jdelvare@suse.de>
Cc: Alexander Deucher <Alexander.Deucher@amd.com>
Cc: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Cc: Lijo Lazar <Lijo.Lazar@amd.com>
Cc: Stanley Yang <Stanley.Yang@amd.com>
Cc: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarLuben Tuikov <luben.tuikov@amd.com>
Acked-by: default avatarAlexander Deucher <Alexander.Deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 746b5847
Loading
Loading
Loading
Loading
+64 −16
Original line number Diff line number Diff line
@@ -32,18 +32,7 @@

#define EEPROM_OFFSET_SIZE 2

/**
 * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
 * @i2c_adap: pointer to the I2C adapter to use
 * @slave_addr: I2C address of the slave device
 * @eeprom_addr: EEPROM address from which to read/write
 * @eeprom_buf: pointer to data buffer to read into/write from
 * @buf_size: the size of @eeprom_buf
 * @read: True if reading from the EEPROM, false if writing
 *
 * Returns the number of bytes read/written; -errno on error.
 */
int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
				u16 slave_addr, u16 eeprom_addr,
				u8 *eeprom_buf, u16 buf_size, bool read)
{
@@ -65,7 +54,7 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
	u16 len;

	r = 0;
	for (len = 0; buf_size > 0;
	for ( ; buf_size > 0;
	      buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
		/* Set the EEPROM address we want to write to/read from.
		 */
@@ -120,3 +109,62 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,

	return r < 0 ? r : eeprom_buf - p;
}

/**
 * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
 * @i2c_adap: pointer to the I2C adapter to use
 * @slave_addr: I2C address of the slave device
 * @eeprom_addr: EEPROM address from which to read/write
 * @eeprom_buf: pointer to data buffer to read into/write from
 * @buf_size: the size of @eeprom_buf
 * @read: True if reading from the EEPROM, false if writing
 *
 * Returns the number of bytes read/written; -errno on error.
 */
int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
		       u16 slave_addr, u16 eeprom_addr,
		       u8 *eeprom_buf, u16 buf_size, bool read)
{
	const struct i2c_adapter_quirks *quirks = i2c_adap->quirks;
	u16 limit;

	if (!quirks)
		limit = 0;
	else if (read)
		limit = quirks->max_read_len;
	else
		limit = quirks->max_write_len;

	if (limit == 0) {
		return __amdgpu_eeprom_xfer(i2c_adap, slave_addr, eeprom_addr,
					    eeprom_buf, buf_size, read);
	} else if (limit <= EEPROM_OFFSET_SIZE) {
		dev_err_ratelimited(&i2c_adap->dev,
				    "maddr:0x%04X size:0x%02X:quirk max_%s_len must be > %d",
				    eeprom_addr, buf_size,
				    read ? "read" : "write", EEPROM_OFFSET_SIZE);
		return -EINVAL;
	} else {
		u16 ps; /* Partial size */
		int res = 0, r;

		/* The "limit" includes all data bytes sent/received,
		 * which would include the EEPROM_OFFSET_SIZE bytes.
		 * Account for them here.
		 */
		limit -= EEPROM_OFFSET_SIZE;
		for ( ; buf_size > 0;
		      buf_size -= ps, eeprom_addr += ps, eeprom_buf += ps) {
			ps = min(limit, buf_size);

			r = __amdgpu_eeprom_xfer(i2c_adap,
						 slave_addr, eeprom_addr,
						 eeprom_buf, ps, read);
			if (r < 0)
				return r;
			res += r;
		}

		return res;
	}
}