|
|
|
@ -28,15 +28,22 @@ |
|
|
|
|
#include <mpc5xxx.h> |
|
|
|
|
#include <i2c.h> |
|
|
|
|
|
|
|
|
|
#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,6 +51,7 @@ 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) |
|
|
|
|
{ |
|
|
|
@ -207,7 +215,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 +225,50 @@ void i2c_init(int speed, int saddr) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mpc_get_fdr(int speed) |
|
|
|
|
{ |
|
|
|
|
DECLARE_GLOBAL_DATA_PTR; |
|
|
|
|
static int fdr = -1; |
|
|
|
|
static int best_speed = 0; |
|
|
|
|
|
|
|
|
|
if (fdr == -1) { |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
fdr = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2); |
|
|
|
|
printf("%d kHz, ", best_speed / 1000); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return fdr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int i2c_probe(uchar chip) |
|
|
|
|
{ |
|
|
|
|
struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE; |
|
|
|
|