Merge branches 'for-32/i2c/omap-v4', 'for-32/i2c/imx-dt', 'for-32/i2c/eg20t-v4',...
authorBen Dooks <ben-linux@fluff.org>
Tue, 1 Nov 2011 00:50:09 +0000 (00:50 +0000)
committerBen Dooks <ben-linux@fluff.org>
Tue, 1 Nov 2011 00:50:09 +0000 (00:50 +0000)
12 files changed:
Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/i2c.h
arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-designware-core.c [moved from drivers/i2c/busses/i2c-designware.c with 65% similarity]
drivers/i2c/busses/i2c-designware-core.h [new file with mode: 0644]
drivers/i2c/busses/i2c-designware-pcidrv.c [new file with mode: 0644]
drivers/i2c/busses/i2c-designware-platdrv.c [new file with mode: 0644]
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-imx.c

diff --git a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
new file mode 100644 (file)
index 0000000..f3cf43b
--- /dev/null
@@ -0,0 +1,25 @@
+* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-i2c"
+- reg : Should contain I2C/HS-I2C registers location and length
+- interrupts : Should contain I2C/HS-I2C interrupt
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+  The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples:
+
+i2c@83fc4000 { /* I2C2 on i.MX51 */
+       compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+       reg = <0x83fc4000 0x4000>;
+       interrupts = <63>;
+};
+
+i2c@70038000 { /* HS-I2C on i.MX51 */
+       compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+       reg = <0x70038000 0x4000>;
+       interrupts = <64>;
+       clock-frequency = <400000>;
+};
index 4a5dc5c..375cdd0 100644 (file)
 
 /**
  * struct imxi2c_platform_data - structure of platform data for MXC I2C driver
- * @init:      Initialise gpio's and other board specific things
- * @exit:      Free everything initialised by @init
  * @bitrate:   Bus speed measured in Hz
  *
  **/
 struct imxi2c_platform_data {
-       int (*init)(struct device *dev);
-       void (*exit)(struct device *dev);
        int bitrate;
 };
 
index 892b7f1..5a5cb73 100644 (file)
@@ -394,19 +394,6 @@ typedef struct     psc_spi {
 #define PSC_SPITXRX_LC         (1 << 29)
 #define PSC_SPITXRX_SR         (1 << 28)
 
-/* PSC in SMBus (I2C) Mode. */
-typedef struct psc_smb {
-       u32     psc_sel;
-       u32     psc_ctrl;
-       u32     psc_smbcfg;
-       u32     psc_smbmsk;
-       u32     psc_smbpcr;
-       u32     psc_smbstat;
-       u32     psc_smbevnt;
-       u32     psc_smbtxrx;
-       u32     psc_smbtmr;
-} psc_smb_t;
-
 /* SMBus Config Register. */
 #define PSC_SMBCFG_RT_MASK     (3 << 30)
 #define PSC_SMBCFG_RT_FIFO1    (0 << 30)
index 646068e..1d7ce9c 100644 (file)
@@ -350,15 +350,25 @@ config I2C_DAVINCI
          devices such as DaVinci NIC.
          For details please see http://www.ti.com/davinci
 
-config I2C_DESIGNWARE
-       tristate "Synopsys DesignWare"
+config I2C_DESIGNWARE_PLATFORM
+       tristate "Synopsys DesignWare Platfrom"
        depends on HAVE_CLK
        help
          If you say yes to this option, support will be included for the
          Synopsys DesignWare I2C adapter. Only master mode is supported.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-designware.
+         will be called i2c-designware-platform.
+
+config I2C_DESIGNWARE_PCI
+       tristate "Synopsys DesignWare PCI"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the
+         Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-designware-pci.
 
 config I2C_GPIO
        tristate "GPIO-based bitbanging I2C"
index e6cf294..fba6da6 100644 (file)
@@ -33,7 +33,10 @@ obj-$(CONFIG_I2C_AU1550)     += i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)          += i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)      += i2c-davinci.o
-obj-$(CONFIG_I2C_DESIGNWARE)   += i2c-designware.o
+obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)  += i2c-designware-platform.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+obj-$(CONFIG_I2C_DESIGNWARE_PCI)       += i2c-designware-pci.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
 obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)   += i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)      += i2c-ibm_iic.o
index 532828b..4f757a2 100644 (file)
 #include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
+#define PSC_SEL                0x00
+#define PSC_CTRL       0x04
+#define PSC_SMBCFG     0x08
+#define PSC_SMBMSK     0x0C
+#define PSC_SMBPCR     0x10
+#define PSC_SMBSTAT    0x14
+#define PSC_SMBEVNT    0x18
+#define PSC_SMBTXRX    0x1C
+#define PSC_SMBTMR     0x20
+
 struct i2c_au1550_data {
-       u32     psc_base;
+       void __iomem *psc_base;
        int     xfer_timeout;
-       int     ack_timeout;
        struct i2c_adapter adap;
        struct resource *ioarea;
 };
 
-static int
-wait_xfer_done(struct i2c_au1550_data *adap)
+static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
 {
-       u32     stat;
-       int     i;
-       volatile psc_smb_t      *sp;
+       __raw_writel(v, a->psc_base + r);
+       wmb();
+}
 
-       sp = (volatile psc_smb_t *)(adap->psc_base);
+static inline unsigned long RD(struct i2c_au1550_data *a, int r)
+{
+       return __raw_readl(a->psc_base + r);
+}
 
