]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
i2c: fti2c010: migrate to new i2c model
authorKuo-Jung Su <dantesu@faraday-tech.com>
Mon, 2 Dec 2013 08:02:57 +0000 (16:02 +0800)
committerHeiko Schocher <hs@denx.de>
Thu, 5 Dec 2013 11:25:01 +0000 (12:25 +0100)
Replace the legacy i2c model with the new one.

Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
Cc: Heiko Schocher <hs@denx.de>
drivers/i2c/fti2c010.c

index ec6afc973489d26320e6fb3348ca5399226406a9..eccc1da468c8790ec74cfa052855b122b38a382a 100644 (file)
 
 #include "fti2c010.h"
 
-#ifndef CONFIG_HARD_I2C
-#error "fti2c010: CONFIG_HARD_I2C is not defined"
-#endif
-
 #ifndef CONFIG_SYS_I2C_SPEED
 #define CONFIG_SYS_I2C_SPEED    5000
 #endif
 
+#ifndef CONFIG_SYS_I2C_SLAVE
+#define CONFIG_SYS_I2C_SLAVE    0
+#endif
+
 #ifndef CONFIG_FTI2C010_CLOCK
 #define CONFIG_FTI2C010_CLOCK   clk_get_rate("I2C")
 #endif
 
 struct fti2c010_chip {
        struct fti2c010_regs *regs;
-       uint bus;
-       uint speed;
 };
 
 static struct fti2c010_chip chip_list[] = {
        {
-               .bus  = 0,
                .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE,
        },
-#ifdef CONFIG_I2C_MULTI_BUS
-# ifdef CONFIG_FTI2C010_BASE1
+#ifdef CONFIG_FTI2C010_BASE1
        {
-               .bus  = 1,
                .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE1,
        },
-# endif
-# ifdef CONFIG_FTI2C010_BASE2
+#endif
+#ifdef CONFIG_FTI2C010_BASE2
        {
-               .bus  = 2,
                .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE2,
        },
-# endif
-# ifdef CONFIG_FTI2C010_BASE3
+#endif
+#ifdef CONFIG_FTI2C010_BASE3
        {
-               .bus  = 3,
                .regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE3,
        },
-# endif
-#endif  /* #ifdef CONFIG_I2C_MULTI_BUS */
+#endif
 };
 
-static struct fti2c010_chip *curr = chip_list;
+static int fti2c010_reset(struct fti2c010_chip *chip)
+{
+       ulong ts;
+       int ret = -1;
+       struct fti2c010_regs *regs = chip->regs;
 
-static int fti2c010_wait(uint32_t mask)
+       writel(CR_I2CRST, &regs->cr);
+       for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) {
+               if (!(readl(&regs->cr) & CR_I2CRST)) {
+                       ret = 0;
+                       break;
+               }
+       }
+
+       if (ret)
+               printf("fti2c010: reset timeout\n");
+
+       return ret;
+}
+
+static int fti2c010_wait(struct fti2c010_chip *chip, uint32_t mask)
 {
        int ret = -1;
        uint32_t stat, ts;
-       struct fti2c010_regs *regs = curr->regs;
+       struct fti2c010_regs *regs = chip->regs;
 
        for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) {
                stat = readl(&regs->sr);
@@ -85,74 +95,97 @@ static int fti2c010_wait(uint32_t mask)
        return ret;
 }
 
-/*
- * u-boot I2C API
- */
+static unsigned int set_i2c_bus_speed(struct fti2c010_chip *chip,
+       unsigned int speed)
+{
+       struct fti2c010_regs *regs = chip->regs;
+       unsigned int clk = CONFIG_FTI2C010_CLOCK;
+       unsigned int gsr = 0;
+       unsigned int tsr = 32;
+       unsigned int div, rate;
+
+       for (div = 0; div < 0x3ffff; ++div) {
+               /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */
+               rate = clk / (2 * (div + 2) + gsr);
+               if (rate <= speed)
+                       break;
+       }
+
+       writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), &regs->tgsr);
+       writel(CDR_DIV(div), &regs->cdr);
+
+       return rate;
+}
 
 /*
  * Initialization, must be called once on start up, may be called
  * repeatedly to change the speed and slave addresses.
  */
