The current i2c-omap driver is set up for 32-bit registers, which
corresponds to most OMAP devices.  However, OMAP730/850 based
devices use a 16-bit register size.

This change modifies the driver to perform a runtime CPU type check
to determine the register sizes, and uses a bit shift of either 1
or 2 bits to compute the proper register sizes for all registers.

Signed-off-by: Cory Maccarrone <darkstar6...@gmail.com>
---
 drivers/i2c/busses/i2c-omap.c |  138 ++++++++++++++++++++++-------------------
 1 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 827da08..dc7cf71 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -49,24 +49,26 @@
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
 #define OMAP_I2C_REV_REG               0x00
-#define OMAP_I2C_IE_REG                        0x04
-#define OMAP_I2C_STAT_REG              0x08
-#define OMAP_I2C_IV_REG                        0x0c
+#define OMAP_I2C_IE_REG                        0x01
+#define OMAP_I2C_STAT_REG              0x02
+#define OMAP_I2C_IV_REG                        0x03
 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
-#define OMAP_I2C_WE_REG                        0x0c
-#define OMAP_I2C_SYSS_REG              0x10
-#define OMAP_I2C_BUF_REG               0x14
-#define OMAP_I2C_CNT_REG               0x18
-#define OMAP_I2C_DATA_REG              0x1c
-#define OMAP_I2C_SYSC_REG              0x20
-#define OMAP_I2C_CON_REG               0x24
-#define OMAP_I2C_OA_REG                        0x28
-#define OMAP_I2C_SA_REG                        0x2c
-#define OMAP_I2C_PSC_REG               0x30
-#define OMAP_I2C_SCLL_REG              0x34
-#define OMAP_I2C_SCLH_REG              0x38
-#define OMAP_I2C_SYSTEST_REG           0x3c
-#define OMAP_I2C_BUFSTAT_REG           0x40
+#define OMAP_I2C_WE_REG                        0x03
+#define OMAP_I2C_SYSS_REG              0x04
+#define OMAP_I2C_BUF_REG               0x05
+#define OMAP_I2C_CNT_REG               0x06
+#define OMAP_I2C_DATA_REG              0x07
+#define OMAP_I2C_SYSC_REG              0x08
+#define OMAP_I2C_CON_REG               0x09
+#define OMAP_I2C_OA_REG                        0x0a
+#define OMAP_I2C_SA_REG                        0x0b
+#define OMAP_I2C_PSC_REG               0x0c
+#define OMAP_I2C_SCLL_REG              0x0d
+#define OMAP_I2C_SCLH_REG              0x0e
+#define OMAP_I2C_SYSTEST_REG           0x0f
+#define OMAP_I2C_BUFSTAT_REG           0x10
+
+#define OMAP_I2C_REG(host, reg)                (OMAP_I2C_##reg##_REG << 
(host)->reg_shift)
 
 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
 #define OMAP_I2C_IE_XDR                (1 << 14)       /* TX Buffer drain int 
enable */
@@ -161,6 +163,7 @@ struct omap_i2c_dev {
        struct device           *dev;
        void __iomem            *base;          /* virtual */
        int                     irq;
+       int                     reg_shift;      /* bit shift for I2C register 
addresses */
        struct clk              *iclk;          /* Interface clock */
        struct clk              *fclk;          /* Functional clock */
        struct completion       cmd_complete;
@@ -232,7 +235,7 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
        clk_enable(dev->fclk);
        dev->idle = 0;
        if (dev->iestate)
-               omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, IE), dev->iestate);
 }
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
@@ -241,15 +244,15 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
 
        WARN_ON(dev->idle);
 
-       dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-       omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
+       dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, IE));
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, IE), 0);
        if (dev->rev < OMAP_I2C_REV_2) {
-               iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
+               iv = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, IV)); /* Read 
clears */
        } else {
-               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, STAT), dev->iestate);
 
                /* Flush posted write before the dev->idle store occurs */
-               omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+               omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, STAT));
        }
        dev->idle = 1;
        clk_disable(dev->fclk);
@@ -265,12 +268,12 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
        unsigned long internal_clk = 0;
 
        if (dev->rev >= OMAP_I2C_REV_2) {
-               omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, SYSC), 
SYSC_SOFTRESET_MASK);
                /* For some reason we need to set the EN bit before the
                 * reset done bit gets set. */
                timeout = jiffies + OMAP_I2C_TIMEOUT;
