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

Reply via email to