X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=cpu%2Fmpc5xxx%2Fi2c.c;h=0f02e78a3bd3e25d04459b50c0b36c5d0e79cdc1;hb=d87080b721e4f8dca977af7571c5338ae7bb8db7;hp=640d14022fcc84bd763ed68f00e869b4a493fcf9;hpb=531716e1710083f91d9fa351f89d18e271b5c577;p=u-boot diff --git a/cpu/mpc5xxx/i2c.c b/cpu/mpc5xxx/i2c.c index 640d14022f..0f02e78a3b 100644 --- a/cpu/mpc5xxx/i2c.c +++ b/cpu/mpc5xxx/i2c.c @@ -23,20 +23,29 @@ #include +DECLARE_GLOBAL_DATA_PTR; + #ifdef CONFIG_HARD_I2C #include #include -#ifdef CFG_I2C_MODULE +#if (CFG_I2C_MODULE == 2) #define I2C_BASE MPC5XXX_I2C2 -#else +#elif (CFG_I2C_MODULE == 1) #define I2C_BASE MPC5XXX_I2C1 +#else +#error CFG_I2C_MODULE is not properly configured #endif #define I2C_TIMEOUT 100 #define I2C_RETRIES 3 +struct mpc5xxx_i2c_tap { + int scl2tap; + int tap2tap; +}; + static int mpc_reg_in (volatile u32 *reg); static void mpc_reg_out (volatile u32 *reg, int val, int mask); static int wait_for_bb (void); @@ -44,11 +53,13 @@ static int wait_for_pin (int *status); static int do_address (uchar chip, char rdwr_flag); static int send_bytes (uchar chip, char *buf, int len); static int receive_bytes (uchar chip, char *buf, int len); +static int mpc_get_fdr (int); static int mpc_reg_in(volatile u32 *reg) { - return *reg >> 24; + int ret = *reg >> 24; __asm__ __volatile__ ("eieio"); + return ret; } static void mpc_reg_out(volatile u32 *reg, int val, int mask) @@ -125,13 +136,13 @@ static int do_address(uchar chip, char rdwr_flag) mpc_reg_out(®s->mcr, I2C_TX, I2C_TX); mpc_reg_out(®s->mdr, chip, 0); - if (wait_for_pin(&status)) { - return -2; - } + if (wait_for_pin(&status)) { + return -2; + } - if (status & I2C_RXAK) { - return -3; - } + if (status & I2C_RXAK) { + return -3; + } return 0; } @@ -207,7 +218,7 @@ void i2c_init(int speed, int saddr) /* Set clock */ - mpc_reg_out(®s->mfdr, speed, 0); + mpc_reg_out(®s->mfdr, mpc_get_fdr(speed), 0); /* Enable module */ @@ -217,6 +228,55 @@ void i2c_init(int speed, int saddr) return; } +static int mpc_get_fdr(int speed) +{ + static int fdr = -1; + + if (fdr == -1) { + ulong best_speed = 0; + ulong divider; + ulong ipb, scl; + ulong bestmatch = 0xffffffffUL; + int best_i = 0, best_j = 0, i, j; + int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8}; + struct mpc5xxx_i2c_tap scltap[] = { + {4, 1}, + {4, 2}, + {6, 4}, + {6, 8}, + {14, 16}, + {30, 32}, + {62, 64}, + {126, 128} + }; + + ipb = gd->ipb_clk; + for (i = 7; i >= 0; i--) { + for (j = 7; j >= 0; j--) { + scl = 2 * (scltap[j].scl2tap + + (SCL_Tap[i] - 1) * scltap[j].tap2tap + 2); + if (ipb <= speed*scl) { + if ((speed*scl - ipb) < bestmatch) { + bestmatch = speed*scl - ipb; + best_i = i; + best_j = j; + best_speed = ipb/scl; + } + } + } + } + divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2); + if (gd->flags & GD_FLG_RELOC) { + fdr = divider; + } else { + printf("%ld kHz, ", best_speed / 1000); + return divider; + } + } + + return fdr; +} + int i2c_probe(uchar chip) { struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE; @@ -227,6 +287,7 @@ int i2c_probe(uchar chip) if (! do_address(chip, 0)) { mpc_reg_out(®s->mcr, 0, I2C_STA); + udelay(500); break; } @@ -239,7 +300,7 @@ int i2c_probe(uchar chip) int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) { - uchar xaddr[4]; + char xaddr[4]; struct mpc5xxx_i2c * regs = (struct mpc5xxx_i2c *)I2C_BASE; int ret = -1; @@ -270,7 +331,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) goto Done; } - if (receive_bytes(chip, buf, len)) { + if (receive_bytes(chip, (char *)buf, len)) { printf("i2c_read: receive_bytes failed\n"); goto Done; } @@ -283,7 +344,7 @@ Done: int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) { - uchar xaddr[4]; + char xaddr[4]; struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE; int ret = -1; @@ -292,13 +353,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) xaddr[2] = (addr >> 8) & 0xFF; xaddr[3] = addr & 0xFF; - if (wait_for_bb()) { + if (wait_for_bb()) { printf("i2c_write: bus is busy\n"); goto Done; } - mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); - if (do_address(chip, 0)) { + mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); + if (do_address(chip, 0)) { printf("i2c_write: failed to address chip\n"); goto Done; } @@ -308,7 +369,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) goto Done; } - if (send_bytes(chip, buf, len)) { + if (send_bytes(chip, (char *)buf, len)) { printf("i2c_write: send_bytes failed\n"); goto Done; } @@ -321,7 +382,7 @@ Done: uchar i2c_reg_read(uchar chip, uchar reg) { - char buf; + uchar buf; i2c_read(chip, reg, 1, &buf, 1);