From: Thierry Reding <thierry.reding@gmail.com>
To: Sowjanya Komatineni <skomatineni@nvidia.com>
Cc: jonathanh@nvidia.com, mkarthik@nvidia.com, smohammed@nvidia.com,
talho@nvidia.com, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org
Subject: Re: [PATCH V1] i2c: tegra: Add Bus Clear Master Support
Date: Thu, 10 Jan 2019 16:21:48 +0100 [thread overview]
Message-ID: <20190110152148.GE25353@ulmo> (raw)
In-Reply-To: <1546561418-10230-1-git-send-email-skomatineni@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 4363 bytes --]
On Thu, Jan 03, 2019 at 04:23:38PM -0800, Sowjanya Komatineni wrote:
> Bus Clear feature of tegra i2c controller helps to recover from
> bus hang when i2c master loses the bus arbitration due to the
> slave device holding SDA LOW continuously for some unknown reasons.
>
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> ---
> drivers/i2c/busses/i2c-tegra.c | 65 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 65 insertions(+)
>
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index 437294ea2f0a..89a0c9fdc99e 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -63,6 +63,7 @@
> #define I2C_FIFO_STATUS_RX_SHIFT 0
> #define I2C_INT_MASK 0x064
> #define I2C_INT_STATUS 0x068
> +#define I2C_INT_BUS_CLR_DONE BIT(11)
> #define I2C_INT_PACKET_XFER_COMPLETE BIT(7)
> #define I2C_INT_ALL_PACKETS_XFER_COMPLETE BIT(6)
> #define I2C_INT_TX_FIFO_OVERFLOW BIT(5)
> @@ -105,6 +106,15 @@
> #define I2C_HEADER_MASTER_ADDR_SHIFT 12
> #define I2C_HEADER_SLAVE_ADDR_SHIFT 1
>
> +#define I2C_BUS_CLEAR_CNFG 0x084
> +#define I2C_BC_SCLK_THRESHOLD 9
> +#define I2C_BC_SCLK_THRESHOLD_SHIFT 16
> +#define I2C_BC_STOP_COND BIT(2)
> +#define I2C_BC_TERMINATE BIT(1)
> +#define I2C_BC_ENABLE BIT(0)
> +#define I2C_BUS_CLEAR_STATUS 0x088
> +#define I2C_BC_STATUS BIT(0)
> +
> #define I2C_CONFIG_LOAD 0x08C
> #define I2C_MSTR_CONFIG_LOAD BIT(0)
> #define I2C_SLV_CONFIG_LOAD BIT(1)
> @@ -154,6 +164,8 @@ enum msg_end_type {
> * @clk_divisor_std_fast_mode: Clock divisor in standard/fast mode. It is
> * applicable if there is no fast clock source i.e. single clock
> * source.
> + * @has_bus_clr_support: Bus Clear support to recover from bus hang during
> + * SDA stuck low from device for some unknown reasons.
Might as well spell out clr as clear in the name. Or maybe to make it
shorter, call it supports_bus_clear.
> */
>
> struct tegra_i2c_hw_feature {
> @@ -167,6 +179,7 @@ struct tegra_i2c_hw_feature {
> bool has_multi_master_mode;
> bool has_slcg_override_reg;
> bool has_mst_fifo;
> + bool has_bus_clr_support;
> };
>
> /**
> @@ -636,6 +649,9 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
> goto err;
> }
>
> + if (i2c_dev->hw->has_bus_clr_support && (status & I2C_INT_BUS_CLR_DONE))
> + goto err;
> +
This looks odd. If we support bus clear and the BUS_CLR_DONE interrupt
is set, shouldn't we still process all other potential interrupts? Or
was this meant to be inversed:
if (!i2c_dev->hw->supports_bus_clear && (status & I2C_INT_BUS_CLR_DONE)
?
> if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) {
> if (i2c_dev->msg_buf_remaining)
> tegra_i2c_empty_rx_fifo(i2c_dev);
> @@ -664,6 +680,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
> tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST |
> I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ |
> I2C_INT_RX_FIFO_DATA_REQ);
> + if (i2c_dev->hw->has_bus_clr_support)
> + tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
> i2c_writel(i2c_dev, status, I2C_INT_STATUS);
> if (i2c_dev->is_dvc)
> dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
> @@ -674,6 +692,41 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +static int tegra_i2c_issue_bus_clear(struct tegra_i2c_dev *i2c_dev)
> +{
> + int time_left, err;
> + u32 reg;
> +
> + if (i2c_dev->hw->has_bus_clr_support) {
> + reinit_completion(&i2c_dev->msg_complete);
> + reg = (I2C_BC_SCLK_THRESHOLD << I2C_BC_SCLK_THRESHOLD_SHIFT) |
> + I2C_BC_STOP_COND | I2C_BC_TERMINATE;
> + i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
> + if (i2c_dev->hw->has_config_load_reg) {
> + err = tegra_i2c_wait_for_config_load(i2c_dev);
> + if (err)
> + return err;
> + }
> + reg |= I2C_BC_ENABLE;
> + i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
> + tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
> +
> + time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
> + TEGRA_I2C_TIMEOUT);
wait_for_completion_timeout() returns an unsigned long, so the type of
time_left should reflect that.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2019-01-10 15:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-04 0:23 [PATCH V1] i2c: tegra: Add Bus Clear Master Support Sowjanya Komatineni
2019-01-04 0:23 ` Sowjanya Komatineni
2019-01-10 15:21 ` Thierry Reding [this message]
2019-01-10 22:59 ` Sowjanya Komatineni
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=20190110152148.GE25353@ulmo \
--to=thierry.reding@gmail.com \
--cc=jonathanh@nvidia.com \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=mkarthik@nvidia.com \
--cc=skomatineni@nvidia.com \
--cc=smohammed@nvidia.com \
--cc=talho@nvidia.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.