-               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
-               while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), 
OMAP_I2C_CON_EN);
+               while (!(omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, SYSS)) &
                         SYSS_RESETDONE_MASK)) {
                        if (time_after(jiffies, timeout)) {
                                dev_warn(dev->dev, "timeout waiting "
@@ -283,7 +286,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
                /* SYSC register is cleared by the reset; rewrite it */
                if (dev->rev == OMAP_I2C_REV_ON_2430) {
 
-                       omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+                       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, SYSC),
                                           SYSC_AUTOIDLE_MASK);
 
                } else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
@@ -296,18 +299,18 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
                        v |= (SYSC_CLOCKACTIVITY_FCLK <<
                              __ffs(SYSC_CLOCKACTIVITY_MASK));
 
-                       omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+                       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, SYSC), v);
                        /*
                         * Enabling all wakup sources to stop I2C freezing on
                         * WFI instruction.
                         * REVISIT: Some wkup sources might not be needed.
                         */
-                       omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+                       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, WE),
                                                        OMAP_I2C_WE_ALL);
 
                }
        }
-       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), 0);
 
        if (cpu_class_is_omap1()) {
                /*
@@ -388,25 +391,25 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
        }
 
        /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
-       omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, PSC), psc);
 
        /* SCL low and high time values */
-       omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
-       omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, SCLL), scll);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, SCLH), sclh);
 
        if (dev->fifo_size)
                /* Note: setup required fifo size - 1 */
-               omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, BUF),
                                        (dev->fifo_size - 1) << 8 | /* RTRSH */
                                        OMAP_I2C_BUF_RXFIF_CLR |
                                        (dev->fifo_size - 1) | /* XTRSH */
                                        OMAP_I2C_BUF_TXFIF_CLR);
 
        /* Take the I2C module out of reset: */
-       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), OMAP_I2C_CON_EN);
 
        /* Enable interrupts */
-       omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, IE),
                        (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
                        OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
                        OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
@@ -422,7 +425,7 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
        unsigned long timeout;
 
        timeout = jiffies + OMAP_I2C_TIMEOUT;
-       while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
+       while (omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, STAT)) & 
OMAP_I2C_STAT_BB) {
                if (time_after(jiffies, timeout)) {
                        dev_warn(dev->dev, "timeout waiting for bus ready\n");
                        return -ETIMEDOUT;
@@ -449,18 +452,18 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        if (msg->len == 0)
                return -EINVAL;
 
-       omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, SA), msg->addr);
 
        /* REVISIT: Could the STB bit of I2C_CON be used with probing? */
        dev->buf = msg->buf;
        dev->buf_len = msg->len;
 
-       omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CNT), dev->buf_len);
 
        /* Clear the FIFO Buffers */
-       w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+       w = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, BUF));
        w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
-       omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, BUF), w);
 
        init_completion(&dev->cmd_complete);
        dev->cmd_err = 0;
@@ -479,16 +482,16 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        if (!dev->b_hw && stop)
                w |= OMAP_I2C_CON_STP;
 
-       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), w);
 
        /*
         * Don't write stt and stp together on some hardware.
         */
        if (dev->b_hw && stop) {
                unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
-               u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+               u16 con = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, CON));
                while (con & OMAP_I2C_CON_STT) {
-                       con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+                       con = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, CON));
 
                        /* Let the user know if i2c is in a bad state */
                        if (time_after(jiffies, delay)) {
@@ -501,7 +504,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 
                w |= OMAP_I2C_CON_STP;
                w &= ~OMAP_I2C_CON_STT;
-               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), w);
        }
 
        /*
@@ -533,9 +536,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
                if (msg->flags & I2C_M_IGNORE_NAK)
                        return 0;
                if (stop) {
-                       w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, CON));
                        w |= OMAP_I2C_CON_STP;
-                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+                       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), w);
                }
                return -EREMOTEIO;
        }
@@ -589,7 +592,7 @@ omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err)
 static inline void
 omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
 {
-       omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, STAT), stat);
 }
 
 /* rev1 devices are apparently only on some 15xx */
@@ -604,7 +607,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
        if (dev->idle)
                return IRQ_NONE;
 
-       iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+       iv = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, IV));
        switch (iv) {
        case 0x00:      /* None */
                break;
@@ -614,14 +617,14 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
                break;
        case 0x02:      /* No acknowledgement */
                omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
-               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP);
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), 
OMAP_I2C_CON_STP);
                break;
        case 0x03:      /* Register access ready */
                omap_i2c_complete_cmd(dev, 0);
                break;
        case 0x04:      /* Receive data ready */
                if (dev->buf_len) {
-                       w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, DATA));
                        *dev->buf++ = w;
                        dev->buf_len--;
                        if (dev->buf_len) {
@@ -639,7 +642,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
                                w |= *dev->buf++ << 8;
                                dev->buf_len--;
                        }
