This patch adds runtime speed configuration to the mv_i2c driver.
Currently standard (max 100kHz) and fast mode (max 400kHz) are
supported.

Signed-off-by: Stefan Roese <s...@denx.de>
Cc: Nadav Haklai <nad...@marvell.com>
Cc: Kostya Porotchkin <kos...@marvell.com>
Cc: Wilson Ding <ding...@marvell.com>
Cc: Victor Gu <x...@marvell.com>
Cc: Hua Jing <jing...@marvell.com>
Cc: Terry Zhou <bjz...@marvell.com>
Cc: Hanna Hawa <han...@marvell.com>
Cc: Haim Boot <ha...@marvell.com>
Cc: Heiko Schocher <h...@denx.de>
---
 drivers/i2c/mv_i2c.c | 30 +++++++++++++++++++++++++++++-
 drivers/i2c/mv_i2c.h | 15 +++++++++------
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c
index 341126a..291b2d7 100644
--- a/drivers/i2c/mv_i2c.c
+++ b/drivers/i2c/mv_i2c.c
@@ -68,6 +68,10 @@ __weak void i2c_clk_enable(void)
  */
 static void i2c_reset(struct mv_i2c *base)
 {
+       u32 icr_mode;
+
+       /* Save bus mode (standard or fast speed) for later use */
+       icr_mode = readl(&base->icr) & ICR_MODE_MASK;
        writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */
        writel(readl(&base->icr) | ICR_UR, &base->icr);   /* reset the unit */
        udelay(100);
@@ -76,7 +80,8 @@ static void i2c_reset(struct mv_i2c *base)
        i2c_clk_enable();
 
        writel(CONFIG_SYS_I2C_SLAVE, &base->isar); /* set our slave address */
-       writel(I2C_ICR_INIT, &base->icr); /* set control reg values */
+       /* set control reg values */
+       writel(I2C_ICR_INIT | icr_mode, &base->icr);
        writel(I2C_ISR_INIT, &base->isr); /* set clear interrupt bits */
        writel(readl(&base->icr) | ICR_IUE, &base->icr); /* enable unit */
        udelay(100);
@@ -416,6 +421,8 @@ unsigned int i2c_get_bus_num(void)
 /* API Functions */
 void i2c_init(int speed, int slaveaddr)
 {
+       u32 val;
+
 #ifdef CONFIG_I2C_MULTI_BUS
        current_bus = 0;
        base_glob = (struct mv_i2c *)i2c_regs[current_bus];
@@ -423,6 +430,12 @@ void i2c_init(int speed, int slaveaddr)
        base_glob = (struct mv_i2c *)CONFIG_MV_I2C_REG;
 #endif
 
+       if (speed > 100000)
+               val = ICR_FM;
+       else
+               val = ICR_SM;
+       clrsetbits_le32(&base_glob->icr, ICR_MODE_MASK, val);
+
        i2c_board_init(base_glob);
 }
 
@@ -543,6 +556,20 @@ static int mv_i2c_xfer(struct udevice *bus, struct i2c_msg 
*msg, int nmsgs)
                                   omsg->len, dmsg->buf, dmsg->len);
 }
 
+static int mv_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+       struct mv_i2c_priv *priv = dev_get_priv(bus);
+       u32 val;
+
+       if (speed > 100000)
+               val = ICR_FM;
+       else
+               val = ICR_SM;
+       clrsetbits_le32(&priv->base->icr, ICR_MODE_MASK, val);
+
+       return 0;
+}
+
 static int mv_i2c_probe(struct udevice *bus)
 {
        struct mv_i2c_priv *priv = dev_get_priv(bus);
@@ -554,6 +581,7 @@ static int mv_i2c_probe(struct udevice *bus)
 
 static const struct dm_i2c_ops mv_i2c_ops = {
        .xfer           = mv_i2c_xfer,
+       .set_bus_speed  = mv_i2c_set_bus_speed,
 };
 
 static const struct udevice_id mv_i2c_ids[] = {
diff --git a/drivers/i2c/mv_i2c.h b/drivers/i2c/mv_i2c.h
index ae27c44..1e62892 100644
--- a/drivers/i2c/mv_i2c.h
+++ b/drivers/i2c/mv_i2c.h
@@ -23,12 +23,7 @@ extern void i2c_clk_enable(void);
 #define I2C_READ               0
 #define I2C_WRITE              1
 
-#if (CONFIG_SYS_I2C_SPEED == 400000)
-#define I2C_ICR_INIT   (ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD \
-               | ICR_SCLE)
-#else
 #define I2C_ICR_INIT   (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
-#endif
 
 #define I2C_ISR_INIT           0x7FF
 /* ----- Control register bits ---------------------------------------- */
@@ -48,7 +43,15 @@ extern void i2c_clk_enable(void);
 #define ICR_ALDIE      0x1000          /* enable arbitration interrupt */
 #define ICR_SADIE      0x2000          /* slave address detected int enable */
 #define ICR_UR         0x4000          /* unit reset */
-#define ICR_FM         0x8000          /* Fast Mode */
+#ifdef CONFIG_ARMADA_3700
+#define ICR_SM         0x00000         /* Standard Mode */
+#define ICR_FM         0x10000         /* Fast Mode */
+#define ICR_MODE_MASK  0x30000         /* Mode mask */
+#else
+#define ICR_SM         0x00000         /* Standard Mode */
+#define ICR_FM         0x08000         /* Fast Mode */
+#define ICR_MODE_MASK  0x18000         /* Mode mask */
+#endif
 
 /* ----- Status register bits ----------------------------------------- */
 
-- 
2.9.3

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

Reply via email to