Skip to content

Commit a069fcd

Browse files
larsclausenwsakernel
authored andcommitted
i2c: cadence: Allow to specify the FIFO depth
The FIFO depth is a synthesis configuration parameters of the Cadence I2C IP. Different SoCs might use different values for these parameters. Currently the driver has the FIFO depth hardcoded to 16. Trying to use the driver with an IP instance that uses smaller values for these will work for short transfers. But longer transfers will fail. Introduce a new devicetree property that allows to describe the FIFO depth of the I2C controller. These changes have been tested with 1) The Xilinx MPSoC for which this driver was originally written which has the previous hardcoded settings of 16 and 255. 2) Another instance of the Cadence I2C IP with FIFO depth of 8 and maximum transfer length of 16. Without these changes the latter would fail for I2C transfers longer than 8. With the updated driver both work fine even for longer transfers. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Michal Simek <michal.simek@amd.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent 6ff0ddb commit a069fcd

1 file changed

Lines changed: 17 additions & 12 deletions

File tree

drivers/i2c/busses/i2c-cadence.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
/* timeout for pm runtime autosuspend */
115115
#define CNDS_I2C_PM_TIMEOUT 1000 /* ms */
116116

117-
#define CDNS_I2C_FIFO_DEPTH 16
117+
#define CDNS_I2C_FIFO_DEPTH_DEFAULT 16
118118
#define CDNS_I2C_MAX_TRANSFER_SIZE 255
119119
/* Transfer size in multiples of data interrupt depth */
120120
#define CDNS_I2C_TRANSFER_SIZE (CDNS_I2C_MAX_TRANSFER_SIZE - 3)
@@ -184,6 +184,7 @@ enum cdns_i2c_slave_state {
184184
* @slave: Registered slave instance.
185185
* @dev_mode: I2C operating role(master/slave).
186186
* @slave_state: I2C Slave state(idle/read/write).
187+
* @fifo_depth: The depth of the transfer FIFO
187188
*/
188189
struct cdns_i2c {
189190
struct device *dev;
@@ -211,6 +212,7 @@ struct cdns_i2c {
211212
enum cdns_i2c_mode dev_mode;
212213
enum cdns_i2c_slave_state slave_state;
213214
#endif
215+
u32 fifo_depth;
214216
};
215217

216218
struct cdns_platform_data {
@@ -236,7 +238,7 @@ static void cdns_i2c_clear_bus_hold(struct cdns_i2c *id)
236238
static inline bool cdns_is_holdquirk(struct cdns_i2c *id, bool hold_wrkaround)
237239
{
238240
return (hold_wrkaround &&
239-
(id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1));
241+
(id->curr_recv_count == id->fifo_depth + 1));
240242
}
241243

242244
#if IS_ENABLED(CONFIG_I2C_SLAVE)
@@ -431,7 +433,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
431433
* if RX data left is less than or equal to
432434
* FIFO DEPTH unless repeated start is selected
433435
*/
434-
if (id->recv_count <= CDNS_I2C_FIFO_DEPTH &&
436+
if (id->recv_count <= id->fifo_depth &&
435437
!id->bus_hold_flag)
436438
cdns_i2c_clear_bus_hold(id);
437439

@@ -456,22 +458,22 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
456458
if (cdns_is_holdquirk(id, updatetx)) {
457459
/* wait while fifo is full */
458460
while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) !=
459-
(id->curr_recv_count - CDNS_I2C_FIFO_DEPTH))
461+
(id->curr_recv_count - id->fifo_depth))
460462
;
461463

462464
/*
463465
* Check number of bytes to be received against maximum
464466
* transfer size and update register accordingly.
465467
*/
466-
if (((int)(id->recv_count) - CDNS_I2C_FIFO_DEPTH) >
468+
if (((int)(id->recv_count) - id->fifo_depth) >
467469
CDNS_I2C_TRANSFER_SIZE) {
468470
cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE,
469471
CDNS_I2C_XFER_SIZE_OFFSET);
470472
id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE +
471-
CDNS_I2C_FIFO_DEPTH;
473+
id->fifo_depth;
472474
} else {
473475
cdns_i2c_writereg(id->recv_count -
474-
CDNS_I2C_FIFO_DEPTH,
476+
id->fifo_depth,
475477
CDNS_I2C_XFER_SIZE_OFFSET);
476478
id->curr_recv_count = id->recv_count;
477479
}
@@ -494,7 +496,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)
494496
* space available in FIFO and fill with that many bytes.
495497
*/
496498
if (id->send_count) {
497-
avail_bytes = CDNS_I2C_FIFO_DEPTH -
499+
avail_bytes = id->fifo_depth -
498500
cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
499501
if (id->send_count > avail_bytes)
500502
bytes_to_send = avail_bytes;
@@ -588,7 +590,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
588590
* Check for the message size against FIFO depth and set the
589591
* 'hold bus' bit if it is greater than FIFO depth.
590592
*/
591-
if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
593+
if (id->recv_count > id->fifo_depth)
592594
ctrl_reg |= CDNS_I2C_CR_HOLD;
593595

594596
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
@@ -612,7 +614,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
612614
}
613615

614616
/* Determine hold_clear based on number of bytes to receive and hold flag */
615-
if (!id->bus_hold_flag && id->recv_count <= CDNS_I2C_FIFO_DEPTH) {
617+
if (!id->bus_hold_flag && id->recv_count <= id->fifo_depth) {
616618
if (ctrl_reg & CDNS_I2C_CR_HOLD) {
617619
hold_clear = true;
618620
if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT)
@@ -673,7 +675,7 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
673675
* Check for the message size against FIFO depth and set the
674676
* 'hold bus' bit if it is greater than FIFO depth.
675677
*/
676-
if (id->send_count > CDNS_I2C_FIFO_DEPTH)
678+
if (id->send_count > id->fifo_depth)
677679
ctrl_reg |= CDNS_I2C_CR_HOLD;
678680
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
679681

@@ -686,7 +688,7 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
686688
* against the space available, and fill the FIFO accordingly.
687689
* Enable the interrupts.
688690
*/
689-
avail_bytes = CDNS_I2C_FIFO_DEPTH -
691+
avail_bytes = id->fifo_depth -
690692
cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
691693

692694
if (id->send_count > avail_bytes)
@@ -1316,6 +1318,9 @@ static int cdns_i2c_probe(struct platform_device *pdev)
13161318
#endif
13171319
id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS;
13181320

1321+
id->fifo_depth = CDNS_I2C_FIFO_DEPTH_DEFAULT;
1322+
of_property_read_u32(pdev->dev.of_node, "fifo-depth", &id->fifo_depth);
1323+
13191324
ret = cdns_i2c_setclk(id->input_clk, id);
13201325
if (ret) {
13211326
dev_err(&pdev->dev, "invalid SCL clock: %u Hz\n", id->i2c_clk);

0 commit comments

Comments
 (0)