Convert omap24xx_i2c driver to DM

Signed-off-by: Christophe Ricard <christophe-h.ric...@st.com>
---

 drivers/i2c/Kconfig        |   8 ++
 drivers/i2c/omap24xx_i2c.c | 280 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 277 insertions(+), 11 deletions(-)

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 14adda2..3498af1 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -58,6 +58,14 @@ config DM_I2C_GPIO
          bindings are supported.
          Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
 
+config SYS_I2C_OMAP24XX
+       bool "Texas Instrument OMAP I2C driver"
+       depends on DM_I2C
+       help
+         Enable support for the I2C interface on the Texas Instruments
+         OMAP1/2 family of processors. Like OMAP1510/1610/1710/5912 and 
OMAP242x.
+         For details see http://www.ti.com/omap.
+
 config SYS_I2C_ROCKCHIP
        bool "Rockchip I2C driver"
        depends on DM_I2C
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 79a5c94..f3a4d96 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -36,13 +36,18 @@
  * Copyright (c) 2014 Hannes Schmelzer <oe5...@oevsv.at>, B&R
  * - Added support for set_speed
  *
+ * Copyright (c) 2016 Christophe Ricard <christophe.ric...@gmail.com>
+ * - Added support for DM_I2C
+ *
  */
 
 #include <common.h>
 #include <i2c.h>
+#include <dm.h>
 
 #include <asm/arch/i2c.h>
 #include <asm/io.h>
+#include <asm/errno.h>
 
 #include "omap24xx_i2c.h"
 
@@ -53,10 +58,26 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Absolutely safe for status update at 100 kHz I2C: */
 #define I2C_WAIT       200
 
+#ifdef CONFIG_DM_I2C
+struct omap24_i2c_bus {
+       int bus_num;
+       int waitdelay;
+       unsigned clock_frequency;
+       struct i2c *i2c_base;
+};
+#endif
+
+#ifdef CONFIG_SYS_I2C
 static int wait_for_bb(struct i2c_adapter *adap);
 static struct i2c *omap24_get_base(struct i2c_adapter *adap);
 static u16 wait_for_event(struct i2c_adapter *adap);
 static void flush_fifo(struct i2c_adapter *adap);
+#else
+static int wait_for_bb(struct udevice *dev);
+static u16 wait_for_event(struct udevice *dev);
+static void flush_fifo(struct udevice *dev);
+#endif
+
 static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
 {
        unsigned int sampleclk, prescaler;
@@ -90,13 +111,27 @@ static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint 
speed)
        }
        return -1;
 }
+
+#ifdef CONFIG_SYS_I2C
 static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
+#else
+static int omap24_i2c_setspeed(struct udevice *adap, unsigned int speed)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        int psc, fsscll = 0, fssclh = 0;
        int hsscll = 0, hssclh = 0;
        u32 scll = 0, sclh = 0;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        if (speed >= OMAP_I2C_HIGH_SPEED) {
                /* High speed */
                psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
@@ -142,8 +177,14 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, 
uint speed)
                }
        }
 
+#ifdef CONFIG_SYS_I2C
        adap->speed     = speed;
        adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
+#else
+       i2c_bus->clock_frequency = speed;
+       i2c_bus->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods 
*/
+#endif
+
        writew(0, &i2c_base->con);
        writew(psc, &i2c_base->psc);
        writew(scll, &i2c_base->scll);
@@ -154,13 +195,26 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, 
uint speed)
        return 0;
 }
 
+#ifdef CONFIG_SYS_I2C
 static void omap24_i2c_deblock(struct i2c_adapter *adap)
+#else
+static int omap24_i2c_deblock(struct udevice *adap)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        int i;
        u16 systest;
        u16 orgsystest;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        /* set test mode ST_EN = 1 */
        orgsystest = readw(&i2c_base->systest);
        systest = orgsystest;
@@ -198,14 +252,31 @@ static void omap24_i2c_deblock(struct i2c_adapter *adap)
 
        /* restore original mode */
        writew(orgsystest, &i2c_base->systest);
+
+#ifdef CONFIG_DM_I2C
+       return 0;
+#endif
 }
 
+#ifdef CONFIG_SYS_I2C
 static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+#else
+static void omap24_i2c_init(struct udevice *adap, int speed, int slaveadd)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        int timeout = I2C_TIMEOUT;
        int deblock = 1;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
 retry:
        if (readw(&i2c_base->con) & I2C_CON_EN) {
                writew(0, &i2c_base->con);
@@ -253,11 +324,24 @@ retry:
                }
 }
 
+#ifdef CONFIG_SYS_I2C
 static void flush_fifo(struct i2c_adapter *adap)
+#else
+static void flush_fifo(struct udevice *adap)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        u16 stat;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        /*
         * note: if you try and read data when its not there or ready
         * you get a bus error
@@ -277,12 +361,25 @@ static void flush_fifo(struct i2c_adapter *adap)
  * i2c_probe: Use write access. Allows to identify addresses that are
  *            write-only (like the config register of dual-port EEPROMs)
  */
