Skip to content

Commit 4ca8ca8

Browse files
robhancocksedwsakernel
authored andcommitted
i2c: cadence: Change large transfer count reset logic to be unconditional
Problems were observed on the Xilinx ZynqMP platform with large I2C reads. When a read of 277 bytes was performed, the controller NAKed the transfer after only 252 bytes were transferred and returned an ENXIO error on the transfer. There is some code in cdns_i2c_master_isr to handle this case by resetting the transfer count in the controller before it reaches 0, to allow larger transfers to work, but it was conditional on the CDNS_I2C_BROKEN_HOLD_BIT quirk being set on the controller, and ZynqMP uses the r1p14 version of the core where this quirk is not being set. The requirement to do this to support larger reads seems like an inherently required workaround due to the core only having an 8-bit transfer size register, so it does not appear that this should be conditional on the broken HOLD bit quirk which is used elsewhere in the driver. Remove the dependency on the CDNS_I2C_BROKEN_HOLD_BIT for this transfer size reset logic to fix this problem. Fixes: 63cab19 ("i2c: removed work arounds in i2c driver for Zynq Ultrascale+ MPSoC") Signed-off-by: Robert Hancock <robert.hancock@calian.com> Reviewed-by: Shubhrajyoti Datta <Shubhrajyoti.datta@amd.com> Acked-by: Michal Simek <michal.simek@amd.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent 824a826 commit 4ca8ca8

File tree

1 file changed

+5
-25
lines changed

1 file changed

+5
-25
lines changed

drivers/i2c/busses/i2c-cadence.c

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,9 @@ static irqreturn_t cdns_i2c_slave_isr(void *ptr)
388388
*/
389389
static irqreturn_t cdns_i2c_master_isr(void *ptr)
390390
{
391-
unsigned int isr_status, avail_bytes, updatetx;
391+
unsigned int isr_status, avail_bytes;
392392
unsigned int bytes_to_send;
393-
bool hold_quirk;
393+
bool updatetx;
394394
struct cdns_i2c *id = ptr;
395395
/* Signal completion only after everything is updated */
396396
int done_flag = 0;
@@ -410,11 +410,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
410410
* Check if transfer size register needs to be updated again for a
411411
* large data receive operation.
412412
*/
413-
updatetx = 0;
414-
if (id->recv_count > id->curr_recv_count)
415-
updatetx = 1;
416-
417-
hold_quirk = (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx;
413+
updatetx = id->recv_count > id->curr_recv_count;
418414

419415
/* When receiving, handle data interrupt and completion interrupt */
420416
if (id->p_recv_buf &&
@@ -445,7 +441,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
445441
break;
446442
}
447443

448-
if (cdns_is_holdquirk(id, hold_quirk))
444+
if (cdns_is_holdquirk(id, updatetx))
449445
break;
450446
}
451447

@@ -456,7 +452,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
456452
* maintain transfer size non-zero while performing a large
457453
* receive operation.
458454
*/
459-
if (cdns_is_holdquirk(id, hold_quirk)) {
455+
if (cdns_is_holdquirk(id, updatetx)) {
460456
/* wait while fifo is full */
461457
while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) !=
462458
(id->curr_recv_count - CDNS_I2C_FIFO_DEPTH))
@@ -478,22 +474,6 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
478474
CDNS_I2C_XFER_SIZE_OFFSET);
479475
id->curr_recv_count = id->recv_count;
480476
}
481-
} else if (id->recv_count && !hold_quirk &&
482-
!id->curr_recv_count) {
483-
484-
/* Set the slave address in address register*/
485-
cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK,
486-
CDNS_I2C_ADDR_OFFSET);
487-
488-
if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) {
489-
cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE,
490-
CDNS_I2C_XFER_SIZE_OFFSET);
491-
id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE;
492-
} else {
493-
cdns_i2c_writereg(id->recv_count,
494-
CDNS_I2C_XFER_SIZE_OFFSET);
495-
id->curr_recv_count = id->recv_count;
496-
}
497477
}
498478

499479
/* Clear hold (if not repeated start) and signal completion */

0 commit comments

Comments
 (0)