From: Tyrone Ting <warp5tw@gmail.com>
To: avifishman70@gmail.com, tmaimon77@gmail.com,
tali.perry1@gmail.com, venture@google.com, yuenn@google.com,
benjaminfair@google.com, robh+dt@kernel.org,
krzysztof.kozlowski@canonical.com, semen.protsenko@linaro.org,
yangyicong@hisilicon.com, wsa@kernel.org, jie.deng@intel.com,
sven@svenpeter.dev, bence98@sch.bme.hu,
christophe.leroy@csgroup.eu, lukas.bulwahn@gmail.com,
olof@lixom.net, arnd@arndb.de, digetx@gmail.com,
andriy.shevchenko@linux.intel.com, warp5tw@gmail.com,
tali.perry@nuvoton.com, Avi.Fishman@nuvoton.com,
tomer.maimon@nuvoton.com, KWLIU@nuvoton.com, JJLIU0@nuvoton.com,
kfting@nuvoton.com
Cc: devicetree@vger.kernel.org, openbmc@lists.ozlabs.org,
linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 09/11] i2c: npcm: Handle spurious interrupts
Date: Sun, 20 Feb 2022 11:53:19 +0800 [thread overview]
Message-ID: <20220220035321.3870-10-warp5tw@gmail.com> (raw)
In-Reply-To: <20220220035321.3870-1-warp5tw@gmail.com>
From: Tali Perry <tali.perry1@gmail.com>
In order to better handle spurious interrupts:
1. Disable incoming interrupts in master only mode.
2. Clear end of busy (EOB) after every interrupt.
3. Return correct status during interrupt.
Fixes: 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
Signed-off-by: Tali Perry <tali.perry1@gmail.com>
Signed-off-by: Tyrone Ting <kfting@nuvoton.com>
---
drivers/i2c/busses/i2c-npcm7xx.c | 92 ++++++++++++++++++++++----------
1 file changed, 63 insertions(+), 29 deletions(-)
diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
index 4715afcf9ac4..a265f6fdbf5c 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -564,6 +564,15 @@ static inline void npcm_i2c_nack(struct npcm_i2c *bus)
iowrite8(val, bus->reg + NPCM_I2CCTL1);
}
+static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus)
+{
+ u8 val;
+
+ /* Clear NEGACK, STASTR and BER bits */
+ val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR;
+ iowrite8(val, bus->reg + NPCM_I2CST);
+}
+
#if IS_ENABLED(CONFIG_I2C_SLAVE)
static void npcm_i2c_slave_int_enable(struct npcm_i2c *bus, bool enable)
{
@@ -643,8 +652,8 @@ static void npcm_i2c_reset(struct npcm_i2c *bus)
iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
iowrite8(0xFF, bus->reg + NPCM_I2CST);
- /* Clear EOB bit */
- iowrite8(NPCM_I2CCST3_EO_BUSY, bus->reg + NPCM_I2CCST3);
+ /* Clear and disable EOB */
+ npcm_i2c_eob_int(bus, false);
/* Clear all fifo bits: */
iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS);
@@ -656,6 +665,9 @@ static void npcm_i2c_reset(struct npcm_i2c *bus)
}
#endif
+ /* clear status bits for spurious interrupts */
+ npcm_i2c_clear_master_status(bus);
+
bus->state = I2C_IDLE;
}
@@ -818,15 +830,6 @@ static void npcm_i2c_read_fifo(struct npcm_i2c *bus, u8 bytes_in_fifo)
}
}
-static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus)
-{
- u8 val;
-
- /* Clear NEGACK, STASTR and BER bits */
- val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR;
- iowrite8(val, bus->reg + NPCM_I2CST);
-}
-
static void npcm_i2c_master_abort(struct npcm_i2c *bus)
{
/* Only current master is allowed to issue a stop condition */
@@ -1234,7 +1237,16 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
ret = IRQ_HANDLED;
} /* SDAST */
- return ret;
+ /*
+ * if irq is not one of the above, make sure EOB is disabled and all
+ * status bits are cleared.
+ */
+ if (ret == IRQ_NONE) {
+ npcm_i2c_eob_int(bus, false);
+ npcm_i2c_clear_master_status(bus);
+ }
+
+ return IRQ_HANDLED;
}
static int npcm_i2c_reg_slave(struct i2c_client *client)
@@ -1470,6 +1482,9 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
npcm_i2c_eob_int(bus, false);
npcm_i2c_master_stop(bus);
+ /* Clear SDA Status bit (by reading dummy byte) */
+ npcm_i2c_rd_byte(bus);
+
/*
* The bus is released from stall only after the SW clears
* NEGACK bit. Then a Stop condition is sent.
@@ -1477,6 +1492,8 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
npcm_i2c_clear_master_status(bus);
readx_poll_timeout_atomic(ioread8, bus->reg + NPCM_I2CCST, val,
!(val & NPCM_I2CCST_BUSY), 10, 200);
+ /* verify no status bits are still set after bus is released */
+ npcm_i2c_clear_master_status(bus);
}
bus->state = I2C_IDLE;
@@ -1675,10 +1692,10 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
int iter = 27;
if ((npcm_i2c_get_SDA(_adap) == 1) && (npcm_i2c_get_SCL(_adap) == 1)) {
- dev_dbg(bus->dev, "bus%d recovery skipped, bus not stuck",
- bus->num);
+ dev_dbg(bus->dev, "bus%d-0x%x recovery skipped, bus not stuck",
+ bus->num, bus->dest_addr);
npcm_i2c_reset(bus);
- return status;
+ return 0;
}
npcm_i2c_int_enable(bus, false);
@@ -1912,6 +1929,7 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
bus_freq_hz < I2C_FREQ_MIN_HZ || bus_freq_hz > I2C_FREQ_MAX_HZ)
return -EINVAL;
+ npcm_i2c_int_enable(bus, false);
npcm_i2c_disable(bus);
/* Configure FIFO mode : */
@@ -1940,10 +1958,18 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
val = (val | NPCM_I2CCTL1_NMINTE) & ~NPCM_I2CCTL1_RWS;
iowrite8(val, bus->reg + NPCM_I2CCTL1);
- npcm_i2c_int_enable(bus, true);
-
npcm_i2c_reset(bus);
+ /* check HW is OK: SDA and SCL should be high at this point. */
+ if ((npcm_i2c_get_SDA(&bus->adap) == 0) ||
+ (npcm_i2c_get_SCL(&bus->adap) == 0)) {
+ dev_err(bus->dev, "I2C%d init fail: lines are low", bus->num);
+ dev_err(bus->dev, "SDA=%d SCL=%d", npcm_i2c_get_SDA(&bus->adap),
+ npcm_i2c_get_SCL(&bus->adap));
+ return -ENXIO;
+ }
+
+ npcm_i2c_int_enable(bus, true);
return 0;
}
@@ -1991,10 +2017,14 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
#if IS_ENABLED(CONFIG_I2C_SLAVE)
if (bus->slave) {
bus->master_or_slave = I2C_SLAVE;
- return npcm_i2c_int_slave_handler(bus);
+ if (npcm_i2c_int_slave_handler(bus))
+ return IRQ_HANDLED;
}
#endif
- return IRQ_NONE;
+ /* clear status bits for spurious interrupts */
+ npcm_i2c_clear_master_status(bus);
+
+ return IRQ_HANDLED;
}
static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
@@ -2051,7 +2081,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
u8 *write_data, *read_data;
u8 slave_addr;
unsigned long timeout;
- int ret = 0;
bool read_block = false;
bool read_PEC = false;
u8 bus_busy;
@@ -2141,12 +2170,12 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
bus->read_block_use = read_block;
reinit_completion(&bus->cmd_complete);
- if (!npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread,
- write_data, read_data, read_PEC,
- read_block))
- ret = -EBUSY;
- if (ret != -EBUSY) {
+ npcm_i2c_int_enable(bus, true);
+
+ if (npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread,
+ write_data, read_data, read_PEC,
+ read_block)) {
time_left = wait_for_completion_timeout(&bus->cmd_complete,
timeout);
@@ -2160,26 +2189,31 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
}
}
}
- ret = bus->cmd_err;
/* if there was BER, check if need to recover the bus: */
if (bus->cmd_err == -EAGAIN)
- ret = i2c_recover_bus(adap);
+ bus->cmd_err = i2c_recover_bus(adap);
/*
* After any type of error, check if LAST bit is still set,
* due to a HW issue.
* It cannot be cleared without resetting the module.
*/
- if (bus->cmd_err &&
- (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
+ else if (bus->cmd_err &&
+ (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
npcm_i2c_reset(bus);
+ /* after any xfer, successful or not, stall and EOB must be disabled */
+ npcm_i2c_stall_after_start(bus, false);
+ npcm_i2c_eob_int(bus, false);
+
#if IS_ENABLED(CONFIG_I2C_SLAVE)
/* reenable slave if it was enabled */
if (bus->slave)
iowrite8((bus->slave->addr & 0x7F) | NPCM_I2CADDR_SAEN,
bus->reg + NPCM_I2CADDR1);
+#else
+ npcm_i2c_int_enable(bus, false);
#endif
return bus->cmd_err;
}
--
2.17.1
next prev parent reply other threads:[~2022-02-21 5:17 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-20 3:53 [PATCH v2 00/11] i2c: npcm: Bug fixes timeout, spurious interrupts Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 01/11] arm: dts: add new property for NPCM i2c module Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 02/11] dt-bindings: i2c: npcm: support NPCM845 Tyrone Ting
2022-02-21 2:36 ` Rob Herring
2022-02-21 8:31 ` Tyrone Ting
2022-02-22 17:56 ` Rob Herring
2022-02-23 3:41 ` Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 03/11] i2c: npcm: Fix client address calculation Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 04/11] i2c: npcm: Update gcr property name Tyrone Ting
2022-02-20 9:32 ` Krzysztof Kozlowski
2022-02-21 8:29 ` Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 05/11] i2c: npcm: Remove unused clock node Tyrone Ting
2022-02-21 11:49 ` Jonathan Neuschäfer
2022-02-22 2:15 ` Tyrone Ting
2022-02-22 15:58 ` Jonathan Neuschäfer
2022-02-23 3:38 ` Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 06/11] i2c: npcm: Fix timeout calculation Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 07/11] i2c: npcm: Add tx complete counter Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 08/11] i2c: npcm: Correct register access width Tyrone Ting
2022-02-21 11:55 ` Jonathan Neuschäfer
2022-02-20 3:53 ` Tyrone Ting [this message]
2022-02-20 3:53 ` [PATCH v2 10/11] i2c: npcm: Remove own slave addresses 2:10 Tyrone Ting
2022-02-20 3:53 ` [PATCH v2 11/11] i2c: npcm: Support NPCM845 Tyrone Ting
2022-02-20 9:36 ` Krzysztof Kozlowski
2022-02-21 8:33 ` Tyrone Ting
2022-02-20 9:30 ` [PATCH v2 00/11] i2c: npcm: Bug fixes timeout, spurious interrupts Krzysztof Kozlowski
2022-02-21 8:16 ` Tyrone Ting
2022-02-21 8:32 ` Krzysztof Kozlowski
2022-02-21 8:47 ` Tyrone Ting
2022-03-01 19:45 ` Wolfram Sang
2022-03-02 12:53 ` Tyrone Ting
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220220035321.3870-10-warp5tw@gmail.com \
--to=warp5tw@gmail.com \
--cc=Avi.Fishman@nuvoton.com \
--cc=JJLIU0@nuvoton.com \
--cc=KWLIU@nuvoton.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=arnd@arndb.de \
--cc=avifishman70@gmail.com \
--cc=bence98@sch.bme.hu \
--cc=benjaminfair@google.com \
--cc=christophe.leroy@csgroup.eu \
--cc=devicetree@vger.kernel.org \
--cc=digetx@gmail.com \
--cc=jie.deng@intel.com \
--cc=kfting@nuvoton.com \
--cc=krzysztof.kozlowski@canonical.com \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas.bulwahn@gmail.com \
--cc=olof@lixom.net \
--cc=openbmc@lists.ozlabs.org \
--cc=robh+dt@kernel.org \
--cc=semen.protsenko@linaro.org \
--cc=sven@svenpeter.dev \
--cc=tali.perry1@gmail.com \
--cc=tali.perry@nuvoton.com \
--cc=tmaimon77@gmail.com \
--cc=tomer.maimon@nuvoton.com \
--cc=venture@google.com \
--cc=wsa@kernel.org \
--cc=yangyicong@hisilicon.com \
--cc=yuenn@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).