Skip to content

Commit ba6bd0d

Browse files
committed
Merge tag 'i2c-fixes-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux
Pull i2c fixes from Andi Shyti: "A handful of small fixes for host controller drivers. One patch also adds Wolfram Sang to CREDITS after more than a decade of work on I2C" * tag 'i2c-fixes-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux: i2c: mediatek: fix WRRD for SoCs without auto_restart option i2c: mlxbf: Fix use-after-free in mlxbf_i2c_init_resource() i2c: spacemit: fix spurious IRQ handling returning IRQ_HANDLED i2c: imx: fix locked bus on SMBus block-read of 0 (IRQ) i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) CREDITS: Add Wolfram Sang
2 parents 1229e2e + deb3533 commit ba6bd0d

5 files changed

Lines changed: 45 additions & 6 deletions

File tree

CREDITS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,13 @@ S: 69 rue Dunois
36263626
S: 75013 Paris
36273627
S: France
36283628

3629+
N: Wolfram Sang
3630+
E: wsa@kernel.org
3631+
W: sang-engineering.com
3632+
P: rsa4096/140DE4CC14A029B6 3991 B1EA B9E2 6751 A4F7 645D 140D E4CC 14A0 29B6
3633+
D: I2C Maintainer 2012 - 2026
3634+
S: Berlin, Germany
3635+
36293636
N: Aleksa Sarai
36303637
E: cyphar@cyphar.com
36313638
W: https://www.cyphar.com/

drivers/i2c/busses/i2c-imx.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,11 +1061,28 @@ static inline enum imx_i2c_state i2c_imx_isr_read_continue(struct imx_i2c_struct
10611061
static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx)
10621062
{
10631063
u8 len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
1064+
unsigned int temp;
10641065

10651066
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
1067+
/*
1068+
* SMBus 3.1 6.5.7: support count byte of 0.
1069+
* I2C_SMBUS_BLOCK_MAX case should not hold the SDA either.
1070+
* So NACK it (TXAK) to not hold the bus.
1071+
*/
1072+
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
1073+
temp |= I2CR_TXAK;
1074+
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
1075+
1076+
if (len == 0) {
1077+
i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = 0;
1078+
i2c_imx->msg->len = 2;
1079+
return;
1080+
}
1081+
10661082
i2c_imx->isr_result = -EPROTO;
10671083
i2c_imx->state = IMX_I2C_STATE_FAILED;
10681084
wake_up(&i2c_imx->queue);
1085+
return;
10691086
}
10701087
i2c_imx->msg->len += len;
10711088
i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = len;
@@ -1415,6 +1432,7 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
14151432
int i, result;
14161433
unsigned int temp;
14171434
int block_data = msgs->flags & I2C_M_RECV_LEN;
1435+
int block_err = 0;
14181436

14191437
result = i2c_imx_prepare_read(i2c_imx, msgs, false);
14201438
if (result)
@@ -1436,8 +1454,20 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
14361454
*/
14371455
if ((!i) && block_data) {
14381456
len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
1439-
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
1440-
return -EPROTO;
1457+
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
1458+
/*
1459+
* SMBus 3.1 6.5.7: support count byte of 0.
1460+
* I2C_SMBUS_BLOCK_MAX case should not hold the SDA either.
1461+
*/
1462+
if (len > I2C_SMBUS_BLOCK_MAX)
1463+
block_err = -EPROTO;
1464+
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
1465+
temp |= I2CR_TXAK;
1466+
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
1467+
msgs->buf[0] = 0;
1468+
msgs->len = 2;
1469+
continue;
1470+
}
14411471
dev_dbg(&i2c_imx->adapter.dev,
14421472
"<%s> read length: 0x%X\n",
14431473
__func__, len);
@@ -1485,7 +1515,7 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
14851515
"<%s> read byte: B%d=0x%X\n",
14861516
__func__, i, msgs->buf[i]);
14871517
}
1488-
return 0;
1518+
return block_err;
14891519
}
14901520

14911521
static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,

drivers/i2c/busses/i2c-k1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
596596

597597
status = readl(i2c->base + SPACEMIT_ISR);
598598
if (!status)
599-
return IRQ_HANDLED;
599+
return IRQ_NONE;
600600

601601
i2c->status = status;
602602

drivers/i2c/busses/i2c-mlxbf.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1051,8 +1051,10 @@ static int mlxbf_i2c_init_resource(struct platform_device *pdev,
10511051

10521052
tmp_res->io = devm_platform_get_and_ioremap_resource(pdev, type, &tmp_res->params);
10531053
if (IS_ERR(tmp_res->io)) {
1054+
int ret = PTR_ERR(tmp_res->io);
1055+
10541056
devm_kfree(dev, tmp_res);
1055-
return PTR_ERR(tmp_res->io);
1057+
return ret;
10561058
}
10571059

10581060
tmp_res->type = type;

drivers/i2c/busses/i2c-mt65xx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
12581258
i2c->auto_restart = i2c->dev_comp->auto_restart;
12591259

12601260
/* checking if we can skip restart and optimize using WRRD mode */
1261-
if (i2c->auto_restart && num == 2) {
1261+
if (num == 2) {
12621262
if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) &&
12631263
msgs[0].addr == msgs[1].addr) {
12641264
i2c->auto_restart = 0;

0 commit comments

Comments
 (0)