-       /* Wait for Tx Buffer Empty
-       */
+static int wait_xfer_done(struct i2c_au1550_data *adap)
+{
+       int i;
+
+       /* Wait for Tx Buffer Empty */
        for (i = 0; i < adap->xfer_timeout; i++) {
-               stat = sp->psc_smbstat;
-               au_sync();
-               if ((stat & PSC_SMBSTAT_TE) != 0)
+               if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
                        return 0;
 
                udelay(1);
@@ -70,41 +82,27 @@ wait_xfer_done(struct i2c_au1550_data *adap)
        return -ETIMEDOUT;
 }
 
-static int
-wait_ack(struct i2c_au1550_data *adap)
+static int wait_ack(struct i2c_au1550_data *adap)
 {
-       u32     stat;
-       volatile psc_smb_t      *sp;
+       unsigned long stat;
 
        if (wait_xfer_done(adap))
                return -ETIMEDOUT;
 
-       sp = (volatile psc_smb_t *)(adap->psc_base);
-
-       stat = sp->psc_smbevnt;
-       au_sync();
-
+       stat = RD(adap, PSC_SMBEVNT);
        if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
                return -ETIMEDOUT;
 
        return 0;
 }
 
-static int
-wait_master_done(struct i2c_au1550_data *adap)
+static int wait_master_done(struct i2c_au1550_data *adap)
 {
-       u32     stat;
-       int     i;
-       volatile psc_smb_t      *sp;
+       int i;
 
-       sp = (volatile psc_smb_t *)(adap->psc_base);
-
-       /* Wait for Master Done.
-       */
-       for (i = 0; i < adap->xfer_timeout; i++) {
-               stat = sp->psc_smbevnt;
-               au_sync();
-               if ((stat & PSC_SMBEVNT_MD) != 0)
+       /* Wait for Master Done. */
+       for (i = 0; i < 2 * adap->xfer_timeout; i++) {
+               if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
                        return 0;
                udelay(1);
        }
@@ -115,29 +113,20 @@ wait_master_done(struct i2c_au1550_data *adap)
 static int
 do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
 {
-       volatile psc_smb_t      *sp;
-       u32                     stat;
+       unsigned long stat;
 
-       sp = (volatile psc_smb_t *)(adap->psc_base);
-
-       /* Reset the FIFOs, clear events.
-       */
-       stat = sp->psc_smbstat;
-       sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
-       au_sync();
+       /* Reset the FIFOs, clear events. */
+       stat = RD(adap, PSC_SMBSTAT);
+       WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
 
        if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
-               sp->psc_smbpcr = PSC_SMBPCR_DC;
-               au_sync();
-               do {
-                       stat = sp->psc_smbpcr;
-                       au_sync();
-               } while ((stat & PSC_SMBPCR_DC) != 0);
+               WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
+               while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
+                       cpu_relax();
                udelay(50);
        }
 
-       /* Write out the i2c chip address and specify operation
-       */
+       /* Write out the i2c chip address and specify operation */
        addr <<= 1;
        if (rd)
                addr |= 1;
@@ -146,56 +135,42 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
        if (q)
                addr |= PSC_SMBTXRX_STP;
 
-       /* Put byte into fifo, start up master.
-       */
-       sp->psc_smbtxrx = addr;
-       au_sync();
-       sp->psc_smbpcr = PSC_SMBPCR_MS;
-       au_sync();
+       /* Put byte into fifo, start up master. */
+       WR(adap, PSC_SMBTXRX, addr);
+       WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
        if (wait_ack(adap))
                return -EIO;
        return (q) ? wait_master_done(adap) : 0;
 }
 
-static u32
-wait_for_rx_byte(struct i2c_au1550_data *adap, u32 *ret_data)
+static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
 {
-       int     j;
-       u32     data, stat;
-       volatile psc_smb_t      *sp;
+       int j;
 
        if (wait_xfer_done(adap))
                return -EIO;
 
-       sp = (volatile psc_smb_t *)(adap->psc_base);
-
        j =  adap->xfer_timeout * 100;
        do {
                j--;
                if (j <= 0)
                        return -EIO;
 
-               stat = sp->psc_smbstat;
-               au_sync();
-               if ((stat & PSC_SMBSTAT_RE) == 0)
+               if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
                        j = 0;
                else
                        udelay(1);
        } while (j > 0);
-       data = sp->psc_smbtxrx;
-       au_sync();
-       *ret_data = data;
+
+       *out = RD(adap, PSC_SMBTXRX);
 
        return 0;
 }
 
-static int
-i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
                    unsigned int len)
 {
-       int     i;
-       u32     data;
-       volatile psc_smb_t      *sp;
+       int i;
 
        if (len == 0)
                return 0;
@@ -204,62 +179,46 @@ i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
         * zero bytes for timing, waiting for bytes to appear in the
         * receive fifo, then reading the bytes.
         */
-
-       sp = (volatile psc_smb_t *)(adap->psc_base);
-
        i = 0;
-       while (i < (len-1)) {
-               sp->psc_smbtxrx = 0;
-               au_sync();
-               if (wait_for_rx_byte(adap, &data))
+       while (i < (len - 1)) {
+               WR(adap, PSC_SMBTXRX, 0);
+               if (wait_for_rx_byte(adap, &buf[i]))
                        return -EIO;
 
-               buf[i] = data;
                i++;
        }
 
-       /* The last byte has to indicate transfer done.
-       */
-       sp->psc_smbtxrx = PSC_SMBTXRX_STP;
-       au_sync();
+       /* The last byte has to indicate transfer done. */
+       WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
        if (wait_master_done(adap))
                return -EIO;
 
-       data = sp->psc_smbtxrx;
-       au_sync();
-       buf[i] = data;
+       buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
        return 0;
 }
 
-static int
-i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
                     unsigned int len)
 {
-       int     i;
-       u32     data;
-       volatile psc_smb_t      *sp;
+       int i;
+       unsigned long data;
 
        if (len == 0)
                return 0;
 
-       sp = (volatile psc_smb_t *)(adap->psc_base);
-
        i = 0;
        while (i < (len-1)) {
                data = buf[i];
-               sp->psc_smbtxrx = data;
-               au_sync();
+               WR(adap, PSC_SMBTXRX, data);
                if (wait_ack(adap))
                        return -EIO;
                i++;
        }
 
-       /* The last byte has to indicate transfer done.
-       */
+       /* The last byte has to indicate transfer done. */
        data = buf[i];
        data |= PSC_SMBTXRX_STP;
-       sp->psc_smbtxrx = data;
-       au_sync();
+       WR(adap, PSC_SMBTXRX, data);
        if (wait_master_done(adap))
                return -EIO;
        return 0;
@@ -269,12 +228,10 @@ static int
 au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
        struct i2c_au1550_data *adap = i2c_adap->algo_data;
-       volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
        struct i2c_msg *p;
        int i, err = 0;
 
-       sp->psc_ctrl = PSC_CTRL_ENABLE;
-       au_sync();
+       WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
 
        for (i = 0; !err && i < num; i++) {
                p = &msgs[i];
@@ -293,14 +250,12 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
        if (err == 0)
                err = num;
 
-       sp->psc_ctrl = PSC_CTRL_SUSPEND;
-       au_sync();
+       WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
 
        return err;
 }
 
-static u32
-au1550_func(struct i2c_adapter *adap)
+static u32 au1550_func(struct i2c_adapter *adap)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
@@ -312,57 +267,45 @@ static const struct i2c_algorithm au1550_algo = {
 
 static void i2c_au1550_setup(struct i2c_au1550_data *priv)
 {
-       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-       u32 stat;
-
-       sp->psc_ctrl = PSC_CTRL_DISABLE;
-       au_sync();
-       sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
-       sp->psc_smbcfg = 0;
-       au_sync();
-       sp->psc_ctrl = PSC_CTRL_ENABLE;
-       au_sync();
-       do {
-               stat = sp->psc_smbstat;
-               au_sync();
-       } while ((stat & PSC_SMBSTAT_SR) == 0);
+       unsigned long cfg;
 
-       sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
-                               PSC_SMBCFG_DD_DISABLE);
+       WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
+       WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
+       WR(priv, PSC_SMBCFG, 0);
+       WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
+       while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+               cpu_relax();
+
+       cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
+       WR(priv, PSC_SMBCFG, cfg);
 
        /* Divide by 8 to get a 6.25 MHz clock.  The later protocol
         * timings are based on this clock.
         */
-       sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
-       sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
-       au_sync();
+       cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
+       WR(priv, PSC_SMBCFG, cfg);
+       WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
 
        /* Set the protocol timer values.  See Table 71 in the
         * Au1550 Data Book for standard timing values.
         */
-       sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
+       WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
                PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
                PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
-               PSC_SMBTMR_SET_CH(15);
-       au_sync();
+               PSC_SMBTMR_SET_CH(15));
 
-       sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
-       do {
-               stat = sp->psc_smbstat;
-               au_sync();
-       } while ((stat & PSC_SMBSTAT_SR) == 0);
+       cfg |= PSC_SMBCFG_DE_ENABLE;
+       WR(priv, PSC_SMBCFG, cfg);
+       while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+               cpu_relax();
 
-       sp->psc_ctrl = PSC_CTRL_SUSPEND;
-       au_sync();
+       WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
 }
 
 static void i2c_au1550_disable(struct i2c_au1550_data *priv)
 {
-       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-
-       sp->psc_smbcfg = 0;
-       sp->psc_ctrl = PSC_CTRL_DISABLE;
-       au_sync();
+       WR(priv, PSC_SMBCFG, 0);
+       WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
 }
 
 /*
@@ -396,9 +339,12 @@ i2c_au1550_probe(struct platform_device *pdev)
                goto out_mem;
        }
 
-       priv->psc_base = CKSEG1ADDR(r->start);
+       priv->psc_base = ioremap(r->start, resource_size(r));
+       if (!priv->psc_base) {
+               ret = -EIO;
+               goto out_map;
+       }
        priv->xfer_timeout = 200;
-       priv->ack_timeout = 200;
 
        priv->adap.nr = pdev->id;
        priv->adap.algo = &au1550_algo;
@@ -406,8 +352,7 @@ i2c_au1550_probe(struct platform_device *pdev)
        priv->adap.dev.parent = &pdev->dev;
        strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
 
-       /* Now, set up the PSC for SMBus PIO mode.
-       */
+       /* Now, set up the PSC for SMBus PIO mode. */
        i2c_au1550_setup(priv);
 
        ret = i2c_add_numbered_adapter(&priv->adap);
@@ -417,7 +362,8 @@ i2c_au1550_probe(struct platform_device *pdev)
        }
 
        i2c_au1550_disable(priv);
-
+       iounmap(priv->psc_base);
+out_map:
        release_resource(priv->ioarea);
        kfree(priv->ioarea);
 out_mem:
@@ -426,14 +372,14 @@ out:
        return ret;
 }
 
