From: Todd Poynor Date: Wed, 13 Oct 2010 01:38:51 +0000 (-0700) Subject: Temporary I2C debugging code X-Git-Tag: firefly_0821_release~9834^2~437 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1a51eabd194b2346d2cca640c25313ce1c8fef24;p=firefly-linux-kernel-4.4.55.git Temporary I2C debugging code To help diagnose repeated transfer timeouts and interrupt storms on Stingray. Change-Id: I55366d269c6bc4ffdb4468a614442f2dad87ace1 --- diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7e201501a84c..a7bcc22af65e 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -95,6 +95,8 @@ #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT 1 +#define DEBUG_TEGRA_I2C_TEMP + struct tegra_i2c_dev; struct tegra_i2c_bus { @@ -128,6 +130,9 @@ struct tegra_i2c_dev { int last_mux_len; unsigned long last_bus_clk; struct tegra_i2c_bus busses[1]; +#ifdef DEBUG_TEGRA_I2C_TEMP + atomic_t incmplt_irq_count; +#endif }; static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) @@ -326,6 +331,10 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) clk_disable(i2c_dev->clk); +#ifdef DEBUG_TEGRA_I2C_TEMP + atomic_set(&i2c_dev->incmplt_irq_count, 0); +#endif + if (i2c_dev->irq_disabled) { i2c_dev->irq_disabled = 0; enable_irq(i2c_dev->irq); @@ -342,6 +351,34 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) status = i2c_readl(i2c_dev, I2C_INT_STATUS); +#ifdef DEBUG_TEGRA_I2C_TEMP + if (atomic_inc_return(&i2c_dev->incmplt_irq_count) == 1000) { + dev_err(i2c_dev->dev, "suspected irq storm\n"); + pr_err("ist=%x im=%x pxst=%x st=%x cfg=%x fst=%x fc=%x\n", + i2c_readl(i2c_dev, I2C_INT_STATUS), + i2c_readl(i2c_dev, I2C_INT_MASK), + i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), + i2c_readl(i2c_dev, I2C_STATUS), + i2c_readl(i2c_dev, I2C_CNFG), + i2c_readl(i2c_dev, I2C_FIFO_STATUS), + i2c_readl(i2c_dev, I2C_FIFO_CONTROL)); + pr_err("mbrm=%d mcmp=%d merr=%d\n", + i2c_dev->msg_buf_remaining, + i2c_dev->msg_transfer_complete, + i2c_dev->msg_err); + + i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT << 1; + + if (! i2c_dev->irq_disabled) { + disable_irq_nosync(i2c_dev->irq); + i2c_dev->irq_disabled = 1; + } + + complete(&i2c_dev->msg_complete); + goto err; + } +#endif + if (status == 0) { dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n", i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), @@ -398,7 +435,7 @@ err: i2c_writel(i2c_dev, status, I2C_INT_STATUS); if (i2c_dev->is_dvc) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); - return IRQ_HANDLED; + return IRQ_NONE; } static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus, @@ -457,9 +494,28 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus, ret = wait_for_completion_timeout(&i2c_dev->msg_complete, TEGRA_I2C_TIMEOUT); tegra_i2c_mask_irq(i2c_dev, int_mask); +#ifdef DEBUG_TEGRA_I2C_TEMP + atomic_set(&i2c_dev->incmplt_irq_count, 0); +#endif + if (WARN_ON(ret == 0)) { dev_err(i2c_dev->dev, "i2c transfer timed out\n"); - +#ifdef DEBUG_TEGRA_I2C_TEMP + pr_err("ist=%x im=%x pxst=%x st=%x cfg=%x fst=%x fc=%x\n", + i2c_readl(i2c_dev, I2C_INT_STATUS), + i2c_readl(i2c_dev, I2C_INT_MASK), + i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), + i2c_readl(i2c_dev, I2C_STATUS), + i2c_readl(i2c_dev, I2C_CNFG), + i2c_readl(i2c_dev, I2C_FIFO_STATUS), + i2c_readl(i2c_dev, I2C_FIFO_CONTROL)); + pr_err("mbrm=%d mcmp=%d merr=%d\n", + i2c_dev->msg_buf_remaining, + i2c_dev->msg_transfer_complete, + i2c_dev->msg_err); + pr_err("madr=%x mlen=%d mfl=%x stop=%d\n", msg->addr, msg->len, + msg->flags, stop); +#endif tegra_i2c_init(i2c_dev); return -ETIMEDOUT; }