Skip to content

Commit

Permalink
i2c: designware: Add missing locks
Browse files Browse the repository at this point in the history
All accesses to controller's registers should be protected on
probe, disable and xfer paths. This is needed for i2c bus controllers
that are shared with but not controller by kernel.

Signed-off-by: Jan Dabros <jsd@semihalf.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
  • Loading branch information
Jan Dabros authored and Wolfram Sang committed Feb 11, 2022
1 parent 6cf72f4 commit 6960331
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 0 deletions.
12 changes: 12 additions & 0 deletions drivers/i2c/busses/i2c-designware-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,12 @@ int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
* Try to detect the FIFO depth if not set by interface driver,
* the depth could be from 2 to 256 from HW spec.
*/
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;

ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &param);
i2c_dw_release_lock(dev);
if (ret)
return ret;

Expand Down Expand Up @@ -607,13 +612,20 @@ u32 i2c_dw_func(struct i2c_adapter *adap)
void i2c_dw_disable(struct dw_i2c_dev *dev)
{
u32 dummy;
int ret;

ret = i2c_dw_acquire_lock(dev);
if (ret)
return;

/* Disable controller */
__i2c_dw_disable(dev);

/* Disable all interrupts */
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);

i2c_dw_release_lock(dev);
}

void i2c_dw_disable_int(struct dw_i2c_dev *dev)
Expand Down
6 changes: 6 additions & 0 deletions drivers/i2c/busses/i2c-designware-master.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,13 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
}

ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;

i2c_dw_disable_int(dev);
i2c_dw_release_lock(dev);

ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags,
dev_name(dev->dev), dev);
if (ret) {
Expand Down

0 comments on commit 6960331

Please sign in to comment.