-static int __devexit
-i2c_au1550_remove(struct platform_device *pdev)
+static int __devexit i2c_au1550_remove(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
 
        platform_set_drvdata(pdev, NULL);
        i2c_del_adapter(&priv->adap);
        i2c_au1550_disable(priv);
+       iounmap(priv->psc_base);
        release_resource(priv->ioarea);
        kfree(priv->ioarea);
        kfree(priv);
@@ -441,49 +387,51 @@ i2c_au1550_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int
-i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+static int i2c_au1550_suspend(struct device *dev)
 {
-       struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+       struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
        i2c_au1550_disable(priv);
 
        return 0;
 }
 
-static int
-i2c_au1550_resume(struct platform_device *pdev)
+static int i2c_au1550_resume(struct device *dev)
 {
-       struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+       struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
        i2c_au1550_setup(priv);
 
        return 0;
 }
+
+static const struct dev_pm_ops i2c_au1550_pmops = {
+       .suspend        = i2c_au1550_suspend,
+       .resume         = i2c_au1550_resume,
+};
+
+#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
+
 #else
-#define i2c_au1550_suspend     NULL
-#define i2c_au1550_resume      NULL
+#define AU1XPSC_SMBUS_PMOPS NULL
 #endif
 
 static struct platform_driver au1xpsc_smbus_driver = {
        .driver = {
                .name   = "au1xpsc_smbus",
                .owner  = THIS_MODULE,
+               .pm     = AU1XPSC_SMBUS_PMOPS,
        },
        .probe          = i2c_au1550_probe,
        .remove         = __devexit_p(i2c_au1550_remove),
-       .suspend        = i2c_au1550_suspend,
-       .resume         = i2c_au1550_resume,
 };
 
-static int __init
-i2c_au1550_init(void)
+static int __init i2c_au1550_init(void)
 {
        return platform_driver_register(&au1xpsc_smbus_driver);
 }
 
-static void __exit
-i2c_au1550_exit(void)
+static void __exit i2c_au1550_exit(void)
 {
        platform_driver_unregister(&au1xpsc_smbus_driver);
 }
similarity index 65%
rename from drivers/i2c/busses/i2c-designware.c
rename to drivers/i2c/busses/i2c-designware-core.c
index 1b42b50..df87992 100644 (file)
  * ----------------------------------------------------------------------------
  *
  */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/clk.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/err.h>
+#include <linux/i2c.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "i2c-designware-core.h"
 
 /*
  * Registers offset
 #define DW_IC_STATUS           0x70
 #define DW_IC_TXFLR            0x74
 #define DW_IC_RXFLR            0x78
-#define DW_IC_COMP_PARAM_1     0xf4
 #define DW_IC_TX_ABRT_SOURCE   0x80
-
-#define DW_IC_CON_MASTER               0x1
-#define DW_IC_CON_SPEED_STD            0x2
-#define DW_IC_CON_SPEED_FAST           0x4
-#define DW_IC_CON_10BITADDR_MASTER     0x10
-#define DW_IC_CON_RESTART_EN           0x20
-#define DW_IC_CON_SLAVE_DISABLE                0x40
+#define DW_IC_COMP_PARAM_1     0xf4
+#define DW_IC_COMP_TYPE                0xfc
+#define DW_IC_COMP_TYPE_VALUE  0x44570140
 
 #define DW_IC_INTR_RX_UNDER    0x001
 #define DW_IC_INTR_RX_OVER     0x002
@@ -170,55 +162,23 @@ static char *abort_sources[] = {
                "lost arbitration",
 };
 
-/**
- * struct dw_i2c_dev - private i2c-designware data
- * @dev: driver model device node
- * @base: IO registers pointer
- * @cmd_complete: tx completion indicator
- * @lock: protect this struct and IO registers
- * @clk: input reference clock
- * @cmd_err: run time hadware error code
- * @msgs: points to an array of messages currently being transferred
- * @msgs_num: the number of elements in msgs
- * @msg_write_idx: the element index of the current tx message in the msgs
- *     array
- * @tx_buf_len: the length of the current tx buffer
- * @tx_buf: the current tx buffer
- * @msg_read_idx: the element index of the current rx message in the msgs
- *     array
- * @rx_buf_len: the length of the current rx buffer
- * @rx_buf: the current rx buffer
- * @msg_err: error status of the current transfer
- * @status: i2c master status, one of STATUS_*
- * @abort_source: copy of the TX_ABRT_SOURCE register
- * @irq: interrupt number for the i2c master
- * @adapter: i2c subsystem adapter node
- * @tx_fifo_depth: depth of the hardware tx fifo
- * @rx_fifo_depth: depth of the hardware rx fifo
- */
-struct dw_i2c_dev {
-       struct device           *dev;
-       void __iomem            *base;
-       struct completion       cmd_complete;
-       struct mutex            lock;
-       struct clk              *clk;
-       int                     cmd_err;
-       struct i2c_msg          *msgs;
-       int                     msgs_num;
-       int                     msg_write_idx;
-       u32                     tx_buf_len;
-       u8                      *tx_buf;
-       int                     msg_read_idx;
-       u32                     rx_buf_len;
-       u8                      *rx_buf;
-       int                     msg_err;
-       unsigned int            status;
-       u32                     abort_source;
-       int                     irq;
-       struct i2c_adapter      adapter;
-       unsigned int            tx_fifo_depth;
-       unsigned int            rx_fifo_depth;
-};
+u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+{
+       u32 value = readl(dev->base + offset);
+
+       if (dev->swab)
+               return swab32(value);
+       else
+               return value;
+}
+
+void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+{
+       if (dev->swab)
+               b = swab32(b);
+
+       writel(b, dev->base + offset);
+}
 
 static u32
 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
@@ -283,13 +243,29 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
  * This function is called during I2C init function, and in case of timeout at
  * run time.
  */
-static void i2c_dw_init(struct dw_i2c_dev *dev)
+int i2c_dw_init(struct dw_i2c_dev *dev)
 {
-       u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
-       u32 ic_con, hcnt, lcnt;
+       u32 input_clock_khz;
+       u32 hcnt, lcnt;
+       u32 reg;
+
+       input_clock_khz = dev->get_clk_rate_khz(dev);
+
+       /* Configure register endianess access */
+       reg = dw_readl(dev, DW_IC_COMP_TYPE);
+       if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
+               dev->swab = 1;
+               reg = DW_IC_COMP_TYPE_VALUE;
+       }
+
+       if (reg != DW_IC_COMP_TYPE_VALUE) {
+               dev_err(dev->dev, "Unknown Synopsys component type: "
+                       "0x%08x\n", reg);
+               return -ENODEV;
+       }
 
        /* Disable the adapter */
-       writel(0, dev->base + DW_IC_ENABLE);
+       dw_writel(dev, 0, DW_IC_ENABLE);
 
        /* set standard and fast speed deviders for high/low periods */
 
@@ -303,8 +279,8 @@ static void i2c_dw_init(struct dw_i2c_dev *dev)
                                47,     /* tLOW = 4.7 us */
                                3,      /* tf = 0.3 us */
                                0);     /* No offset */
-       writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
-       writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
+       dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
+       dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
        dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
        /* Fast-mode */
@@ -317,18 +293,17 @@ static void i2c_dw_init(struct dw_i2c_dev *dev)
                                13,     /* tLOW = 1.3 us */
                                3,      /* tf = 0.3 us */
                                0);     /* No offset */
-       writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
-       writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
+       dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
+       dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
        dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
        /* Configure Tx/Rx FIFO threshold levels */
-       writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
-       writel(0, dev->base + DW_IC_RX_TL);
+       dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+       dw_writel(dev, 0, DW_IC_RX_TL);
 
        /* configure the i2c master */
-       ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-               DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
-       writel(ic_con, dev->base + DW_IC_CON);
+       dw_writel(dev, dev->master_cfg , DW_IC_CON);
+       return 0;
 }
 
 /*
@@ -338,7 +313,7 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
 {
        int timeout = TIMEOUT;
 
-       while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+       while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
                if (timeout <= 0) {
                        dev_warn(dev->dev, "timeout waiting for bus ready\n");
                        return -ETIMEDOUT;
@@ -356,24 +331,24 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
        u32 ic_con;
 
        /* Disable the adapter */
