diff options
-rw-r--r-- | arch/powerpc/cpu/mpc85xx/cmd_errata.c | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/config_mpc85xx.h | 16 | ||||
-rw-r--r-- | arch/powerpc/include/asm/fsl_i2c.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/processor.h | 5 | ||||
-rw-r--r-- | board/samsung/common/multi_i2c.c | 14 | ||||
-rw-r--r-- | board/samsung/goni/goni.c | 6 | ||||
-rw-r--r-- | board/samsung/trats/trats.c | 17 | ||||
-rw-r--r-- | board/samsung/universal_c210/universal.c | 4 | ||||
-rw-r--r-- | drivers/i2c/fsl_i2c.c | 67 | ||||
-rw-r--r-- | drivers/power/power_i2c.c | 2 | ||||
-rw-r--r-- | include/configs/trats.h | 3 | ||||
-rw-r--r-- | include/i2c.h | 2 |
12 files changed, 120 insertions, 22 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index cbb443f..05436f9 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -248,6 +248,11 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef CONFIG_SYS_FSL_ERRATUM_A005812 puts("Work-around for Erratum A-005812 enabled\n"); #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_I2C_A004447 + if ((SVR_SOC_VER(svr) == SVR_8548 && IS_SVR_REV(svr, 3, 1)) || + (SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV)) + puts("Work-around for Erratum I2C-A004447 enabled\n"); +#endif return 0; } diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index e1fc0f7..cf1bb02 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -67,6 +67,8 @@ #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5 #define CONFIG_SYS_FSL_RMU #define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x00 #elif defined(CONFIG_MPC8555) #define CONFIG_MAX_CPUS 1 @@ -132,6 +134,8 @@ #define CONFIG_SYS_FSL_ERRATUM_IFC_A002769 #define CONFIG_SYS_FSL_ERRATUM_P1010_A003549 #define CONFIG_SYS_FSL_ERRATUM_IFC_A003399 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x10 /* P1011 is single core version of P1020 */ #elif defined(CONFIG_P1011) @@ -249,6 +253,8 @@ #define CONFIG_SYS_FM_MURAM_SIZE 0x10000 #define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2" #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff600000 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x11 /* P1024 is lower end variant of P1020 */ #elif defined(CONFIG_P1024) @@ -334,6 +340,8 @@ #define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000 #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034 #define CONFIG_SYS_FSL_ERRATUM_A004849 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x11 #elif defined(CONFIG_PPC_P3041) #define CONFIG_SYS_FSL_QORIQ_CHASSIS1 @@ -369,6 +377,8 @@ #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034 #define CONFIG_SYS_FSL_ERRATUM_A004849 #define CONFIG_SYS_FSL_ERRATUM_A005812 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x20 #elif defined(CONFIG_PPC_P4080) /* also supports P4040 */ #define CONFIG_SYS_FSL_QORIQ_CHASSIS1 @@ -415,6 +425,8 @@ #define CONFIG_SYS_FSL_ERRATUM_A004580 #define CONFIG_SYS_P4080_ERRATUM_PCIE_A003 #define CONFIG_SYS_FSL_ERRATUM_A005812 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x20 #elif defined(CONFIG_PPC_P5020) /* also supports P5010 */ #define CONFIG_SYS_PPC64 /* 64-bit core */ @@ -446,6 +458,8 @@ #define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10 #define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xc0000000 #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034 +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x20 #elif defined(CONFIG_PPC_P5040) #define CONFIG_SYS_PPC64 @@ -510,6 +524,8 @@ #define CONFIG_SYS_FSL_ERRATUM_ESDHC111 #define CONFIG_SYS_FSL_ESDHC_P1010_BROKEN_SDCLK #define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2" +#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447 +#define CONFIG_SYS_FSL_A004447_SVR_REV 0x11 #elif defined(CONFIG_PPC_T4240) || defined(CONFIG_PPC_T4160) #define CONFIG_E6500 diff --git a/arch/powerpc/include/asm/fsl_i2c.h b/arch/powerpc/include/asm/fsl_i2c.h index 4f71341..d6537fd 100644 --- a/arch/powerpc/include/asm/fsl_i2c.h +++ b/arch/powerpc/include/asm/fsl_i2c.h @@ -54,6 +54,7 @@ typedef struct fsl_i2c { #define I2C_CR_MTX 0x10 #define I2C_CR_TXAK 0x08 #define I2C_CR_RSTA 0x04 +#define I2C_CR_BIT6 0x02 /* required for workaround A004447 */ #define I2C_CR_BCST 0x01 u8 sr; /* I2C status register */ diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 64a6f9c..bcf6cfb 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -847,7 +847,7 @@ /* System-On-Chip Version Register (SVR) field extraction */ #define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */ -#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revision field */ +#define SVR_REV(svr) (((svr) >> 0) & 0xFF) /* Revision field */ #define SVR_CID(svr) (((svr) >> 28) & 0x0F) /* Company or manufacturer ID */ #define SVR_SOCOP(svr) (((svr) >> 22) & 0x3F) /* SOC integration options */ @@ -1043,9 +1043,6 @@ /* System Version Register (SVR) field extraction */ -#define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */ -#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revison field */ - #define SVR_SUBVER(svr) (((svr) >> 8) & 0xFF) /* Process/MFG sub-version */ #define SVR_FAM(svr) (((svr) >> 20) & 0xFFF) /* Family field */ diff --git a/board/samsung/common/multi_i2c.c b/board/samsung/common/multi_i2c.c index 4fce987..084858d 100644 --- a/board/samsung/common/multi_i2c.c +++ b/board/samsung/common/multi_i2c.c @@ -11,13 +11,12 @@ /* Handle multiple I2C buses instances */ int get_multi_scl_pin(void) { - unsigned int bus = I2C_GET_BUS(); + unsigned int bus = i2c_get_bus_num(); switch (bus) { - case I2C_0: /* I2C_0 definition - compatibility layer */ - case I2C_5: + case I2C_0: return CONFIG_SOFT_I2C_I2C5_SCL; - case I2C_9: + case I2C_1: return CONFIG_SOFT_I2C_I2C9_SCL; default: printf("I2C_%d not supported!\n", bus); @@ -28,13 +27,12 @@ int get_multi_scl_pin(void) int get_multi_sda_pin(void) { - unsigned int bus = I2C_GET_BUS(); + unsigned int bus = i2c_get_bus_num(); switch (bus) { - case I2C_0: /* I2C_0 definition - compatibility layer */ - case I2C_5: + case I2C_0: return CONFIG_SOFT_I2C_I2C5_SDA; - case I2C_9: + case I2C_1: return CONFIG_SOFT_I2C_I2C9_SDA; default: printf("I2C_%d not supported!\n", bus); diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c index c05801d..5b3d6ef 100644 --- a/board/samsung/goni/goni.c +++ b/board/samsung/goni/goni.c @@ -32,7 +32,11 @@ int power_init_board(void) { int ret; - ret = pmic_init(I2C_5); + /* + * For PMIC the I2C bus is named as I2C5, but it is connected + * to logical I2C adapter 0 + */ + ret = pmic_init(I2C_0); if (ret) return ret; diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c index c8698f3..7f61d17 100644 --- a/board/samsung/trats/trats.c +++ b/board/samsung/trats/trats.c @@ -61,10 +61,10 @@ void i2c_init_board(void) struct exynos4_gpio_part2 *gpio2 = (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2(); - /* I2C_5 -> PMIC */ + /* I2C_5 -> PMIC -> Adapter 0 */ s5p_gpio_direction_output(&gpio1->b, 7, 1); s5p_gpio_direction_output(&gpio1->b, 6, 1); - /* I2C_9 -> FG */ + /* I2C_9 -> FG -> Adapter 1 */ s5p_gpio_direction_output(&gpio2->y4, 0, 1); s5p_gpio_direction_output(&gpio2->y4, 1, 1); } @@ -282,10 +282,17 @@ int power_init_board(void) struct power_battery *pb; struct pmic *p_fg, *p_chrg, *p_muic, *p_bat; - ret = pmic_init(I2C_5); + /* + * For PMIC/MUIC the I2C bus is named as I2C5, but it is connected + * to logical I2C adapter 0 + * + * The FUEL_GAUGE is marked as I2C9 on the schematic, but connected + * to logical I2C adapter 1 + */ + ret = pmic_init(I2C_0); ret |= pmic_init_max8997(); - ret |= power_fg_init(I2C_9); - ret |= power_muic_init(I2C_5); + ret |= power_fg_init(I2C_1); + ret |= power_muic_init(I2C_0); ret |= power_bat_init(0); if (ret) return ret; diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c index 2e1dba6..54d0e1e 100644 --- a/board/samsung/universal_c210/universal.c +++ b/board/samsung/universal_c210/universal.c @@ -45,6 +45,10 @@ int power_init_board(void) { int ret; + /* + * For PMIC the I2C bus is named as I2C5, but it is connected + * to logical I2C adapter 0 + */ ret = pmic_init(I2C_5); if (ret) return ret; diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 38455e1..291ad94 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -206,9 +206,58 @@ static unsigned int get_i2c_clock(int bus) return gd->arch.i2c1_clk; /* I2C1 clock */ } +static int fsl_i2c_fixup(const struct fsl_i2c *dev) +{ + const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); + unsigned long long timeval = 0; + int ret = -1; + unsigned int flags = 0; + +#ifdef CONFIG_SYS_FSL_ERRATUM_I2C_A004447 + unsigned int svr = get_svr(); + if ((SVR_SOC_VER(svr) == SVR_8548 && IS_SVR_REV(svr, 3, 1)) || + (SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV)) + flags = I2C_CR_BIT6; +#endif + + writeb(I2C_CR_MEN | I2C_CR_MSTA, &dev->cr); + + timeval = get_ticks(); + while (!(readb(&dev->sr) & I2C_SR_MBB)) { + if ((get_ticks() - timeval) > timeout) + goto err; + } + + if (readb(&dev->sr) & I2C_SR_MAL) { + /* SDA is stuck low */ + writeb(0, &dev->cr); + udelay(100); + writeb(I2C_CR_MSTA | flags, &dev->cr); + writeb(I2C_CR_MEN | I2C_CR_MSTA | flags, &dev->cr); + } + + readb(&dev->dr); + + timeval = get_ticks(); + while (!(readb(&dev->sr) & I2C_SR_MIF)) { + if ((get_ticks() - timeval) > timeout) + goto err; + } + ret = 0; + +err: + writeb(I2C_CR_MEN | flags, &dev->cr); + writeb(0, &dev->sr); + udelay(100); + + return ret; +} + static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { const struct fsl_i2c *dev; + const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); + unsigned long long timeval; #ifdef CONFIG_SYS_I2C_INIT_BOARD /* Call board specific i2c bus reset routine before accessing the @@ -226,6 +275,18 @@ static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) writeb(0x0, &dev->sr); /* clear status register */ writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ + timeval = get_ticks(); + while (readb(&dev->sr) & I2C_SR_MBB) { + if ((get_ticks() - timeval) < timeout) + continue; + + if (fsl_i2c_fixup(dev)) + debug("i2c_init: BUS#%d failed to init\n", + adap->hwadapnr); + + break; + } + #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; @@ -394,8 +455,10 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen, int i = -1; /* signal error */ u8 *a = (u8*)&addr; - if (i2c_wait4bus(adap) >= 0 && - i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 && + if (i2c_wait4bus(adap) < 0) + return -1; + + if (i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 && __i2c_write(adap, &a[4 - alen], alen) == alen) { i = __i2c_write(adap, data, length); } diff --git a/drivers/power/power_i2c.c b/drivers/power/power_i2c.c index 66b3bab..ac76870 100644 --- a/drivers/power/power_i2c.c +++ b/drivers/power/power_i2c.c @@ -98,7 +98,7 @@ int pmic_reg_read(struct pmic *p, u32 reg, u32 *val) int pmic_probe(struct pmic *p) { - I2C_SET_BUS(p->bus); + i2c_set_bus_num(p->bus); debug("Bus: %d PMIC:%s probed!\n", p->bus, p->name); if (i2c_probe(pmic_i2c_addr)) { printf("Can't find PMIC:%s\n", p->name); diff --git a/include/configs/trats.h b/include/configs/trats.h index 9b6aac9..24ea06b 100644 --- a/include/configs/trats.h +++ b/include/configs/trats.h @@ -263,6 +263,9 @@ #define CONFIG_SYS_I2C_SOFT /* I2C bit-banged */ #define CONFIG_SYS_I2C_SOFT_SPEED 50000 #define CONFIG_SYS_I2C_SOFT_SLAVE 0xFE +#define I2C_SOFT_DECLARATIONS2 +#define CONFIG_SYS_I2C_SOFT_SPEED_2 50000 +#define CONFIG_SYS_I2C_SOFT_SLAVE_2 0x7F #define CONFIG_SOFT_I2C_READ_REPEATED_START #define CONFIG_SYS_I2C_INIT_BOARD #define CONFIG_I2C_MULTI_BUS diff --git a/include/i2c.h b/include/i2c.h index d8674ef..8fd17d1 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -390,7 +390,7 @@ unsigned int i2c_get_bus_speed(void); # if !defined(CONFIG_SYS_MAX_I2C_BUS) # define CONFIG_SYS_MAX_I2C_BUS 2 # endif -# define I2C_MULTI_BUS 0 +# define I2C_MULTI_BUS 1 #else # define CONFIG_SYS_MAX_I2C_BUS 1 # define I2C_MULTI_BUS 0 |