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, ®s->cr);
+ for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) {
+ if (!(readl(®s->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(®s->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), ®s->tgsr);
+ writel(CDR_DIV(div), ®s->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), ®s->dr);
+ writel(I2C_WR(dev), ®s->dr);
writel(CR_ENABLE | CR_TBEN | CR_START, ®s->cr);
- ret = fti2c010_wait(SR_DT);
+ ret = fti2c010_wait(chip, SR_DT);
if (ret)
return ret;
/* 2. Select device register */
writel(0, ®s->dr);
writel(CR_ENABLE | CR_TBEN, ®s->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), ®s->dr);
+ writel(I2C_WR(dev), ®s->dr);
writel(CR_ENABLE | CR_TBEN | CR_START, ®s->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], ®s->dr);
writel(ctrl, ®s->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), ®s->dr);
+ writel(I2C_RD(dev), ®s->dr);
writel(CR_ENABLE | CR_TBEN | CR_START, ®s->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, ®s->cr);
- ret = fti2c010_wait(stat);
+ ret = fti2c010_wait(chip, stat);
if (ret)
break;
buf[pos] = (uchar)(readl(®s->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), ®s->dr);
+ writel(I2C_WR(dev), ®s->dr);
writel(CR_ENABLE | CR_TBEN | CR_START, ®s->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], ®s->dr);
writel(ctrl, ®s->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], ®s->dr);
writel(ctrl, ®s->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, ®s->cr);
- mdelay(100);
- if (readl(®s->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), ®s->tgsr);
- writel(CDR_DIV(div), ®s->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
next prev 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.