public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Kuo-Jung Su <dantesu@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/2] i2c: fti2c010: migrate to new i2c model
Date: Mon, 25 Nov 2013 10:48:13 +0800	[thread overview]
Message-ID: <1385347693-1192-3-git-send-email-dantesu@gmail.com> (raw)
In-Reply-To: <1385347693-1192-1-git-send-email-dantesu@gmail.com>

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

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 |  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

  parent reply	other threads:[~2013-11-25  2:48 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-25  2:48 [U-Boot] [PATCH 0/2] i2c: fti2c010: migrate to new i2c model Kuo-Jung Su
2013-11-25  2:48 ` [U-Boot] [PATCH 1/2] i2c: fti2c010: cosmetic: coding style cleanup Kuo-Jung Su
2013-11-25  2:48 ` Kuo-Jung Su [this message]
2013-11-28  2:47 ` [U-Boot] [PATCH v2 0/4] i2c: fti2c010: bug fix & new driver model Kuo-Jung Su
2013-11-28  2:47   ` [U-Boot] [PATCH v2 1/4] i2c: fti2c010: cosmetic: coding style cleanup Kuo-Jung Su
2013-11-28  2:47   ` [U-Boot] [PATCH v2 2/4] i2c: fti2c010: migrate to new i2c model Kuo-Jung Su
2013-11-28  2:47   ` [U-Boot] [PATCH v2 3/4] i2c: fti2c010: serial out r/w address in MSB order Kuo-Jung Su
2013-11-28  2:47   ` [U-Boot] [PATCH v2 4/4] cmd_eeprom: bug fix for i2c read/write Kuo-Jung Su
2013-11-28 10:39     ` Alexey Brodkin
2013-11-29  0:59       ` Kuo-Jung Su
2013-11-29  9:10         ` Alexey Brodkin
2013-11-29  9:32           ` Kuo-Jung Su
2013-11-29  9:56             ` Alexey Brodkin
2013-11-29 15:04               ` Kuo-Jung Su
2013-12-02  2:57 ` [U-Boot] [PATCH v3 0/4] i2c: fti2c010: bug fix & new driver model Kuo-Jung Su
2013-12-02  2:57   ` [U-Boot] [PATCH v3 1/4] i2c: fti2c010: cosmetic: coding style cleanup Kuo-Jung Su
2013-12-02  7:30   ` [U-Boot] [PATCH v3 0/4] i2c: fti2c010: bug fix & new driver model Heiko Schocher
2013-12-02  8:09     ` Kuo-Jung Su
2013-12-02  8:36       ` Heiko Schocher
2013-12-02  8:02 ` Kuo-Jung Su
2013-12-02  8:02   ` [U-Boot] [PATCH v3 1/4] i2c: fti2c010: cosmetic: coding style cleanup Kuo-Jung Su
2013-12-09  6:52     ` [U-Boot] [U-Boot, v3, " Heiko Schocher
2013-12-02  8:02   ` [U-Boot] [PATCH v3 2/4] i2c: fti2c010: migrate to new i2c model Kuo-Jung Su
2013-12-09  6:53     ` [U-Boot] [U-Boot, v3, " Heiko Schocher
2013-12-02  8:02   ` [U-Boot] [PATCH v3 3/4] i2c: fti2c010: serial out r/w address in MSB order Kuo-Jung Su
2013-12-09  6:55     ` [U-Boot] [U-Boot, v3, " Heiko Schocher
2013-12-02  8:02   ` [U-Boot] [PATCH v3 4/4] cmd_eeprom: bug fix for i2c read/write Kuo-Jung Su
2013-12-02 11:09     ` Alexey Brodkin
2013-12-03  0:55       ` Kuo-Jung Su
2013-12-03  7:42         ` Alexey Brodkin
2013-12-09  6:56     ` [U-Boot] [U-Boot, v3, " Heiko Schocher
2013-12-09 10:35       ` Alexey Brodkin
2013-12-09 11:21         ` Heiko Schocher
2013-12-10 10:18           ` Alexey Brodkin
2013-12-11  1:13             ` Kuo-Jung Su

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1385347693-1192-3-git-send-email-dantesu@gmail.com \
    --to=dantesu@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox