Skip to content

Commit d3c2191

Browse files
0xharshalAndi Shyti
authored andcommitted
i2c: rtl9300: Implement I2C block read and write
It was noticed that the original implementation of SMBus Block Write in the driver was actually an I2C Block Write. Both differ only in the Count byte before the actual data: S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P The I2C Block Write is just skipping this Count byte and starts directly with the data: S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P The I2C controller of RTL93xx doesn't handle this Count byte special and it is simply another one of (16 possible) data bytes. Adding support for the I2C Block Write therefore only requires skipping the count byte (0) in data->block. It is similar for reads. The SMBUS Block read is having a Count byte before the data: S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P And the I2C Block Read is directly starting with the actual data: S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Data] A [Data] A ... A [Data] NA P The I2C controller is also not handling this byte in a special way. It simply provides every byte after the Rd marker + Ack as part of the 16 byte receive buffer (registers). The content of this buffer just has to be copied to the right position in the receive data->block. Signed-off-by: Harshal Gohel <hg@simonwunderlich.de> Co-developed-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Sven Eckelmann <sven@narfation.org> Reviewed-by: Chris Packham <chris.packham@alliedtelesis.co.nz> Tested-by: Chris Packham <chris.packham@alliedtelesis.co.nz> Reviewed-by: Jonas Jelonek <jelonek.jonas@gmail.com> Tested-by: Jonas Jelonek <jelonek.jonas@gmail.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org> Link: https://lore.kernel.org/all/20250927-i2c-rtl9300-multi-byte-v7-2-c0fd0e78b818@narfation.org
1 parent cf8da11 commit d3c2191

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

drivers/i2c/busses/i2c-rtl9300.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,22 +186,32 @@ static int rtl9300_i2c_execute_xfer(struct rtl9300_i2c *i2c, char read_write,
186186
return -EIO;
187187

188188
if (read_write == I2C_SMBUS_READ) {
189-
if (size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA) {
189+
switch (size) {
190+
case I2C_SMBUS_BYTE:
191+
case I2C_SMBUS_BYTE_DATA:
190192
ret = regmap_read(i2c->regmap,
191193
i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val);
192194
if (ret)
193195
return ret;
194196
data->byte = val & 0xff;
195-
} else if (size == I2C_SMBUS_WORD_DATA) {
197+
break;
198+
case I2C_SMBUS_WORD_DATA:
196199
ret = regmap_read(i2c->regmap,
197200
i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val);
198201
if (ret)
199202
return ret;
200203
data->word = val & 0xffff;
201-
} else {
204+
break;
205+
case I2C_SMBUS_I2C_BLOCK_DATA:
206+
ret = rtl9300_i2c_read(i2c, &data->block[1], len);
207+
if (ret)
208+
return ret;
209+
break;
210+
default:
202211
ret = rtl9300_i2c_read(i2c, &data->block[0], len);
203212
if (ret)
204213
return ret;
214+
break;
205215
}
206216
}
207217

@@ -290,6 +300,25 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s
290300
len = data->block[0] + 1;
291301
break;
292302

303+
case I2C_SMBUS_I2C_BLOCK_DATA:
304+
ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
305+
if (ret)
306+
goto out_unlock;
307+
if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) {
308+
ret = -EINVAL;
309+
goto out_unlock;
310+
}
311+
ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]);
312+
if (ret)
313+
goto out_unlock;
314+
if (read_write == I2C_SMBUS_WRITE) {
315+
ret = rtl9300_i2c_write(i2c, &data->block[1], data->block[0]);
316+
if (ret)
317+
goto out_unlock;
318+
}
319+
len = data->block[0];
320+
break;
321+
293322
default:
294323
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
295324
ret = -EOPNOTSUPP;
@@ -307,7 +336,8 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s
307336
static u32 rtl9300_i2c_func(struct i2c_adapter *a)
308337
{
309338
return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
310-
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA;
339+
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
340+
I2C_FUNC_SMBUS_I2C_BLOCK;
311341
}
312342

313343
static const struct i2c_algorithm rtl9300_i2c_algo = {

0 commit comments

Comments
 (0)