Skip to content

Commit 2702ea7

Browse files
zehortigozaWolfram Sang
authored and
Wolfram Sang
committed
i2c: designware: wait for disable/enable only if necessary
If we aren't going to continue using the controller we can just disable it instead of waiting for it to complete. The biggest improvement here is when a I2C transaction is completed and it doesn't block until the adapter is disabled. When a new transfer is needed we will disable and wait for its completion. This way the adapter will continue changing its state in parallel to the execution of the thread that requested the I2C transaction saving most of the time 25~250 usec per I2C transaction. A simple program doing a register read (1 byte write, 1 byte read) alternating on 2 different slaves repeated 25k times for each and measurements taken 4 times we get: perf stat -r4 chrt -f 10 ./i2c-test /dev/i2c-1 25000 0x40 0x6 0x1e 0x00 Before: 30.879317977 seconds time elapsed ( +- 14.83% ) After: 8.638705161 seconds time elapsed ( +- 5.90% ) Signed-off-by: José Roberto de Souza <[email protected]> Signed-off-by: Lucas De Marchi <[email protected]> Acked-by: Jarkko Nikula <[email protected]> Tested-by: Christian Ruppert <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 10f8e7f commit 2702ea7

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

drivers/i2c/busses/i2c-designware-core.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,16 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
256256
}
257257

258258
static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
259+
{
260+
dw_writel(dev, enable, DW_IC_ENABLE);
261+
}
262+
263+
static void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
259264
{
260265
int timeout = 100;
261266

262267
do {
263-
dw_writel(dev, enable, DW_IC_ENABLE);
268+
__i2c_dw_enable(dev, enable);
264269
if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
265270
return;
266271

@@ -328,7 +333,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
328333
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
329334

330335
/* Disable the adapter */
331-
__i2c_dw_enable(dev, false);
336+
__i2c_dw_enable_and_wait(dev, false);
332337

333338
/* set standard and fast speed deviders for high/low periods */
334339

@@ -441,7 +446,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
441446
u32 ic_con, ic_tar = 0;
442447

443448
/* Disable the adapter */
444-
__i2c_dw_enable(dev, false);
449+
__i2c_dw_enable_and_wait(dev, false);
445450

446451
/* if the slave address is ten bit address, enable 10BITADDR */
447452
ic_con = dw_readl(dev, DW_IC_CON);
@@ -860,7 +865,7 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
860865
void i2c_dw_disable(struct dw_i2c_dev *dev)
861866
{
862867
/* Disable controller */
863-
__i2c_dw_enable(dev, false);
868+
__i2c_dw_enable_and_wait(dev, false);
864869

865870
/* Disable all interupts */
866871
dw_writel(dev, 0, DW_IC_INTR_MASK);

0 commit comments

Comments
 (0)