From: Anders Berg <anders.b...@avagotech.com> If the device tree does not specify an interrupt property, the device falls back to polling the controller status. This is needed to support simulator models without interrupt capabilities.
Signed-off-by: Anders Berg <anders.b...@avagotech.com> --- drivers/i2c/busses/i2c-axxia.c | 82 +++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index 4721d3c..93f73ec 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -123,6 +123,8 @@ struct axxia_i2c_dev { size_t msg_xfrd; /* error code for completed message */ int msg_err; + /* IRQ number (or 0 if not using interrupt) */ + int irq; /* current i2c bus clock rate */ u32 bus_clk_rate; }; @@ -327,15 +329,11 @@ status_str(u32 status) return buf; } -static irqreturn_t -axxia_i2c_isr(int irq, void *_dev) +static void +axxia_i2c_service_irq(struct axxia_i2c_dev *idev) { - struct axxia_i2c_dev *idev = _dev; u32 status = readl(&idev->regs->mst_int_status); - /* Clear interrupt */ - writel(0x01, &idev->regs->interrupt_status); - /* RX FIFO needs service? */ if (i2c_m_rd(idev->msg) && (status & MST_STATUS_RFL)) axxia_i2c_empty_rx_fifo(idev); @@ -370,6 +368,23 @@ axxia_i2c_isr(int irq, void *_dev) readl(&idev->regs->mst_tx_xfer)); complete(&idev->msg_complete); } +} + +static irqreturn_t +axxia_i2c_isr(int irq, void *_dev) +{ + struct axxia_i2c_dev *idev = _dev; + + if ((readl(&idev->regs->interrupt_status) & 0x1) == 0) + return IRQ_NONE; + + if (!idev->msg) + return IRQ_NONE; + + axxia_i2c_service_irq(idev); + + /* Clear interrupt */ + writel(0x01, &idev->regs->interrupt_status); return IRQ_HANDLED; } @@ -436,14 +451,21 @@ axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg) /* Start manual mode */ writel(0x8, &idev->regs->mst_command); - i2c_int_enable(idev, int_mask); - - ret = wait_for_completion_timeout(&idev->msg_complete, - I2C_XFER_TIMEOUT); - - i2c_int_disable(idev, int_mask); + if (idev->irq > 0) { + i2c_int_enable(idev, int_mask); + ret = wait_for_completion_timeout(&idev->msg_complete, + I2C_XFER_TIMEOUT); + i2c_int_disable(idev, int_mask); + WARN_ON(readl(&idev->regs->mst_command) & 0x8); + } else { + unsigned long tmo = jiffies + I2C_XFER_TIMEOUT; - WARN_ON(readl(&idev->regs->mst_command) & 0x8); + do { + /* Poll interrupt status */ + axxia_i2c_service_irq(idev); + ret = try_wait_for_completion(&idev->msg_complete); + } while (!ret && time_before(jiffies, tmo)); + } if (ret == 0) { dev_warn(idev->dev, "xfer timeout (%#x)\n", msg->addr); @@ -518,7 +540,6 @@ axxia_i2c_probe(struct platform_device *pdev) struct axxia_i2c_dev *idev = NULL; struct resource *res; void __iomem *base; - int irq; int ret = 0; idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); @@ -526,48 +547,41 @@ axxia_i2c_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "can't get device io-resource\n"); - return -ENOENT; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "can't get irq number\n"); - return -ENOENT; - } - base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); + idev->irq = platform_get_irq(pdev, 0); + if (idev->irq < 0) + dev_info(&pdev->dev, "No IRQ specified, using polling mode\n"); + idev->i2c_clk = devm_clk_get(&pdev->dev, "i2c"); if (IS_ERR(idev->i2c_clk)) { dev_err(&pdev->dev, "missing I2C bus clock"); return PTR_ERR(idev->i2c_clk); } - idev->regs = (struct i2c_regs __iomem *) base; - idev->dev = &pdev->dev; + idev->regs = (struct i2c_regs __iomem *) base; + idev->dev = &pdev->dev; init_completion(&idev->msg_complete); of_property_read_u32(np, "clock-frequency", &idev->bus_clk_rate); if (idev->bus_clk_rate == 0) idev->bus_clk_rate = 100000; /* default clock rate */ - platform_set_drvdata(pdev, idev); - ret = axxia_i2c_init(idev); if (ret) { dev_err(&pdev->dev, "Failed to initialize i2c controller"); return ret; } - ret = devm_request_irq(&pdev->dev, irq, axxia_i2c_isr, 0, - pdev->name, idev); - if (ret) { - dev_err(&pdev->dev, "can't claim irq %d\n", irq); - return ret; + if (idev->irq >= 0) { + ret = devm_request_irq(&pdev->dev, idev->irq, axxia_i2c_isr, 0, + pdev->name, idev); + if (ret) { + dev_err(&pdev->dev, "can't claim irq %d\n", idev->irq); + return ret; + } } clk_enable(idev->i2c_clk); -- 1.7.9.5 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto