[U-Boot] [PATCH 2/2] i2c: fti2c010: migrate to new i2c model

Kuo-Jung Su dantesu at gmail.com
Mon Nov 25 03:48:13 CET 2013


From: Kuo-Jung Su <dantesu at faraday-tech.com>

Replace the legacy i2c model with the new one.

Signed-off-by: Kuo-Jung Su <dantesu at faraday-tech.com>
Cc: Heiko Schocher <hs at denx.de>
---
 drivers/i2c/fti2c010.c |  299 +++++++++++++++++++++---------------------------
 1 file changed, 133 insertions(+), 166 deletions(-)

diff --git a/drivers/i2c/fti2c010.c b/drivers/i2c/fti2c010.c
index ec6afc9..eccc1da 100644
--- a/drivers/i2c/fti2c010.c
+++ b/drivers/i2c/fti2c010.c
@@ -13,14 +13,14 @@
 
 #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
@@ -35,44 +35,54 @@
 
 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
-- 
1.7.9.5



More information about the U-Boot mailing list