
From: Vitaly Andrianov vitalya@ti.com
Signed-off-by: Vitaly Andrianov vitalya@ti.com --- drivers/i2c/davinci_i2c.c | 344 ++++++++++++++++++++++++++------------------- drivers/i2c/davinci_i2c.h | 27 ++-- 2 files changed, 218 insertions(+), 153 deletions(-)
diff --git a/drivers/i2c/davinci_i2c.c b/drivers/i2c/davinci_i2c.c index 6e5260c..c584a11 100644 --- a/drivers/i2c/davinci_i2c.c +++ b/drivers/i2c/davinci_i2c.c @@ -1,25 +1,37 @@ /* * TI DaVinci (TMS320DM644x) I2C driver. * - * Copyright (C) 2007 Sergey Kubushyn ksi@koi8.net + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + * (C) Copyright 2007 Sergey Kubushyn ksi@koi8.net * - * -------------------------------------------------------- - * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0+ */
#include <common.h> #include <i2c.h> #include <asm/arch/hardware.h> #include <asm/arch/i2c_defs.h> +#include <asm/io.h> #include "davinci_i2c.h"
+DECLARE_GLOBAL_DATA_PTR; + +static struct i2c_regs __attribute__((section(".data"))) *i2c_base = + (struct i2c_regs *)I2C_BASE; + +#ifdef CONFIG_I2C_MULTI_BUS +static unsigned int __attribute__((section(".data"))) + bus_initialized[I2C_BUS_MAX] = { [0 ... (I2C_BUS_MAX-1)] = 0 }; +static unsigned int __attribute__((section(".data"))) current_bus; +#endif + #define CHECK_NACK() \ do {\ if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ - REG(I2C_CON) = 0;\ - return(1);\ - }\ + REG(&(i2c_base->i2c_con)) = 0;\ + return 1;\ + } \ } while (0)
@@ -27,20 +39,21 @@ static int wait_for_bus(void) { int stat, timeout;
- REG(I2C_STAT) = 0xffff; + REG(&(i2c_base->i2c_stat)) = 0xffff;
for (timeout = 0; timeout < 10; timeout++) { - if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { - REG(I2C_STAT) = 0xffff; - return(0); + stat = REG(&(i2c_base->i2c_stat)); + if (!((stat) & I2C_STAT_BB)) { + REG(&(i2c_base->i2c_stat)) = 0xffff; + return 0; }
- REG(I2C_STAT) = stat; + REG(&(i2c_base->i2c_stat)) = stat; udelay(50000); }
- REG(I2C_STAT) = 0xffff; - return(1); + REG(&(i2c_base->i2c_stat)) = 0xffff; + return 1; }
@@ -50,25 +63,24 @@ static int poll_i2c_irq(int mask)
for (timeout = 0; timeout < 10; timeout++) { udelay(1000); - stat = REG(I2C_STAT); - if (stat & mask) { - return(stat); - } + stat = REG(&(i2c_base->i2c_stat)); + if (stat & mask) + return stat; }
- REG(I2C_STAT) = 0xffff; - return(stat | I2C_TIMEOUT); + REG(&(i2c_base->i2c_stat)) = 0xffff; + return stat | I2C_TIMEOUT; }
void flush_rx(void) { while (1) { - if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) + if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_RRDY)) break;
- REG(I2C_DRR); - REG(I2C_STAT) = I2C_STAT_RRDY; + REG(&(i2c_base->i2c_drr)); + REG(&(i2c_base->i2c_stat)) = I2C_STAT_RRDY; udelay(1000); } } @@ -78,28 +90,33 @@ void i2c_init(int speed, int slaveadd) { u_int32_t div, psc;
- if (REG(I2C_CON) & I2C_CON_EN) { - REG(I2C_CON) = 0; - udelay (50000); + if (REG(&(i2c_base->i2c_con)) & I2C_CON_EN) { + REG(&(i2c_base->i2c_con)) = 0; + udelay(50000); }
psc = 2; - div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */ - REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */ - REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ - REG(I2C_SCLH) = div - REG(I2C_SCLL); + div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; + REG(&(i2c_base->i2c_psc)) = psc; + REG(&(i2c_base->i2c_scll)) = (div * 50) / 100; + REG(&(i2c_base->i2c_sclh)) = div - REG(&(i2c_base->i2c_scll));
- REG(I2C_OA) = slaveadd; - REG(I2C_CNT) = 0; + REG(&(i2c_base->i2c_oa)) = slaveadd; + REG(&(i2c_base->i2c_cnt)) = 0;
/* Interrupts must be enabled or I2C module won't work */ - REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | + REG(&(i2c_base->i2c_ie)) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
/* Now enable I2C controller (get it out of reset) */ - REG(I2C_CON) = I2C_CON_EN; + REG(&(i2c_base->i2c_con)) = I2C_CON_EN;
udelay(1000); + +#ifdef CONFIG_I2C_MULTI_BUS + if (gd->flags & GD_FLG_RELOC) + bus_initialized[current_bus] = 1; +#endif }
int i2c_set_bus_speed(unsigned int speed) @@ -112,34 +129,36 @@ int i2c_probe(u_int8_t chip) { int rc = 1;
- if (chip == REG(I2C_OA)) { - return(rc); - } + if (chip == REG(&(i2c_base->i2c_oa))) + return rc;
- REG(I2C_CON) = 0; - if (wait_for_bus()) {return(1);} + REG(&(i2c_base->i2c_con)) = 0; + if (wait_for_bus()) + return 1;
/* try to read one byte from current (or only) address */ - REG(I2C_CNT) = 1; - REG(I2C_SA) = chip; - REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP); - udelay (50000); + REG(&(i2c_base->i2c_cnt)) = 1; + REG(&(i2c_base->i2c_sa)) = chip; + REG(&(i2c_base->i2c_con)) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | + I2C_CON_STP); + udelay(50000);
- if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { + if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_NACK)) { rc = 0; flush_rx(); - REG(I2C_STAT) = 0xffff; + REG(&(i2c_base->i2c_stat)) = 0xffff; } else { - REG(I2C_STAT) = 0xffff; - REG(I2C_CON) |= I2C_CON_STP; + REG(&(i2c_base->i2c_stat)) = 0xffff; + REG(&(i2c_base->i2c_con)) |= I2C_CON_STP; udelay(20000); - if (wait_for_bus()) {return(1);} + if (wait_for_bus()) + return 1; }
flush_rx(); - REG(I2C_STAT) = 0xffff; - REG(I2C_CNT) = 0; - return(rc); + REG(&(i2c_base->i2c_stat)) = 0xffff; + REG(&(i2c_base->i2c_cnt)) = 0; + return rc; }
@@ -149,73 +168,76 @@ int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) int i;
if ((alen < 0) || (alen > 2)) { - printf("%s(): bogus address length %x\n", __FUNCTION__, alen); - return(1); + printf("%s(): bogus address length %x\n", __func__, alen); + return 1; }
- if (wait_for_bus()) {return(1);} + if (wait_for_bus()) + return 1;
if (alen != 0) { /* Start address phase */ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; - REG(I2C_CNT) = alen; - REG(I2C_SA) = chip; - REG(I2C_CON) = tmp; + REG(&(i2c_base->i2c_cnt)) = alen; + REG(&(i2c_base->i2c_sa)) = chip; + REG(&(i2c_base->i2c_con)) = tmp;
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
CHECK_NACK();
switch (alen) { - case 2: - /* Send address MSByte */ - if (tmp & I2C_STAT_XRDY) { - REG(I2C_DXR) = (addr >> 8) & 0xff; - } else { - REG(I2C_CON) = 0; - return(1); - } - - tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); - - CHECK_NACK(); - /* No break, fall through */ - case 1: - /* Send address LSByte */ - if (tmp & I2C_STAT_XRDY) { - REG(I2C_DXR) = addr & 0xff; - } else { - REG(I2C_CON) = 0; - return(1); - } - - tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); - - CHECK_NACK(); - - if (!(tmp & I2C_STAT_ARDY)) { - REG(I2C_CON) = 0; - return(1); - } + case 2: + /* Send address MSByte */ + if (tmp & I2C_STAT_XRDY) { + REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff; + } else { + REG(&(i2c_base->i2c_con)) = 0; + return 1; + } + + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + + CHECK_NACK(); + /* No break, fall through */ + case 1: + /* Send address LSByte */ + if (tmp & I2C_STAT_XRDY) { + REG(&(i2c_base->i2c_dxr)) = addr & 0xff; + } else { + REG(&(i2c_base->i2c_con)) = 0; + return 1; + } + + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | + I2C_STAT_ARDY); + + CHECK_NACK(); + + if (!(tmp & I2C_STAT_ARDY)) { + REG(&(i2c_base->i2c_con)) = 0; + return 1; + } } }
/* Address phase is over, now read 'len' bytes and stop */ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; - REG(I2C_CNT) = len & 0xffff; - REG(I2C_SA) = chip; - REG(I2C_CON) = tmp; + REG(&(i2c_base->i2c_cnt)) = len & 0xffff; + REG(&(i2c_base->i2c_sa)) = chip; + REG(&(i2c_base->i2c_con)) = tmp;
for (i = 0; i < len; i++) { - tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); + tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | + I2C_STAT_ROVR);
CHECK_NACK();
if (tmp & I2C_STAT_RRDY) { - buf[i] = REG(I2C_DRR); + buf[i] = REG(&(i2c_base->i2c_drr)); } else { - REG(I2C_CON) = 0; - return(1); + REG(&(i2c_base->i2c_con)) = 0; + return 1; } }
@@ -224,16 +246,16 @@ int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) CHECK_NACK();
if (!(tmp & I2C_STAT_SCD)) { - REG(I2C_CON) = 0; - return(1); + REG(&(i2c_base->i2c_con)) = 0; + return 1; }
flush_rx(); - REG(I2C_STAT) = 0xffff; - REG(I2C_CNT) = 0; - REG(I2C_CON) = 0; + REG(&(i2c_base->i2c_stat)) = 0xffff; + REG(&(i2c_base->i2c_cnt)) = 0; + REG(&(i2c_base->i2c_con)) = 0;
- return(0); + return 0; }
@@ -243,48 +265,51 @@ int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) int i;
if ((alen < 0) || (alen > 2)) { - printf("%s(): bogus address length %x\n", __FUNCTION__, alen); - return(1); + printf("%s(): bogus address length %x\n", __func__, alen); + return 1; } if (len < 0) { - printf("%s(): bogus length %x\n", __FUNCTION__, len); - return(1); + printf("%s(): bogus length %x\n", __func__, len); + return 1; }
- if (wait_for_bus()) {return(1);} + if (wait_for_bus()) + return 1;
/* Start address phase */ - tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; - REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; - REG(I2C_SA) = chip; - REG(I2C_CON) = tmp; + tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | + I2C_CON_TRX | I2C_CON_STP; + REG(&(i2c_base->i2c_cnt)) = (alen == 0) ? + len & 0xffff : (len & 0xffff) + alen; + REG(&(i2c_base->i2c_sa)) = chip; + REG(&(i2c_base->i2c_con)) = tmp;
switch (alen) { - case 2: - /* Send address MSByte */ - tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + case 2: + /* Send address MSByte */ + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
- CHECK_NACK(); + CHECK_NACK();
- if (tmp & I2C_STAT_XRDY) { - REG(I2C_DXR) = (addr >> 8) & 0xff; - } else { - REG(I2C_CON) = 0; - return(1); - } - /* No break, fall through */ - case 1: - /* Send address LSByte */ - tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + if (tmp & I2C_STAT_XRDY) { + REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff; + } else { + REG(&(i2c_base->i2c_con)) = 0; + return 1; + } + /* No break, fall through */ + case 1: + /* Send address LSByte */ + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
- CHECK_NACK(); + CHECK_NACK();
- if (tmp & I2C_STAT_XRDY) { - REG(I2C_DXR) = addr & 0xff; - } else { - REG(I2C_CON) = 0; - return(1); - } + if (tmp & I2C_STAT_XRDY) { + REG(&(i2c_base->i2c_dxr)) = addr & 0xff; + } else { + REG(&(i2c_base->i2c_con)) = 0; + return 1; + } }
for (i = 0; i < len; i++) { @@ -292,11 +317,10 @@ int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
CHECK_NACK();
- if (tmp & I2C_STAT_XRDY) { - REG(I2C_DXR) = buf[i]; - } else { - return(1); - } + if (tmp & I2C_STAT_XRDY) + REG(&(i2c_base->i2c_dxr)) = buf[i]; + else + return 1; }
tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); @@ -304,14 +328,52 @@ int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) CHECK_NACK();
if (!(tmp & I2C_STAT_SCD)) { - REG(I2C_CON) = 0; - return(1); + REG(&(i2c_base->i2c_con)) = 0; + return 1; }
flush_rx(); - REG(I2C_STAT) = 0xffff; - REG(I2C_CNT) = 0; - REG(I2C_CON) = 0; + REG(&(i2c_base->i2c_stat)) = 0xffff; + REG(&(i2c_base->i2c_cnt)) = 0; + REG(&(i2c_base->i2c_con)) = 0; + + return 0; +} + +#ifdef CONFIG_I2C_MULTI_BUS +int i2c_set_bus_num(unsigned int bus) +{ + if ((bus < 0) || (bus >= I2C_BUS_MAX)) { + printf("Bad bus: %d\n", bus); + return -1; + }
- return(0); + switch (bus) { +#if I2C_BUS_MAX == 3 + case 2: + i2c_base = (struct i2c_regs *)I2C2_BASE; + break; +#endif +#if I2C_BUS_MAX >= 2 + case 1: + i2c_base = (struct i2c_regs *)I2C1_BASE; + break; +#endif + default: + i2c_base = (struct i2c_regs *)I2C0_BASE; + bus = 0; + } + + current_bus = bus; + + if (!bus_initialized[current_bus]) + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + return 0; +} + +unsigned int i2c_get_bus_num(void) +{ + return (int) current_bus; } +#endif diff --git a/drivers/i2c/davinci_i2c.h b/drivers/i2c/davinci_i2c.h index 79ff7a3..20d4342 100644 --- a/drivers/i2c/davinci_i2c.h +++ b/drivers/i2c/davinci_i2c.h @@ -12,18 +12,21 @@ #define I2C_WRITE 0 #define I2C_READ 1
-#define I2C_OA (I2C_BASE + 0x00) -#define I2C_IE (I2C_BASE + 0x04) -#define I2C_STAT (I2C_BASE + 0x08) -#define I2C_SCLL (I2C_BASE + 0x0c) -#define I2C_SCLH (I2C_BASE + 0x10) -#define I2C_CNT (I2C_BASE + 0x14) -#define I2C_DRR (I2C_BASE + 0x18) -#define I2C_SA (I2C_BASE + 0x1c) -#define I2C_DXR (I2C_BASE + 0x20) -#define I2C_CON (I2C_BASE + 0x24) -#define I2C_IV (I2C_BASE + 0x28) -#define I2C_PSC (I2C_BASE + 0x30) +struct i2c_regs { + u32 i2c_oa; + u32 i2c_ie; + u32 i2c_stat; + u32 i2c_scll; + u32 i2c_sclh; + u32 i2c_cnt; + u32 i2c_drr; + u32 i2c_sa; + u32 i2c_dxr; + u32 i2c_con; + u32 i2c_iv; + u32 res_2c; + u32 i2c_psc; +};
/* I2C masks */