-void i2c_init(int speed, int slaveaddr)
+static void fti2c010_init(struct i2c_adapter *adap, int speed, int slaveaddr)
 {
-       if (speed || !curr->speed)
-               i2c_set_bus_speed(speed);
+       struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
 
-       /* if slave mode disabled */
-       if (!slaveaddr)
+       if (adap->init_done)
                return;
 
-       /*
-        * TODO:
-        * Implement slave mode, but is it really necessary?
-        */
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+       /* Call board specific i2c bus reset routine before accessing the
+        * environment, which might be in a chip on that bus. For details
+        * about this problem see doc/I2C_Edge_Conditions.
+       */
+       i2c_init_board();
+#endif
+
+       /* master init */
+
+       fti2c010_reset(chip);
+
+       set_i2c_bus_speed(chip, speed);
+
+       /* slave init, don't care */
+
+#ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT
+       /* Call board specific i2c bus reset routine AFTER the bus has been
+        * initialized. Use either this callpoint or i2c_init_board;
+        * which is called before fti2c010_init operations.
+        * For details about this problem see doc/I2C_Edge_Conditions.
+       */
+       i2c_board_late_init();
+#endif
 }
 
 /*
  * Probe the given I2C chip address.  Returns 0 if a chip responded,
  * not 0 on failure.
  */
-int i2c_probe(uchar chip)
+static int fti2c010_probe(struct i2c_adapter *adap, u8 dev)
 {
+       struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
+       struct fti2c010_regs *regs = chip->regs;
        int ret;
-       struct fti2c010_regs *regs = curr->regs;
-
-       i2c_init(0, 0);
 
        /* 1. Select slave device (7bits Address + 1bit R/W) */
-       writel(I2C_WR(chip), &regs->dr);
+       writel(I2C_WR(dev), &regs->dr);
        writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
-       ret = fti2c010_wait(SR_DT);
+       ret = fti2c010_wait(chip, SR_DT);
        if (ret)
                return ret;
 
        /* 2. Select device register */
        writel(0, &regs->dr);
        writel(CR_ENABLE | CR_TBEN, &regs->cr);
-       ret = fti2c010_wait(SR_DT);
+       ret = fti2c010_wait(chip, SR_DT);
 
        return ret;
 }
 
-/*
- * Read/Write interface:
- *   chip:    I2C chip address, range 0..127
- *   addr:    Memory (register) address within the chip
- *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
- *              memories, 0 for register type devices with only one
- *              register)
- *   buffer:  Where to read/write the data
- *   len:     How many bytes to read/write
- *
- *   Returns: 0 on success, not 0 on failure
- */
-int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+static int fti2c010_read(struct i2c_adapter *adap,
+                       u8 dev, uint addr, int alen, uchar *buf, int len)
 {
+       struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
+       struct fti2c010_regs *regs = chip->regs;
        int ret, pos;
        uchar paddr[4];
-       struct fti2c010_regs *regs = curr->regs;
-
-       i2c_init(0, 0);
 
        paddr[0] = (addr >> 0)  & 0xFF;
        paddr[1] = (addr >> 8)  & 0xFF;
@@ -164,9 +197,9 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
         */
 
        /* A.1 Select slave device (7bits Address + 1bit R/W) */
-       writel(I2C_WR(chip), &regs->dr);
+       writel(I2C_WR(dev), &regs->dr);
        writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
-       ret = fti2c010_wait(SR_DT);
+       ret = fti2c010_wait(chip, SR_DT);
        if (ret)
                return ret;
 
@@ -176,7 +209,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
 
                writel(paddr[pos], &regs->dr);
                writel(ctrl, &regs->cr);
-               ret = fti2c010_wait(SR_DT);
+               ret = fti2c010_wait(chip, SR_DT);
                if (ret)
                        return ret;
        }
@@ -186,9 +219,9 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
         */
 
        /* B.1 Select slave device (7bits Address + 1bit R/W) */
-       writel(I2C_RD(chip), &regs->dr);
+       writel(I2C_RD(dev), &regs->dr);
        writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
-       ret = fti2c010_wait(SR_DT);
+       ret = fti2c010_wait(chip, SR_DT);
        if (ret)
                return ret;
 
@@ -202,7 +235,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
                        stat |= SR_ACK;
                }
                writel(ctrl, &regs->cr);
-               ret = fti2c010_wait(stat);
+               ret = fti2c010_wait(chip, stat);
                if (ret)
                        break;
                buf[pos] = (uchar)(readl(&regs->dr) & 0xFF);
@@ -211,25 +244,13 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
        return ret;
 }
 
-/*
- * Read/Write interface:
- *   chip:    I2C chip address, range 0..127
- *   addr:    Memory (register) address within the chip
- *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
- *              memories, 0 for register type devices with only one
- *              register)
- *   buffer:  Where to read/write the data
- *   len:     How many bytes to read/write
- *
- *   Returns: 0 on success, not 0 on failure
- */
-int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+static int fti2c010_write(struct i2c_adapter *adap,
+                       u8 dev, uint addr, int alen, u8 *buf, int len)
 {
+       struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
+       struct fti2c010_regs *regs = chip->regs;
        int ret, pos;
        uchar paddr[4];
-       struct fti2c010_regs *regs = curr->regs;
-
-       i2c_init(0, 0);
 
        paddr[0] = (addr >> 0)  & 0xFF;
        paddr[1] = (addr >> 8)  & 0xFF;
@@ -241,9 +262,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
         *
         * A.1 Select slave device (7bits Address + 1bit R/W)
         */
-       writel(I2C_WR(chip), &regs->dr);
+       writel(I2C_WR(dev), &regs->dr);
        writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
-       ret = fti2c010_wait(SR_DT);
+       ret = fti2c010_wait(chip, SR_DT);
        if (ret)
                return ret;
 
@@ -253,7 +274,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
 
                writel(paddr[pos], &regs->dr);
                writel(ctrl, &regs->cr);
-               ret = fti2c010_wait(SR_DT);
+               ret = fti2c010_wait(chip, SR_DT);
                if (ret)
                        return ret;
        }