-       writel(0, dev->base + DW_IC_ENABLE);
+       dw_writel(dev, 0, DW_IC_ENABLE);
 
        /* set the slave (target) address */
-       writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
+       dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
 
        /* if the slave address is ten bit address, enable 10BITADDR */
-       ic_con = readl(dev->base + DW_IC_CON);
+       ic_con = dw_readl(dev, DW_IC_CON);
        if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
                ic_con |= DW_IC_CON_10BITADDR_MASTER;
        else
                ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-       writel(ic_con, dev->base + DW_IC_CON);
+       dw_writel(dev, ic_con, DW_IC_CON);
 
        /* Enable the adapter */
-       writel(1, dev->base + DW_IC_ENABLE);
+       dw_writel(dev, 1, DW_IC_ENABLE);
 
        /* Enable interrupts */
-       writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
+       dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
 }
 
 /*
@@ -382,7 +357,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
  * messages into the tx buffer.  Even if the size of i2c_msg data is
  * longer than the size of the tx buffer, it handles everything.
  */
-static void
+void
 i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 {
        struct i2c_msg *msgs = dev->msgs;
@@ -420,15 +395,15 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
                        buf_len = msgs[dev->msg_write_idx].len;
                }
 
-               tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
-               rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
+               tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+               rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
 
                while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
                        if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
-                               writel(0x100, dev->base + DW_IC_DATA_CMD);
+                               dw_writel(dev, 0x100, DW_IC_DATA_CMD);
                                rx_limit--;
                        } else
-                               writel(*buf++, dev->base + DW_IC_DATA_CMD);
+                               dw_writel(dev, *buf++, DW_IC_DATA_CMD);
                        tx_limit--; buf_len--;
                }
 
@@ -453,7 +428,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
        if (dev->msg_err)
                intr_mask = 0;
 
-       writel(intr_mask, dev->base + DW_IC_INTR_MASK);
+       dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
 }
 
 static void
@@ -477,10 +452,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
                        buf = dev->rx_buf;
                }
 
-               rx_valid = readl(dev->base + DW_IC_RXFLR);
+               rx_valid = dw_readl(dev, DW_IC_RXFLR);
 
                for (; len > 0 && rx_valid > 0; len--, rx_valid--)
-                       *buf++ = readl(dev->base + DW_IC_DATA_CMD);
+                       *buf++ = dw_readl(dev, DW_IC_DATA_CMD);
 
                if (len > 0) {
                        dev->status |= STATUS_READ_IN_PROGRESS;
@@ -518,7 +493,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
 /*
  * Prepare controller for a transaction and call i2c_dw_xfer_msg
  */
-static int
+int
 i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 {
        struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
@@ -527,6 +502,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
 
        mutex_lock(&dev->lock);
+       pm_runtime_get_sync(dev->dev);
 
        INIT_COMPLETION(dev->cmd_complete);
        dev->msgs = msgs;
@@ -563,7 +539,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        /* no error */
        if (likely(!dev->cmd_err)) {
                /* Disable the adapter */
-               writel(0, dev->base + DW_IC_ENABLE);
+               dw_writel(dev, 0, DW_IC_ENABLE);
                ret = num;
                goto done;
        }
@@ -576,19 +552,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        ret = -EIO;
 
 done:
+       pm_runtime_put(dev->dev);
        mutex_unlock(&dev->lock);
 
        return ret;
 }
 
-static u32 i2c_dw_func(struct i2c_adapter *adap)
+u32 i2c_dw_func(struct i2c_adapter *adap)
 {
-       return  I2C_FUNC_I2C |
-               I2C_FUNC_10BIT_ADDR |
-               I2C_FUNC_SMBUS_BYTE |
-               I2C_FUNC_SMBUS_BYTE_DATA |
-               I2C_FUNC_SMBUS_WORD_DATA |
-               I2C_FUNC_SMBUS_I2C_BLOCK;
+       struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+       return dev->functionality;
 }
 
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
@@ -601,47 +574,47 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
         * in the IC_RAW_INTR_STAT register.
         *
         * That is,
-        *   stat = readl(IC_INTR_STAT);
+        *   stat = dw_readl(IC_INTR_STAT);
         * equals to,
-        *   stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
+        *   stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
         *
         * The raw version might be useful for debugging purposes.
         */
-       stat = readl(dev->base + DW_IC_INTR_STAT);
+       stat = dw_readl(dev, DW_IC_INTR_STAT);
 
        /*
         * Do not use the IC_CLR_INTR register to clear interrupts, or
         * you'll miss some interrupts, triggered during the period from
-        * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
+        * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
         *
         * Instead, use the separately-prepared IC_CLR_* registers.
         */
        if (stat & DW_IC_INTR_RX_UNDER)
-               readl(dev->base + DW_IC_CLR_RX_UNDER);
+               dw_readl(dev, DW_IC_CLR_RX_UNDER);
        if (stat & DW_IC_INTR_RX_OVER)
-               readl(dev->base + DW_IC_CLR_RX_OVER);
+               dw_readl(dev, DW_IC_CLR_RX_OVER);
        if (stat & DW_IC_INTR_TX_OVER)
-               readl(dev->base + DW_IC_CLR_TX_OVER);
+               dw_readl(dev, DW_IC_CLR_TX_OVER);
        if (stat & DW_IC_INTR_RD_REQ)
-               readl(dev->base + DW_IC_CLR_RD_REQ);
+               dw_readl(dev, DW_IC_CLR_RD_REQ);
        if (stat & DW_IC_INTR_TX_ABRT) {
                /*
                 * The IC_TX_ABRT_SOURCE register is cleared whenever
                 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
                 */
-               dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
-               readl(dev->base + DW_IC_CLR_TX_ABRT);
+               dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
+               dw_readl(dev, DW_IC_CLR_TX_ABRT);
        }
        if (stat & DW_IC_INTR_RX_DONE)
-               readl(dev->base + DW_IC_CLR_RX_DONE);
+               dw_readl(dev, DW_IC_CLR_RX_DONE);
        if (stat & DW_IC_INTR_ACTIVITY)
-               readl(dev->base + DW_IC_CLR_ACTIVITY);
+               dw_readl(dev, DW_IC_CLR_ACTIVITY);
        if (stat & DW_IC_INTR_STOP_DET)
-               readl(dev->base + DW_IC_CLR_STOP_DET);
+               dw_readl(dev, DW_IC_CLR_STOP_DET);
        if (stat & DW_IC_INTR_START_DET)
-               readl(dev->base + DW_IC_CLR_START_DET);
+               dw_readl(dev, DW_IC_CLR_START_DET);
        if (stat & DW_IC_INTR_GEN_CALL)
-               readl(dev->base + DW_IC_CLR_GEN_CALL);
+               dw_readl(dev, DW_IC_CLR_GEN_CALL);
 
        return stat;
 }
@@ -650,13 +623,19 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
  * Interrupt service routine. This gets called whenever an I2C interrupt
  * occurs.
  */
-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
 {
        struct dw_i2c_dev *dev = dev_id;
-       u32 stat;
+       u32 stat, enabled;
+
+       enabled = dw_readl(dev, DW_IC_ENABLE);
+       stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+       dev_dbg(dev->dev, "%s:  %s enabled= 0x%x stat=0x%x\n", __func__,
+               dev->adapter.name, enabled, stat);
+       if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
+               return IRQ_NONE;
 
        stat = i2c_dw_read_clear_intrbits(dev);
-       dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
 
        if (stat & DW_IC_INTR_TX_ABRT) {
                dev->cmd_err |= DW_IC_ERR_TX_ABRT;
@@ -666,7 +645,7 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
                 * Anytime TX_ABRT is set, the contents of the tx/rx
                 * buffers are flushed.  Make sure to skip them.
                 */
-               writel(0, dev->base + DW_IC_INTR_MASK);
+               dw_writel(dev, 0, DW_IC_INTR_MASK);
                goto tx_aborted;
        }
 
@@ -689,159 +668,38 @@ tx_aborted:
        return IRQ_HANDLED;
 }
 
