Commit 5da71efa18e8b4eac9afd8bfa13e3c7e7ddde1d0

Authored by Eric Millbrandt
Committed by Heiko Schocher
1 parent 9f23ca42b3

Reset i2c slave devices during init on mpc5xxx cpus

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.

Signed-off-by: Eric Millbrandt <emillbrandt@dekaresearch.com>

Showing 3 changed files with 57 additions and 0 deletions Side-by-side Diff

... ... @@ -1366,6 +1366,13 @@
1366 1366 therefore be cleared to 0 (See, eg, MPC823e User's Manual
1367 1367 p.16-473). So, set CONFIG_SYS_I2C_SLAVE to 0.
1368 1368  
  1369 + CONFIG_SYS_I2C_INIT_MPC5XXX
  1370 +
  1371 + When a board is reset during an i2c bus transfer
  1372 + chips might think that the current transfer is still
  1373 + in progress. Reset the slave devices by sending start
  1374 + commands until the slave device responds.
  1375 +
1369 1376 That's all that's required for CONFIG_HARD_I2C.
1370 1377  
1371 1378 If you use the software i2c interface (CONFIG_SOFT_I2C)
... ... @@ -207,6 +207,52 @@
207 207 return 0;
208 208 }
209 209  
  210 +#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX)
  211 +
  212 +#define FDR510(x) (u8) (((x & 0x20) >> 3) | (x & 0x3))
  213 +#define FDR432(x) (u8) ((x & 0x1C) >> 2)
  214 +/*
  215 + * Reset any i2c devices that may have been interrupted during a system reset.
  216 + * Normally this would be accomplished by clocking the line until SCL and SDA
  217 + * are released and then sending a start condtiion (From an Atmel datasheet).
  218 + * There is no direct access to the i2c pins so instead create start commands
  219 + * through the i2c interface. Send a start command then delay for the SDA Hold
  220 + * time, repeat this by disabling/enabling the bus a total of 9 times.
  221 + */
  222 +static void send_reset(void)
  223 +{
  224 + struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
  225 + int i;
  226 + u32 delay;
  227 + u8 fdr;
  228 + int SDA_Tap[] = { 3, 3, 4, 4, 1, 1, 2, 2};
  229 + struct mpc5xxx_i2c_tap scltap[] = {
  230 + {4, 1},
  231 + {4, 2},
  232 + {6, 4},
  233 + {6, 8},
  234 + {14, 16},
  235 + {30, 32},
  236 + {62, 64},
  237 + {126, 128}
  238 + };
  239 +
  240 + fdr = (u8)mpc_reg_in(&regs->mfdr);
  241 +
  242 + delay = scltap[FDR432(fdr)].scl2tap + ((SDA_Tap[FDR510(fdr)] - 1) * \
  243 + scltap[FDR432(fdr)].tap2tap) + 3;
  244 +
  245 + for (i = 0; i < 9; i++) {
  246 + mpc_reg_out(&regs->mcr, I2C_EN|I2C_STA|I2C_TX, I2C_INIT_MASK);
  247 + udelay(delay);
  248 + mpc_reg_out(&regs->mcr, 0, I2C_INIT_MASK);
  249 + udelay(delay);
  250 + }
  251 +
  252 + mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
  253 +}
  254 +#endif /* CONFIG_SYS_I2c_INIT_MPC5XXX */
  255 +
210 256 /**************** I2C API ****************/
211 257  
212 258 void i2c_init(int speed, int saddr)
... ... @@ -225,6 +271,9 @@
225 271 mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
226 272 mpc_reg_out(&regs->msr, 0, I2C_IF);
227 273  
  274 +#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX)
  275 + send_reset();
  276 +#endif
228 277 return;
229 278 }
230 279  
include/configs/galaxy5200.h
... ... @@ -110,6 +110,7 @@
110 110 #define CONFIG_SYS_I2C_MODULE 2 /* Select I2C module #1 or #2 */
111 111 #define CONFIG_SYS_I2C_SPEED 100000 /* 100 kHz */
112 112 #define CONFIG_SYS_I2C_SLAVE 0x7F
  113 +#define CONFIG_SYS_I2C_INIT_MPC5XXX /* Reset devices on i2c bus */
113 114  
114 115 /*
115 116 * EEPROM CAT24WC32 configuration