summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-i801.c
diff options
context:
space:
mode:
authorYann Sionneau <ysionneau@kalray.eu>2023-09-11 17:07:49 +0300
committerWolfram Sang <wsa@kernel.org>2023-09-19 22:57:11 +0300
commit2409205acd3c7c877f3d0080cac6a5feb3358f83 (patch)
tree779312359899d099411f5a5bc87cc62507bf79b2 /drivers/i2c/busses/i2c-i801.c
parent3914784553f68c931fc666dbe7e86fe881aada38 (diff)
downloadlinux-2409205acd3c7c877f3d0080cac6a5feb3358f83.tar.xz
i2c: designware: fix __i2c_dw_disable() in case master is holding SCL low
The DesignWare IP can be synthesized with the IC_EMPTYFIFO_HOLD_MASTER_EN parameter. In this case, when the TX FIFO gets empty and the last command didn't have the STOP bit (IC_DATA_CMD[9]), the controller will hold SCL low until a new command is pushed into the TX FIFO or the transfer is aborted. When the controller is holding SCL low, it cannot be disabled. The transfer must first be aborted. Also, the bus recovery won't work because SCL is held low by the master. Check if the master is holding SCL low in __i2c_dw_disable() before trying to disable the controller. If SCL is held low, an abort is initiated. When the abort is done, then proceed with disabling the controller. This whole situation can happen for instance during SMBus read data block if the slave just responds with "byte count == 0". This puts the driver in an unrecoverable state, because the controller is holding SCL low and the current __i2c_dw_disable() procedure is not working. In this situation only a SoC reset can fix the i2c bus. Co-developed-by: Jonathan Borne <jborne@kalray.eu> Signed-off-by: Jonathan Borne <jborne@kalray.eu> Signed-off-by: Yann Sionneau <ysionneau@kalray.eu> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
0 files changed, 0 insertions, 0 deletions