+#ifdef CONFIG_SYS_I2C
 static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
+#else
+static int omap24_i2c_probe(struct udevice *adap, uint chip, uint chip_flags)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        u16 status;
        int res = 1; /* default = fail */
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        if (chip == readw(&i2c_base->oa))
                return res;
 
@@ -305,17 +402,26 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, 
uchar chip)
                 * silent exit is desired upon unconfigured bus, remove the
                 * following 'if' section:
                 */
-               if (status == I2C_STAT_XRDY)
+               if (status == I2C_STAT_XRDY) {
+#ifdef CONFIG_SYS_I2C
                        printf("i2c_probe: pads on bus %d probably not 
configured (status=0x%x)\n",
                               adap->hwadapnr, status);
-
+#else
+                       printf("i2c_probe: pads on bus %d probably not 
configured (status=0x%x)\n",
+                              i2c_bus->bus_num, status);
+#endif
+               }
                goto pr_exit;
        }
 
        /* Check for ACK (!NAK) */
        if (!(status & I2C_STAT_NACK)) {
                res = 0;                                /* Device found */
+#ifdef CONFIG_SYS_I2C
                udelay(adap->waitdelay);/* Required by AM335X in SPL */
+#else
+               udelay(i2c_bus->waitdelay);
+#endif
                /* Abort transfer (force idle state) */
                writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
                udelay(1000);
@@ -341,13 +447,27 @@ pr_exit:
  *           or that do not need a register address at all (such as some clock
  *           distributors).
  */
+#ifdef CONFIG_SYS_I2C
 static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
                           int alen, uchar *buffer, int len)
+#else
+static int omap24_i2c_read(struct udevice *adap, uchar chip, uint addr,
+                          int alen, uchar *buffer, int len)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        int i2c_error = 0;
        u16 status;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        if (alen < 0) {
                puts("I2C read: addr len < 0\n");
                return 1;
@@ -397,8 +517,13 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar 
chip, uint addr,
                        /* Try to identify bus that is not padconf'd for I2C */
                        if (status == I2C_STAT_XRDY) {
                                i2c_error = 2;
+#ifdef CONFIG_SYS_I2C
                                printf("i2c_read (addr phase): pads on bus %d 
probably not configured (status=0x%x)\n",
                                       adap->hwadapnr, status);
+#else
+                               printf("i2c_read (addr phase): pads on bus %d 
probably not configured (status=0x%x)\n",
+                                      i2c_bus->bus_num, status);
+#endif
                                goto rd_exit;
                        }
                        if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -441,8 +566,13 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar 
chip, uint addr,
                 */
                if (status == I2C_STAT_XRDY) {
                        i2c_error = 2;
+#ifdef CONFIG_SYS_I2C
                        printf("i2c_read (data phase): pads on bus %d probably 
not configured (status=0x%x)\n",
                               adap->hwadapnr, status);
+#else
+                       printf("i2c_read (data phase): pads on bus %d probably 
not configured (status=0x%x)\n",
+                              i2c_bus->bus_num, status);
+#endif
                        goto rd_exit;
                }
                if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -466,15 +596,29 @@ rd_exit:
 }
 
 /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */
+#ifdef CONFIG_SYS_I2C
 static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
                            int alen, uchar *buffer, int len)