-                       omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+                       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, DATA), w);
                } else
                        dev_err(dev->dev, "XRDY IRQ while no data to send\n");
                break;
@@ -664,8 +667,8 @@ omap_i2c_isr(int this_irq, void *dev_id)
        if (dev->idle)
                return IRQ_NONE;
 
-       bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-       while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
+       bits = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, IE));
+       while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, STAT)))) & 
bits) {
                dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
                if (count++ == 100) {
                        dev_warn(dev->dev, "Too much work in one IRQ\n");
@@ -679,13 +682,13 @@ complete:
                 * acked after the data operation is complete.
                 * Ref: TRM SWPU114Q Figure 18-31
                 */
-               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, STAT), stat &
                                ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
                                OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
 
                if (stat & OMAP_I2C_STAT_NACK) {
                        err |= OMAP_I2C_STAT_NACK;
-                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+                       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON),
                                           OMAP_I2C_CON_STP);
                }
                if (stat & OMAP_I2C_STAT_AL) {
@@ -707,12 +710,12 @@ complete:
                                        num_bytes = dev->fifo_size;
                                else    /* read RXSTAT on RDR interrupt */
                                        num_bytes = (omap_i2c_read_reg(dev,
-                                                       OMAP_I2C_BUFSTAT_REG)
+                                                       OMAP_I2C_REG(dev, 
BUFSTAT))
                                                        >> 8) & 0x3F;
                        }
                        while (num_bytes) {
                                num_bytes--;
-                               w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                               w = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, 
DATA));
                                if (dev->buf_len) {
                                        *dev->buf++ = w;
                                        dev->buf_len--;
@@ -747,7 +750,7 @@ complete:
                                        num_bytes = dev->fifo_size;
                                else    /* read TXSTAT on XDR interrupt */
                                        num_bytes = omap_i2c_read_reg(dev,
-                                                       OMAP_I2C_BUFSTAT_REG)
+                                                       OMAP_I2C_REG(dev, 
BUFSTAT))
                                                        & 0x3F;
                        }
                        while (num_bytes) {
@@ -792,11 +795,11 @@ complete:
                                                                goto complete;
                                                        }
                                                        cpu_relax();
-                                                       stat = 
omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+                                                       stat = 
omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, STAT));
                                                }
                                }
 
-                               omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+                               omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, 
DATA), w);
                        }
                        omap_i2c_ack_stat(dev,
                                stat & (OMAP_I2C_STAT_XRDY | 
OMAP_I2C_STAT_XDR));
@@ -877,13 +880,13 @@ omap_i2c_probe(struct platform_device *pdev)
 
        omap_i2c_unidle(dev);
 
-       dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+       dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, REV)) & 0xff;
 
        if (cpu_is_omap2430() || cpu_is_omap34xx()) {
                u16 s;
 
                /* Set up the fifo size - Get total size */
-               s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
+               s = (omap_i2c_read_reg(dev, OMAP_I2C_REG(dev, BUFSTAT)) >> 14) 
& 0x3;
                dev->fifo_size = 0x8 << s;
 
                /*
@@ -895,6 +898,11 @@ omap_i2c_probe(struct platform_device *pdev)
                dev->b_hw = 1; /* Enable hardware fixes */
        }
 
+       if (cpu_is_omap7xx())
+               dev->reg_shift = 1;
+       else
+               dev->reg_shift = 2;
+
        /* reset ASAP, clearing any IRQs */
        omap_i2c_init(dev);
 
@@ -932,7 +940,7 @@ omap_i2c_probe(struct platform_device *pdev)
 err_free_irq:
        free_irq(dev->irq, dev);
 err_unuse_clocks:
-       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), 0);
        omap_i2c_idle(dev);
        omap_i2c_put_clocks(dev);
 err_iounmap:
@@ -956,7 +964,7 @@ omap_i2c_remove(struct platform_device *pdev)
 
        free_irq(dev->irq, dev);
        i2c_del_adapter(&dev->adapter);
-       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       omap_i2c_write_reg(dev, OMAP_I2C_REG(dev, CON), 0);
        omap_i2c_put_clocks(dev);
        iounmap(dev->base);
        kfree(dev);
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to