-static struct i2c_algorithm i2c_dw_algo = {
-       .master_xfer    = i2c_dw_xfer,
-       .functionality  = i2c_dw_func,
-};
-
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
+void i2c_dw_enable(struct dw_i2c_dev *dev)
 {
-       struct dw_i2c_dev *dev;
-       struct i2c_adapter *adap;
-       struct resource *mem, *ioarea;
-       int irq, r;
-
-       /* NOTE: driver uses the static register mapping */
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "no mem resource?\n");
-               return -EINVAL;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "no irq resource?\n");
-               return irq; /* -ENXIO */
-       }
-
-       ioarea = request_mem_region(mem->start, resource_size(mem),
-                       pdev->name);
-       if (!ioarea) {
-               dev_err(&pdev->dev, "I2C region already claimed\n");
-               return -EBUSY;
-       }
-
-       dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
-       if (!dev) {
-               r = -ENOMEM;
-               goto err_release_region;
-       }
-
-       init_completion(&dev->cmd_complete);
-       mutex_init(&dev->lock);
-       dev->dev = get_device(&pdev->dev);
-       dev->irq = irq;
-       platform_set_drvdata(pdev, dev);
-
-       dev->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(dev->clk)) {
-               r = -ENODEV;
-               goto err_free_mem;
-       }
-       clk_enable(dev->clk);
-
-       dev->base = ioremap(mem->start, resource_size(mem));
-       if (dev->base == NULL) {
-               dev_err(&pdev->dev, "failure mapping io resources\n");
-               r = -EBUSY;
-               goto err_unuse_clocks;
-       }
-       {
-               u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
-
-               dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-               dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-       }
-       i2c_dw_init(dev);
-
-       writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
-       r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
-       if (r) {
-               dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
-               goto err_iounmap;
-       }
-
-       adap = &dev->adapter;
-       i2c_set_adapdata(adap, dev);
-       adap->owner = THIS_MODULE;
-       adap->class = I2C_CLASS_HWMON;
-       strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
-                       sizeof(adap->name));
-       adap->algo = &i2c_dw_algo;
-       adap->dev.parent = &pdev->dev;
-
-       adap->nr = pdev->id;
-       r = i2c_add_numbered_adapter(adap);
-       if (r) {
-               dev_err(&pdev->dev, "failure adding adapter\n");
-               goto err_free_irq;
-       }
-
-       return 0;
-
-err_free_irq:
-       free_irq(dev->irq, dev);
-err_iounmap:
-       iounmap(dev->base);
-err_unuse_clocks:
-       clk_disable(dev->clk);
-       clk_put(dev->clk);
-       dev->clk = NULL;
-err_free_mem:
-       platform_set_drvdata(pdev, NULL);
-       put_device(&pdev->dev);
-       kfree(dev);
-err_release_region:
-       release_mem_region(mem->start, resource_size(mem));
-
-       return r;
+       /* Enable the adapter */
+       dw_writel(dev, 1, DW_IC_ENABLE);
 }
 
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
+u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
 {
-       struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
-       struct resource *mem;
-
-       platform_set_drvdata(pdev, NULL);
-       i2c_del_adapter(&dev->adapter);
-       put_device(&pdev->dev);
-
-       clk_disable(dev->clk);
-       clk_put(dev->clk);
-       dev->clk = NULL;
-
-       writel(0, dev->base + DW_IC_ENABLE);
-       free_irq(dev->irq, dev);
-       kfree(dev);
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
-       return 0;
+       return dw_readl(dev, DW_IC_ENABLE);
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_designware");
+void i2c_dw_disable(struct dw_i2c_dev *dev)
+{
+       /* Disable controller */
+       dw_writel(dev, 0, DW_IC_ENABLE);
 
-static struct platform_driver dw_i2c_driver = {
-       .remove         = __devexit_p(dw_i2c_remove),
-       .driver         = {
-               .name   = "i2c_designware",
-               .owner  = THIS_MODULE,
-       },
-};
+       /* Disable all interupts */
+       dw_writel(dev, 0, DW_IC_INTR_MASK);
+       dw_readl(dev, DW_IC_CLR_INTR);
+}
 
-static int __init dw_i2c_init_driver(void)
+void i2c_dw_clear_int(struct dw_i2c_dev *dev)
 {
-       return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+       dw_readl(dev, DW_IC_CLR_INTR);
 }
-module_init(dw_i2c_init_driver);
 
-static void __exit dw_i2c_exit_driver(void)
+void i2c_dw_disable_int(struct dw_i2c_dev *dev)
 {
-       platform_driver_unregister(&dw_i2c_driver);
+       dw_writel(dev, 0, DW_IC_INTR_MASK);
 }
-module_exit(dw_i2c_exit_driver);
 
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
-MODULE_LICENSE("GPL");
+u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
+{
+       return dw_readl(dev, DW_IC_COMP_PARAM_1);
+}
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
new file mode 100644 (file)
index 0000000..02d1a2d
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#define DW_IC_CON_MASTER               0x1
+#define DW_IC_CON_SPEED_STD            0x2
+#define DW_IC_CON_SPEED_FAST           0x4
+#define DW_IC_CON_10BITADDR_MASTER     0x10
+#define DW_IC_CON_RESTART_EN           0x20
+#define DW_IC_CON_SLAVE_DISABLE                0x40
+
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ *     array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ *     array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+       struct device           *dev;
+       void __iomem            *base;
+       struct completion       cmd_complete;
+       struct mutex            lock;
+       struct clk              *clk;
+       u32                     (*get_clk_rate_khz) (struct dw_i2c_dev *dev);
+       struct dw_pci_controller *controller;
+       int                     cmd_err;
+       struct i2c_msg          *msgs;
+       int                     msgs_num;
+       int                     msg_write_idx;
+       u32                     tx_buf_len;
+       u8                      *tx_buf;
+       int                     msg_read_idx;
+       u32                     rx_buf_len;
+       u8                      *rx_buf;
+       int                     msg_err;
+       unsigned int            status;
+       u32                     abort_source;
+       int                     irq;
+       int                     swab;
+       struct i2c_adapter      adapter;
+       u32                     functionality;
+       u32                     master_cfg;
+       unsigned int            tx_fifo_depth;
+       unsigned int            rx_fifo_depth;
+};
+
+extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
+extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+extern int i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+               int num);
+extern u32 i2c_dw_func(struct i2c_adapter *adap);
+extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
+extern void i2c_dw_enable(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable(struct dw_i2c_dev *dev);
+extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
new file mode 100644 (file)
index 0000000..9e89e73
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ * Copyright (C) 2011 Intel corporation.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include "i2c-designware-core.h"
+
+#define DRIVER_NAME "i2c-designware-pci"
+
+enum dw_pci_ctl_id_t {
+       moorestown_0,
+       moorestown_1,
+       moorestown_2,
+
+       medfield_0,
+       medfield_1,
+       medfield_2,
+       medfield_3,
+       medfield_4,
+       medfield_5,
+};
+
+struct dw_pci_controller {
+       u32 bus_num;
+       u32 bus_cfg;
+       u32 tx_fifo_depth;
+       u32 rx_fifo_depth;
+       u32 clk_khz;
+};
+
+#define INTEL_MID_STD_CFG  (DW_IC_CON_MASTER |                 \
+                               DW_IC_CON_SLAVE_DISABLE |       \
+                               DW_IC_CON_RESTART_EN)
+
+static struct  dw_pci_controller  dw_pci_controllers[] = {
+       [moorestown_0] = {
+               .bus_num     = 0,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [moorestown_1] = {
+               .bus_num     = 1,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [moorestown_2] = {
+               .bus_num     = 2,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_0] = {
+               .bus_num     = 0,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_1] = {
+               .bus_num     = 1,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_2] = {
+               .bus_num     = 2,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_3] = {
+               .bus_num     = 3,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_4] = {
+               .bus_num     = 4,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+       [medfield_5] = {
+               .bus_num     = 5,
+               .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+               .tx_fifo_depth = 32,
+               .rx_fifo_depth = 32,
+               .clk_khz      = 25000,
+       },
+};
+static struct i2c_algorithm i2c_dw_algo = {
+       .master_xfer    = i2c_dw_xfer,
+       .functionality  = i2c_dw_func,
+};
+
+static int i2c_dw_pci_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+       struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+       int err;
+
+
+       i2c_dw_disable(i2c);
+
+       err = pci_save_state(pdev);
+       if (err) {
+               dev_err(&pdev->dev, "pci_save_state failed\n");
+               return err;
+       }
+
+       err = pci_set_power_state(pdev, PCI_D3hot);
+       if (err) {
+               dev_err(&pdev->dev, "pci_set_power_state failed\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int i2c_dw_pci_resume(struct device *dev)
+{
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+       struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+       int err;
+       u32 enabled;
+
+       enabled = i2c_dw_is_enabled(i2c);
+       if (enabled)
+               return 0;
+
+       err = pci_set_power_state(pdev, PCI_D0);
+       if (err) {
+               dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+               return err;
+       }
+
+       pci_restore_state(pdev);
+
+       i2c_dw_init(i2c);
+       i2c_dw_enable(i2c);
+       return 0;
+}
+
+static int i2c_dw_pci_runtime_idle(struct device *dev)
+{
+       int err = pm_schedule_suspend(dev, 500);
+       dev_dbg(dev, "runtime_idle called\n");
+
+       if (err != 0)
+               return 0;
+       return -EBUSY;
+}
+
+static const struct dev_pm_ops i2c_dw_pm_ops = {
+       .resume         = i2c_dw_pci_resume,
+       .suspend        = i2c_dw_pci_suspend,
+       SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume,
+                          i2c_dw_pci_runtime_idle)
+};
+
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+       return dev->controller->clk_khz;
+}
+
+static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
+const struct pci_device_id *id)
+{
+       struct dw_i2c_dev *dev;
+       struct i2c_adapter *adap;
+       unsigned long start, len;
+       void __iomem *base;
+       int r;
+       struct  dw_pci_controller *controller;
+
+       if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+               printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+                       id->driver_data);
+               return -EINVAL;
+       }
+
+       controller = &dw_pci_controllers[id->driver_data];
+
+       r = pci_enable_device(pdev);
+       if (r) {
+               dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
+                       r);
+               goto exit;
+       }
+
+       /* Determine the address of the I2C area */
+       start = pci_resource_start(pdev, 0);
+       len = pci_resource_len(pdev, 0);
+       if (!start || len == 0) {
+               dev_err(&pdev->dev, "base address not set\n");
+               r = -ENODEV;
+               goto exit;
+       }
+
+       r = pci_request_region(pdev, 0, DRIVER_NAME);
+       if (r) {
+               dev_err(&pdev->dev, "failed to request I2C region "
+                       "0x%lx-0x%lx\n", start,
+                       (unsigned long)pci_resource_end(pdev, 0));
+               goto exit;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&pdev->dev, "I/O memory remapping failed\n");
+               r = -ENOMEM;
+               goto err_release_region;
+       }
+
+
+       dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+       if (!dev) {
+               r = -ENOMEM;
+               goto err_release_region;
+       }
+
+       init_completion(&dev->cmd_complete);
+       mutex_init(&dev->lock);
+       dev->clk = NULL;
+       dev->controller = controller;
+       dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+       dev->base = base;
+       dev->dev = get_device(&pdev->dev);
+       dev->functionality =
+               I2C_FUNC_I2C |
+               I2C_FUNC_SMBUS_BYTE |
+               I2C_FUNC_SMBUS_BYTE_DATA |
+               I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_I2C_BLOCK;
+       dev->master_cfg =  controller->bus_cfg;
+
+       pci_set_drvdata(pdev, dev);
+
+       dev->tx_fifo_depth = controller->tx_fifo_depth;
+       dev->rx_fifo_depth = controller->rx_fifo_depth;
+       r = i2c_dw_init(dev);
+       if (r)
+               goto err_iounmap;
+
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = 0;
+       adap->algo = &i2c_dw_algo;
+       adap->dev.parent = &pdev->dev;
+       adap->nr = controller->bus_num;
+       snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d",
+               adap->nr);
+
+       r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
+       if (r) {
+               dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+               goto err_iounmap;
+       }
+
+       i2c_dw_disable_int(dev);
+       i2c_dw_clear_int(dev);
+       r = i2c_add_numbered_adapter(adap);
+       if (r) {
+               dev_err(&pdev->dev, "failure adding adapter\n");
+               goto err_free_irq;
+       }
+
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_allow(&pdev->dev);
+
+       return 0;
+
+err_free_irq:
+       free_irq(pdev->irq, dev);
+err_iounmap:
+       iounmap(dev->base);
+       pci_set_drvdata(pdev, NULL);
+       put_device(&pdev->dev);
+       kfree(dev);
+err_release_region:
+       pci_release_region(pdev, 0);
+exit:
+       return r;
+}
+
+static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
+{
+       struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+
+       i2c_dw_disable(dev);
+       pm_runtime_forbid(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
+
+       pci_set_drvdata(pdev, NULL);
+       i2c_del_adapter(&dev->adapter);
+       put_device(&pdev->dev);
+
+       free_irq(dev->irq, dev);
+       kfree(dev);
+       pci_release_region(pdev, 0);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("i2c_designware-pci");
+
+DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
+       /* Moorestown */
+       { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
+       { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
+       { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
+       /* Medfield */
+       { PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
+       { PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
+       { PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
+       { PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
+       { PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
+       { PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
+       { 0,}
+};
+MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
+
+static struct pci_driver dw_i2c_driver = {
+       .name           = DRIVER_NAME,
+       .id_table       = i2_designware_pci_ids,
+       .probe          = i2c_dw_pci_probe,
+       .remove         = __devexit_p(i2c_dw_pci_remove),
+       .driver         = {
+               .pm     = &i2c_dw_pm_ops,
+       },
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+       return  pci_register_driver(&dw_i2c_driver);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+       pci_unregister_driver(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
new file mode 100644 (file)
index 0000000..2d3657a
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+       .master_xfer    = i2c_dw_xfer,
+       .functionality  = i2c_dw_func,
+};
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+       return clk_get_rate(dev->clk)/1000;
+}
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+       struct dw_i2c_dev *dev;
+       struct i2c_adapter *adap;
+       struct resource *mem, *ioarea;
+       int irq, r;
+
+       /* NOTE: driver uses the static register mapping */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return irq; /* -ENXIO */
+       }
+
+       ioarea = request_mem_region(mem->start, resource_size(mem),
+                       pdev->name);
+       if (!ioarea) {
+               dev_err(&pdev->dev, "I2C region already claimed\n");
+               return -EBUSY;
+       }
+
+       dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+       if (!dev) {
+               r = -ENOMEM;
+               goto err_release_region;
+       }
+
+       init_completion(&dev->cmd_complete);
+       mutex_init(&dev->lock);
+       dev->dev = get_device(&pdev->dev);
+       dev->irq = irq;
+       platform_set_drvdata(pdev, dev);
+
+       dev->clk = clk_get(&pdev->dev, NULL);
+       dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+
+       if (IS_ERR(dev->clk)) {
+               r = -ENODEV;
+               goto err_free_mem;
+       }
+       clk_enable(dev->clk);
+
+       dev->functionality =
+               I2C_FUNC_I2C |
+               I2C_FUNC_10BIT_ADDR |
+               I2C_FUNC_SMBUS_BYTE |
+               I2C_FUNC_SMBUS_BYTE_DATA |
+               I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_I2C_BLOCK;
+       dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+               DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+
+       dev->base = ioremap(mem->start, resource_size(mem));
+       if (dev->base == NULL) {
+               dev_err(&pdev->dev, "failure mapping io resources\n");
+               r = -EBUSY;
+               goto err_unuse_clocks;
+       }
+       {
+               u32 param1 = i2c_dw_read_comp_param(dev);
+
+               dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+               dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+       }
+       r = i2c_dw_init(dev);
+       if (r)
+               goto err_iounmap;
+
+       i2c_dw_disable_int(dev);
+       r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+       if (r) {
+               dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+               goto err_iounmap;
+       }
+
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_HWMON;
+       strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+                       sizeof(adap->name));
+       adap->algo = &i2c_dw_algo;
+       adap->dev.parent = &pdev->dev;
+
+       adap->nr = pdev->id;
+       r = i2c_add_numbered_adapter(adap);
+       if (r) {
+               dev_err(&pdev->dev, "failure adding adapter\n");
+               goto err_free_irq;
+       }
+
+       return 0;
+
+err_free_irq:
+       free_irq(dev->irq, dev);
+err_iounmap:
+       iounmap(dev->base);
+err_unuse_clocks:
+       clk_disable(dev->clk);
+       clk_put(dev->clk);
+       dev->clk = NULL;
+err_free_mem:
+       platform_set_drvdata(pdev, NULL);
+       put_device(&pdev->dev);
+       kfree(dev);
+err_release_region:
+       release_mem_region(mem->start, resource_size(mem));
+
+       return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+       struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+       struct resource *mem;
+
+       platform_set_drvdata(pdev, NULL);
+       i2c_del_adapter(&dev->adapter);
+       put_device(&pdev->dev);
+
+       clk_disable(dev->clk);
+       clk_put(dev->clk);
+       dev->clk = NULL;
+
+       i2c_dw_disable(dev);
+       free_irq(dev->irq, dev);
+       kfree(dev);
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, resource_size(mem));
+       return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+       .remove         = __devexit_p(dw_i2c_remove),
+       .driver         = {
+               .name   = "i2c_designware",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+       return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+       platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
index ce1a32b..8cebef4 100644 (file)
@@ -64,6 +64,7 @@
 #define TEN_BIT_ADDR_DEFAULT   0xF000
 #define TEN_BIT_ADDR_MASK      0xF0
 #define PCH_START              0x0020
+#define PCH_RESTART            0x0004
 #define PCH_ESR_START          0x0001
 #define PCH_BUFF_START         0x1
 #define PCH_REPSTART           0x0004
@@ -273,23 +274,24 @@ static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
                                     s32 timeout)
 {
        void __iomem *p = adap->pch_base_address;
+       ktime_t ns_val;
+
+       if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+               return 0;
 
        /* MAX timeout value is timeout*1000*1000nsec */
-       ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+       ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
        do {
-               if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
-                       break;
                msleep(20);
+               if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+                       return 0;
        } while (ktime_lt(ktime_get(), ns_val));
 
        pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+       pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+       pch_i2c_init(adap);
 
-       if (timeout == 0) {
-               pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
-               return -ETIME;
-       }
-
-       return 0;
+       return -ETIME;
 }
 
 /**
@@ -311,21 +313,19 @@ static void pch_i2c_start(struct i2c_algo_pch_data *adap)
  */
 static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
 {
-       s32 ret;
+       long ret;
        ret = wait_event_timeout(pch_event,
                        (adap->pch_event_flag != 0), msecs_to_jiffies(50));
-       if (ret < 0) {
-               pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
-               return ret;
-       }
 
        if (ret == 0) {
                pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
+               adap->pch_event_flag = 0;
                return -ETIMEDOUT;
        }
 
        if (adap->pch_event_flag & I2C_ERROR_MASK) {
                pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
+               adap->pch_event_flag = 0;
                return -EIO;
        }
 
@@ -394,6 +394,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
        u32 addr_2_msb;
        u32 addr_8_lsb;
        s32 wrcount;
+       s32 rtn;
        void __iomem *p = adap->pch_base_address;
 
        length = msgs->len;
@@ -412,15 +413,29 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
        }
 
        if (msgs->flags & I2C_M_TEN) {
-               addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
+               addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
                iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
                if (first)
                        pch_i2c_start(adap);
-               if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
-                   pch_i2c_getack(adap) == 0) {
+
+               rtn = pch_i2c_wait_for_xfer_complete(adap);
+               if (rtn == 0) {
+                       if (pch_i2c_getack(adap)) {
+                               pch_dbg(adap, "Receive NACK for slave address"
+                                       "setting\n");
+                               return -EIO;
+                       }
                        addr_8_lsb = (addr & I2C_ADDR_MSK);
                        iowrite32(addr_8_lsb, p + PCH_I2CDR);
-               } else {
+               } else if (rtn == -EIO) { /* Arbitration Lost */
+                       pch_err(adap, "Lost Arbitration\n");
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMAL_BIT);
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMIF_BIT);
+                       pch_i2c_init(adap);
+                       return -EAGAIN;
+               } else { /* wait-event timeout */
                        pch_i2c_stop(adap);
                        return -ETIME;
                }
@@ -431,30 +446,51 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
                        pch_i2c_start(adap);
        }
 
-       if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-           (pch_i2c_getack(adap) == 0)) {
-               for (wrcount = 0; wrcount < length; ++wrcount) {
-                       /* write buffer value to I2C data register */
-                       iowrite32(buf[wrcount], p + PCH_I2CDR);
-                       pch_dbg(adap, "writing %x to Data register\n",
-                               buf[wrcount]);
+       rtn = pch_i2c_wait_for_xfer_complete(adap);
+       if (rtn == 0) {
+               if (pch_i2c_getack(adap)) {
+                       pch_dbg(adap, "Receive NACK for slave address"
+                               "setting\n");
+                       return -EIO;
+               }
+       } else if (rtn == -EIO) { /* Arbitration Lost */
+               pch_err(adap, "Lost Arbitration\n");
+               pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+               pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+               pch_i2c_init(adap);
+               return -EAGAIN;
+       } else { /* wait-event timeout */
+               pch_i2c_stop(adap);
+               return -ETIME;
+       }
 
-                       if (pch_i2c_wait_for_xfer_complete(adap) != 0)
-                               return -ETIME;
+       for (wrcount = 0; wrcount < length; ++wrcount) {
+               /* write buffer value to I2C data register */
+               iowrite32(buf[wrcount], p + PCH_I2CDR);
+               pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
 
-                       if (pch_i2c_getack(adap))
+               rtn = pch_i2c_wait_for_xfer_complete(adap);
+               if (rtn == 0) {
+                       if (pch_i2c_getack(adap)) {
+                               pch_dbg(adap, "Receive NACK for slave address"
+                                       "setting\n");
                                return -EIO;
+                       }
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMCF_BIT);
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMIF_BIT);
+               } else { /* wait-event timeout */
+                       pch_i2c_stop(adap);
+                       return -ETIME;
                }
+       }
 
-               /* check if this is the last message */
-               if (last)
-                       pch_i2c_stop(adap);
-               else
-                       pch_i2c_repstart(adap);
-       } else {
+       /* check if this is the last message */
+       if (last)
                pch_i2c_stop(adap);
-               return -EIO;
-       }
+       else
+               pch_i2c_repstart(adap);
 
        pch_dbg(adap, "return=%d\n", wrcount);
 
@@ -483,6 +519,19 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
        pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK);
 }
 
+/**
+ * pch_i2c_restart() - Generate I2C restart condition in normal mode.
+ * @adap:      Pointer to struct i2c_algo_pch_data.
+ *
+ * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
+ */
+static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
+{
+       void __iomem *p = adap->pch_base_address;
+       pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+       pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
+}
+
 /**
  * pch_i2c_readbytes() - read data  from I2C bus in normal mode.
  * @i2c_adap:  Pointer to the struct i2c_adapter.
@@ -500,7 +549,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
        u32 length;
        u32 addr;
        u32 addr_2_msb;
+       u32 addr_8_lsb;
        void __iomem *p = adap->pch_base_address;
+       s32 rtn;
 
        length = msgs->len;
        buf = msgs->buf;
@@ -515,9 +566,55 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
        }
 
        if (msgs->flags & I2C_M_TEN) {
-               addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+               addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
                iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
+               if (first)
+                       pch_i2c_start(adap);
 
+               rtn = pch_i2c_wait_for_xfer_complete(adap);
+               if (rtn == 0) {
+                       if (pch_i2c_getack(adap)) {
+                               pch_dbg(adap, "Receive NACK for slave address"
+                                       "setting\n");
+                               return -EIO;
+                       }
+                       addr_8_lsb = (addr & I2C_ADDR_MSK);
+                       iowrite32(addr_8_lsb, p + PCH_I2CDR);
+               } else if (rtn == -EIO) { /* Arbitration Lost */
+                       pch_err(adap, "Lost Arbitration\n");
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMAL_BIT);
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMIF_BIT);
+                       pch_i2c_init(adap);
+                       return -EAGAIN;
+               } else { /* wait-event timeout */
+                       pch_i2c_stop(adap);
+                       return -ETIME;
+               }
+               pch_i2c_restart(adap);
+               rtn = pch_i2c_wait_for_xfer_complete(adap);
+               if (rtn == 0) {
+                       if (pch_i2c_getack(adap)) {
+                               pch_dbg(adap, "Receive NACK for slave address"
+                                       "setting\n");
+                               return -EIO;
+                       }
+                       addr_2_msb |= I2C_RD;
+                       iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
+                                 p + PCH_I2CDR);
+               } else if (rtn == -EIO) { /* Arbitration Lost */
+                       pch_err(adap, "Lost Arbitration\n");
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMAL_BIT);
+                       pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+                                  I2CMIF_BIT);
+                       pch_i2c_init(adap);
+                       return -EAGAIN;
+               } else { /* wait-event timeout */
+                       pch_i2c_stop(adap);
+                       return -ETIME;
+               }
        } else {
                /* 7 address bits + R/W bit */
                addr = (((addr) << 1) | (I2C_RD));
@@ -528,56 +625,81 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
        if (first)
                pch_i2c_start(adap);
 
-       if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-           (pch_i2c_getack(adap) == 0)) {
-               pch_dbg(adap, "return %d\n", 0);
+       rtn = pch_i2c_wait_for_xfer_complete(adap);
+       if (rtn == 0) {
+               if (pch_i2c_getack(adap)) {
+                       pch_dbg(adap, "Receive NACK for slave address"
+                               "setting\n");
+                       return -EIO;
+               }
+       } else if (rtn == -EIO) { /* Arbitration Lost */
+               pch_err(adap, "Lost Arbitration\n");
+               pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+               pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+               pch_i2c_init(adap);
+               return -EAGAIN;
+       } else { /* wait-event timeout */
+               pch_i2c_stop(adap);
+               return -ETIME;
+       }
 
-               if (length == 0) {
-                       pch_i2c_stop(adap);
-                       ioread32(p + PCH_I2CDR); /* Dummy read needs */
+       if (length == 0) {
+               pch_i2c_stop(adap);
+               ioread32(p + PCH_I2CDR); /* Dummy read needs */
 
-                       count = length;
-               } else {
-                       int read_index;
-                       int loop;
-                       pch_i2c_sendack(adap);
+               count = length;
+       } else {
+               int read_index;
+               int loop;
+               pch_i2c_sendack(adap);
 
-                       /* Dummy read */
-                       for (loop = 1, read_index = 0; loop < length; loop++) {
-                               buf[read_index] = ioread32(p + PCH_I2CDR);
+               /* Dummy read */
+               for (loop = 1, read_index = 0; loop < length; loop++) {
+                       buf[read_index] = ioread32(p + PCH_I2CDR);
 
-                               if (loop != 1)
-                                       read_index++;
+                       if (loop != 1)
+                               read_index++;
 
-                               if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
-                                       pch_i2c_stop(adap);
-                                       return -ETIME;
+                       rtn = pch_i2c_wait_for_xfer_complete(adap);
+                       if (rtn == 0) {
+                               if (pch_i2c_getack(adap)) {
+                                       pch_dbg(adap, "Receive NACK for slave"
+                                               "address setting\n");
+                                       return -EIO;
                                }
-                       }       /* end for */
+                       } else { /* wait-event timeout */
+                               pch_i2c_stop(adap);
+                               return -ETIME;
+                       }
 
-                       pch_i2c_sendnack(adap);
+               }       /* end for */
 
-                       buf[read_index] = ioread32(p + PCH_I2CDR);
+               pch_i2c_sendnack(adap);
 
-                       if (length != 1)
-                               read_index++;
+               buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
 
-                       if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
-                               if (last)
-                                       pch_i2c_stop(adap);
-                               else
-                                       pch_i2c_repstart(adap);
+               if (length != 1)
+                       read_index++;
 
-                               buf[read_index++] = ioread32(p + PCH_I2CDR);
-                               count = read_index;
-                       } else {
-                               count = -ETIME;
+               rtn = pch_i2c_wait_for_xfer_complete(adap);
+               if (rtn == 0) {
+                       if (pch_i2c_getack(adap)) {
+                               pch_dbg(adap, "Receive NACK for slave"
+                                       "address setting\n");
+                               return -EIO;
                        }
-
+               } else { /* wait-event timeout */
+                       pch_i2c_stop(adap);
+                       return -ETIME;
                }
-       } else {
-               count = -ETIME;
-               pch_i2c_stop(adap);
+
+               if (last)
+                       pch_i2c_stop(adap);
+               else
+                       pch_i2c_repstart(adap);
+
+               buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
+               count = read_index;
        }
 
        return count;
index 4c2a62b..58832e5 100644 (file)
@@ -48,6 +48,9 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
@@ -125,6 +128,11 @@ struct imx_i2c_struct {
        unsigned int            ifdr; /* IMX_I2C_IFDR */
 };
 
+static const struct of_device_id i2c_imx_dt_ids[] = {
+       { .compatible = "fsl,imx1-i2c", },
+       { /* sentinel */ }
+};
+
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
@@ -466,10 +474,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 {
        struct imx_i2c_struct *i2c_imx;
        struct resource *res;
-       struct imxi2c_platform_data *pdata;
+       struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
        void __iomem *base;
        resource_size_t res_size;
-       int irq;
+       int irq, bitrate;
        int ret;
 
        dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -485,19 +493,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
                return -ENOENT;
        }
 
-       pdata = pdev->dev.platform_data;
-
-       if (pdata && pdata->init) {
-               ret = pdata->init(&pdev->dev);
-               if (ret)
-                       return ret;
-       }
-
        res_size = resource_size(res);
 
        if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
-               ret = -EBUSY;
-               goto fail0;
+               dev_err(&pdev->dev, "request_mem_region failed\n");
+               return -EBUSY;
        }
 
        base = ioremap(res->start, res_size);
@@ -520,6 +520,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
        i2c_imx->adapter.algo           = &i2c_imx_algo;
        i2c_imx->adapter.dev.parent     = &pdev->dev;
        i2c_imx->adapter.nr             = pdev->id;
+       i2c_imx->adapter.dev.of_node    = pdev->dev.of_node;
        i2c_imx->irq                    = irq;
        i2c_imx->base                   = base;
        i2c_imx->res                    = res;
@@ -546,10 +547,12 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
        i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
 
        /* Set up clock divider */
-       if (pdata && pdata->bitrate)
-               i2c_imx_set_clk(i2c_imx, pdata->bitrate);
-       else
-               i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);
+       bitrate = IMX_I2C_BIT_RATE;
+       ret = of_property_read_u32(pdev->dev.of_node,
+                                  "clock-frequency", &bitrate);
+       if (ret < 0 && pdata && pdata->bitrate)
+               bitrate = pdata->bitrate;
+       i2c_imx_set_clk(i2c_imx, bitrate);
 
        /* Set up chip registers to defaults */
        writeb(0, i2c_imx->base + IMX_I2C_I2CR);
@@ -562,6 +565,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
                goto fail5;
        }
 
+       of_i2c_register_devices(&i2c_imx->adapter);
+
        /* Set up platform driver data */
        platform_set_drvdata(pdev, i2c_imx);
 
@@ -586,16 +591,12 @@ fail2:
        iounmap(base);
 fail1:
        release_mem_region(res->start, resource_size(res));
-fail0:
-       if (pdata && pdata->exit)
-               pdata->exit(&pdev->dev);
        return ret; /* Return error number */
 }
 
 static int __exit i2c_imx_remove(struct platform_device *pdev)
 {
        struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
-       struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 
        /* remove adapter */
        dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -611,10 +612,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
        writeb(0, i2c_imx->base + IMX_I2C_I2CR);
        writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 
-       /* Shut down hardware */
-       if (pdata && pdata->exit)
-               pdata->exit(&pdev->dev);
-
        clk_put(i2c_imx->clk);
 
        iounmap(i2c_imx->base);
@@ -628,6 +625,7 @@ static struct platform_driver i2c_imx_driver = {
        .driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = i2c_imx_dt_ids,
        }
 };