+#else
+static int omap24_i2c_write(struct udevice *adap, uchar chip, uint addr,
+                           int alen, uchar *buffer, int len)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        int i;
        u16 status;
        int i2c_error = 0;
        int timeout = I2C_TIMEOUT;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        if (alen < 0) {
                puts("I2C write: addr len < 0\n");
                return 1;
@@ -519,8 +663,13 @@ static int omap24_i2c_write(struct i2c_adapter *adap, 
uchar chip, uint addr,
                /* Try to identify bus that is not padconf'd for I2C */
                if (status == I2C_STAT_XRDY) {
                        i2c_error = 2;
+#ifdef CONFIG_SYS_I2C
                        printf("i2c_write: pads on bus %d probably not 
configured (status=0x%x)\n",
                               adap->hwadapnr, status);
+#else
+                       printf("i2c_write: pads on bus %d probably not 
configured (status=0x%x)\n",
+                              i2c_bus->bus_num, status);
+#endif
                        goto wr_exit;
                }
                if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -579,12 +728,25 @@ wr_exit:
  * Wait for the bus to be free by checking the Bus Busy (BB)
  * bit to become clear
  */
+#ifdef CONFIG_SYS_I2C
 static int wait_for_bb(struct i2c_adapter *adap)
+#else
+static int wait_for_bb(struct udevice *adap)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        int timeout = I2C_TIMEOUT;
        u16 stat;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        writew(0xFFFF, &i2c_base->stat);        /* clear current interrupts...*/
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
        while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
@@ -594,7 +756,11 @@ static int wait_for_bb(struct i2c_adapter *adap)
                I2C_STAT_BB) && timeout--) {
 #endif
                writew(stat, &i2c_base->stat);
+#ifdef CONFIG_SYS_I2C
                udelay(adap->waitdelay);
+#else
+               udelay(i2c_bus->waitdelay);
+#endif
        }
 
        if (timeout <= 0) {
@@ -610,14 +776,31 @@ static int wait_for_bb(struct i2c_adapter *adap)
  * Wait for the I2C controller to complete current action
  * and update status
  */
+#ifdef CONFIG_SYS_I2C
 static u16 wait_for_event(struct i2c_adapter *adap)
+#else
+static u16 wait_for_event(struct udevice *adap)
+#endif
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
+       struct i2c *i2c_base;
        u16 status;
        int timeout = I2C_TIMEOUT;
 
+#ifdef CONFIG_SYS_I2C
+       i2c_base = omap24_get_base(adap);
+#else
+       struct omap24_i2c_bus *i2c_bus;
+
+       i2c_bus = dev_get_priv(adap);
+       i2c_base = i2c_bus->i2c_base;
+#endif
+
        do {
+#ifdef CONFIG_SYS_I2C
                udelay(adap->waitdelay);
+#else
+               udelay(i2c_bus->waitdelay);
+#endif
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
                status = readw(&i2c_base->stat);
 #else
@@ -636,8 +819,13 @@ static u16 wait_for_event(struct i2c_adapter *adap)
                 * If status is still 0 here, probably the bus pads have
                 * not been configured for I2C, and/or pull-ups are missing.
                 */
+#ifdef CONFIG_SYS_I2C
                printf("Check if pads/pull-ups of bus %d are properly 
configured\n",
                       adap->hwadapnr);
+#else
+               printf("Check if pads/pull-ups of bus %d are properly 
configured\n",
+                      i2c_bus->bus_num);
+#endif
                writew(0xFFFF, &i2c_base->stat);
                status = 0;
        }
@@ -645,6 +833,7 @@ static u16 wait_for_event(struct i2c_adapter *adap)
        return status;
 }
 
+#ifdef CONFIG_SYS_I2C
 static struct i2c *omap24_get_base(struct i2c_adapter *adap)
 {
        switch (adap->hwadapnr) {
@@ -735,3 +924,72 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_4, omap24_i2c_init, 
omap24_i2c_probe,
 #endif
 #endif
 #endif
+#endif
+
+#ifdef CONFIG_DM_I2C
+static int omap24_i2c_xfer(struct udevice *adap, struct i2c_msg *msg,
+                          int nmsgs)
+{
+       int ret;
+
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       ret = omap24_i2c_read(adap, msg->addr, 0, 0, msg->buf,
+                                             msg->len);
+               } else {
+                       ret = omap24_i2c_write(adap, msg->addr, 0, 0, msg->buf,
+                                              msg->len);
+               }
+
+               if (ret)
+                       return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+static int omap24_i2c_ofdata_to_platdata(struct udevice *adap)
+{
+       const void *blob = gd->fdt_blob;
+       struct omap24_i2c_bus *i2c_bus = dev_get_priv(adap);
+       int node;
+
+       node = adap->of_offset;
+
+       i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
+                                                 "clock-frequency", 100000);
+       i2c_bus->i2c_base = (struct i2c *)dev_get_addr(adap);
+       i2c_bus->waitdelay = (10000000 / i2c_bus->clock_frequency) * 2; /* wait 
for 20 clkperiods */
+
+       i2c_bus->bus_num = adap->seq;
+
+       omap24_i2c_init(adap, i2c_bus->clock_frequency, 1);
+
+       return 0;
+}
+
+static const struct dm_i2c_ops omap24_i2c_ops = {
+       .xfer           = omap24_i2c_xfer,
+       .probe_chip     = omap24_i2c_probe,
+       .set_bus_speed  = omap24_i2c_setspeed,
+       .deblock        = omap24_i2c_deblock,
+};
+
+static const struct udevice_id omap24_i2c_ids[] = {
+       { .compatible = "ti,omap3-i2c" },
+       { .compatible = "ti,omap4-i2c" },
+       { .compatible = "ti,omap2430-i2c" },
+       { .compatible = "ti,omap2420-i2c" },
+       { }
+};
+
+U_BOOT_DRIVER(omap_i2c) = {
+       .name   = "omap_i2c",
+       .id     = UCLASS_I2C,
+       .of_match = omap24_i2c_ids,
+       .ofdata_to_platdata = omap24_i2c_ofdata_to_platdata,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .priv_auto_alloc_size = sizeof(struct omap24_i2c_bus),
+       .ops    = &omap24_i2c_ops,
+};
+#endif
-- 
2.5.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to