Skip to content

Commit 64b6426

Browse files
jhnikulaAndi Shyti
authored andcommitted
i2c: designware: Do not enable interrupts shortly in polling mode
I was testing the polling mode txgbe_i2c_dw_xfer_quirk() on a HW where the i2c-designware has interrupt connected and shared with other device. I noticed there is a bogus interrupt for each transfer. Reason for this that both polling mode functions call the i2c_dw_xfer_init() which enable interrupts then followed by immediate disable by the same polling mode functions. This is enough to trigger TX_EMPTY interrupt. Fix this by introducing a __i2c_dw_write_intr_mask() helper that unmasks interrupts conditionally and use it in i2c_dw_xfer_init(). Signed-off-by: Jarkko Nikula <[email protected]> Tested-by: Jiawen Wu <[email protected]> Signed-off-by: Andi Shyti <[email protected]>
1 parent 535677e commit 64b6426

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
352352
dev->status &= ~STATUS_ACTIVE;
353353
}
354354

355+
static inline void __i2c_dw_write_intr_mask(struct dw_i2c_dev *dev,
356+
unsigned int intr_mask)
357+
{
358+
unsigned int val = dev->flags & ACCESS_POLLING ? 0 : intr_mask;
359+
360+
regmap_write(dev->map, DW_IC_INTR_MASK, val);
361+
}
362+
355363
void __i2c_dw_disable(struct dw_i2c_dev *dev);
356364

357365
extern void i2c_dw_configure_master(struct dw_i2c_dev *dev);

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
250250

251251
/* Clear and enable interrupts */
252252
regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
253-
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK);
253+
__i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
254254
}
255255

256256
static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
@@ -300,7 +300,6 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
300300
dev->msgs = msgs;
301301
dev->msgs_num = num_msgs;
302302
i2c_dw_xfer_init(dev);
303-
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
304303

305304
/* Initiate messages read/write transaction */
306305
for (msg_wrt_idx = 0; msg_wrt_idx < num_msgs; msg_wrt_idx++) {
@@ -384,7 +383,6 @@ static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msg
384383
dev->msgs = msgs;
385384
dev->msgs_num = num_msgs;
386385
i2c_dw_xfer_init(dev);
387-
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
388386

389387
for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) {
390388
buf = msgs[msg_idx].buf;

0 commit comments

Comments
 (0)