X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cpu%2Fmpc5xxx%2Fi2c.c;h=4f7f71632873318d9989a6babe47e8d6e5af05b4;hb=25ee856e4406da302f9d454fba9a7aa0357ee2ca;hp=044db46f6fb43676627c835ba844871a6e5a89d7;hpb=ea1fba136a4778b8f55e6b94a76a548cfad9f522;p=oweals%2Fu-boot.git diff --git a/cpu/mpc5xxx/i2c.c b/cpu/mpc5xxx/i2c.c index 044db46f6f..4f7f716328 100644 --- a/cpu/mpc5xxx/i2c.c +++ b/cpu/mpc5xxx/i2c.c @@ -23,20 +23,22 @@ #include +DECLARE_GLOBAL_DATA_PTR; + #ifdef CONFIG_HARD_I2C #include #include -#if (CFG_I2C_MODULE == 2) +#if (CONFIG_SYS_I2C_MODULE == 2) #define I2C_BASE MPC5XXX_I2C2 -#elif (CFG_I2C_MODULE == 1) +#elif (CONFIG_SYS_I2C_MODULE == 1) #define I2C_BASE MPC5XXX_I2C1 #else -#error CFG_I2C_MODULE is not properly configured +#error CONFIG_SYS_I2C_MODULE is not properly configured #endif -#define I2C_TIMEOUT 100 +#define I2C_TIMEOUT 6667 #define I2C_RETRIES 3 struct mpc5xxx_i2c_tap { @@ -92,7 +94,7 @@ static int wait_for_bb(void) mpc_reg_out(®s->mcr, 0, 0); mpc_reg_out(®s->mcr, I2C_EN, 0); #endif - udelay(1000); + udelay(15); status = mpc_reg_in(®s->msr); } @@ -107,7 +109,7 @@ static int wait_for_pin(int *status) *status = mpc_reg_in(®s->msr); while (timeout-- && !(*status & I2C_IF)) { - udelay(1000); + udelay(15); *status = mpc_reg_in(®s->msr); } @@ -205,6 +207,52 @@ static int receive_bytes(uchar chip, char *buf, int len) return 0; } +#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX) + +#define FDR510(x) (u8) (((x & 0x20) >> 3) | (x & 0x3)) +#define FDR432(x) (u8) ((x & 0x1C) >> 2) +/* + * Reset any i2c devices that may have been interrupted during a system reset. + * Normally this would be accomplished by clocking the line until SCL and SDA + * are released and then sending a start condtiion (From an Atmel datasheet). + * There is no direct access to the i2c pins so instead create start commands + * through the i2c interface. Send a start command then delay for the SDA Hold + * time, repeat this by disabling/enabling the bus a total of 9 times. + */ +static void send_reset(void) +{ + struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE; + int i; + u32 delay; + u8 fdr; + int SDA_Tap[] = { 3, 3, 4, 4, 1, 1, 2, 2}; + struct mpc5xxx_i2c_tap scltap[] = { + {4, 1}, + {4, 2}, + {6, 4}, + {6, 8}, + {14, 16}, + {30, 32}, + {62, 64}, + {126, 128} + }; + + fdr = (u8)mpc_reg_in(®s->mfdr); + + delay = scltap[FDR432(fdr)].scl2tap + ((SDA_Tap[FDR510(fdr)] - 1) * \ + scltap[FDR432(fdr)].tap2tap) + 3; + + for (i = 0; i < 9; i++) { + mpc_reg_out(®s->mcr, I2C_EN|I2C_STA|I2C_TX, I2C_INIT_MASK); + udelay(delay); + mpc_reg_out(®s->mcr, 0, I2C_INIT_MASK); + udelay(delay); + } + + mpc_reg_out(®s->mcr, I2C_EN, I2C_INIT_MASK); +} +#endif /* CONFIG_SYS_I2c_INIT_MPC5XXX */ + /**************** I2C API ****************/ void i2c_init(int speed, int saddr) @@ -223,12 +271,14 @@ void i2c_init(int speed, int saddr) mpc_reg_out(®s->mcr, I2C_EN, I2C_INIT_MASK); mpc_reg_out(®s->msr, 0, I2C_IF); +#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX) + send_reset(); +#endif return; } static int mpc_get_fdr(int speed) { - DECLARE_GLOBAL_DATA_PTR; static int fdr = -1; if (fdr == -1) { @@ -268,7 +318,8 @@ static int mpc_get_fdr(int speed) if (gd->flags & GD_FLG_RELOC) { fdr = divider; } else { - printf("%ld kHz, ", best_speed / 1000); + if (gd->have_console) + printf("%ld kHz, ", best_speed / 1000); return divider; } } @@ -309,29 +360,34 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) xaddr[3] = addr & 0xFF; if (wait_for_bb()) { - printf("i2c_read: bus is busy\n"); + if (gd->have_console) + printf("i2c_read: bus is busy\n"); goto Done; } mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); if (do_address(chip, 0)) { - printf("i2c_read: failed to address chip\n"); + if (gd->have_console) + printf("i2c_read: failed to address chip\n"); goto Done; } if (send_bytes(chip, &xaddr[4-alen], alen)) { - printf("i2c_read: send_bytes failed\n"); + if (gd->have_console) + printf("i2c_read: send_bytes failed\n"); goto Done; } mpc_reg_out(®s->mcr, I2C_RSTA, I2C_RSTA); if (do_address(chip, 1)) { - printf("i2c_read: failed to address chip\n"); + if (gd->have_console) + printf("i2c_read: failed to address chip\n"); goto Done; } if (receive_bytes(chip, (char *)buf, len)) { - printf("i2c_read: receive_bytes failed\n"); + if (gd->have_console) + printf("i2c_read: receive_bytes failed\n"); goto Done; } @@ -353,23 +409,27 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) xaddr[3] = addr & 0xFF; if (wait_for_bb()) { - printf("i2c_write: bus is busy\n"); + if (gd->have_console) + printf("i2c_write: bus is busy\n"); goto Done; } mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); if (do_address(chip, 0)) { - printf("i2c_write: failed to address chip\n"); + if (gd->have_console) + printf("i2c_write: failed to address chip\n"); goto Done; } if (send_bytes(chip, &xaddr[4-alen], alen)) { - printf("i2c_write: send_bytes failed\n"); + if (gd->have_console) + printf("i2c_write: send_bytes failed\n"); goto Done; } if (send_bytes(chip, (char *)buf, len)) { - printf("i2c_write: send_bytes failed\n"); + if (gd->have_console) + printf("i2c_write: send_bytes failed\n"); goto Done; } @@ -379,20 +439,4 @@ Done: return ret; } -uchar i2c_reg_read(uchar chip, uchar reg) -{ - uchar buf; - - i2c_read(chip, reg, 1, &buf, 1); - - return buf; -} - -void i2c_reg_write(uchar chip, uchar reg, uchar val) -{ - i2c_write(chip, reg, 1, &val, 1); - - return; -} - #endif /* CONFIG_HARD_I2C */