@@ -268,7 +289,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
                        ctrl |= CR_STOP;
                writel(buf[pos], &regs->dr);
                writel(ctrl, &regs->cr);
-               ret = fti2c010_wait(SR_DT);
+               ret = fti2c010_wait(chip, SR_DT);
                if (ret)
                        break;
        }
@@ -276,94 +297,40 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
        return ret;
 }
 
-/*
- * Functions for setting the current I2C bus and its speed
- */
-#ifdef CONFIG_I2C_MULTI_BUS
-
-/*
- * i2c_set_bus_num:
- *
- *  Change the active I2C bus.  Subsequent read/write calls will
- *  go to this one.
- *
- *    bus - bus index, zero based
- *
- *    Returns: 0 on success, not 0 on failure
- */
-int i2c_set_bus_num(uint bus)
-{
-       if (bus >= ARRAY_SIZE(chip_list))
-               return -1;
-       curr = chip_list + bus;
-       i2c_init(0, 0);
-       return 0;
-}
-
-/*
- * i2c_get_bus_num:
- *
- *  Returns index of currently active I2C bus.  Zero-based.
- */
-
-uint i2c_get_bus_num(void)
-{
-       return curr->bus;
-}
-
-#endif    /* #ifdef CONFIG_I2C_MULTI_BUS */
-
-/*
- * i2c_set_bus_speed:
- *
- *  Change the speed of the active I2C bus
- *
- *    speed - bus speed in Hz
- *
- *    Returns: 0 on success, not 0 on failure
- */
-int i2c_set_bus_speed(uint speed)
+static unsigned int fti2c010_set_bus_speed(struct i2c_adapter *adap,
+                       unsigned int speed)
 {
-       struct fti2c010_regs *regs = curr->regs;
-       uint clk = CONFIG_FTI2C010_CLOCK;
-       uint gsr = 0, tsr = 32;
-       uint spd, div;
-
-       if (!speed)
-               speed = CONFIG_SYS_I2C_SPEED;
-
-       for (div = 0; div < 0x3ffff; ++div) {
-               /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */
-               spd = clk / (2 * (div + 2) + gsr);
-               if (spd <= speed)
-                       break;
-       }
-
-       if (curr->speed == spd)
-               return 0;
-
-       writel(CR_I2CRST, &regs->cr);
-       mdelay(100);
-       if (readl(&regs->cr) & CR_I2CRST) {
-               printf("fti2c010: reset timeout\n");
-               return -1;
-       }
-
-       curr->speed = spd;
+       struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
+       int ret;
 
-       writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), &regs->tgsr);
-       writel(CDR_DIV(div), &regs->cdr);
+       fti2c010_reset(chip);
+       ret = set_i2c_bus_speed(chip, speed);
 
-       return 0;
+       return ret;
 }
 
 /*
- * i2c_get_bus_speed:
- *
- *  Returns speed of currently active I2C bus in Hz
+ * Register i2c adapters
  */
-
-uint i2c_get_bus_speed(void)
-{
-       return curr->speed;
-}
+U_BOOT_I2C_ADAP_COMPLETE(i2c_0, fti2c010_init, fti2c010_probe, fti2c010_read,
+                       fti2c010_write, fti2c010_set_bus_speed,
+                       CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
+                       0)
+#ifdef CONFIG_FTI2C010_BASE1
+U_BOOT_I2C_ADAP_COMPLETE(i2c_1, fti2c010_init, fti2c010_probe, fti2c010_read,
+                       fti2c010_write, fti2c010_set_bus_speed,
+                       CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
+                       1)
+#endif
+#ifdef CONFIG_FTI2C010_BASE2
+U_BOOT_I2C_ADAP_COMPLETE(i2c_2, fti2c010_init, fti2c010_probe, fti2c010_read,
+                       fti2c010_write, fti2c010_set_bus_speed,
+                       CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
+                       2)
+#endif
+#ifdef CONFIG_FTI2C010_BASE3
+U_BOOT_I2C_ADAP_COMPLETE(i2c_3, fti2c010_init, fti2c010_probe, fti2c010_read,
+                       fti2c010_write, fti2c010_set_bus_speed,
+                       CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
+                       3)
+#endif