[U-Boot-Users] I2C Initialization

Joakim Tjernlund
2003-03-12T08:31:46Z

> For I2C Reset it is adviseable to cause at least a sequence of eight STOP
> one START and another STOP condition. Some Manufacturers (Microchip when I
> remember correctly) require that because in violation of the I2C Spec they
> do not recognize a STOP condition while expecting the Bits of a Byte.
> Otherwise you might end up writing an arbitrary value the last addressed
> location in your I2C memory if the previous transfer has been interrupted in
> an unfortunate state... (see also I2C Edge Conditions, which addresses a
> part of the Problem).

Hi

I have a DS1337 RTC which hangs if you press the reset button while doing
hwclock. To "unhang" the DS1337 I have to remove the battery :-(.
I figured the above I2C reset trick would help, but so far nothing helps.

I copied parts of mpc8xx/soft_i2c.c in my ppcboot(1.0.5) and hacked
a I2C Reset function that is called from misc_init_r().

Someone else that has this problem or can see what I am doing wrong?

This is my i2c reset hack:

#define PB_SCL 0x00000020 /* PB 26 */
#define PB_SDA 0x00000010 /* PB 27 */

#define SET_PB_BIT(bit) do { \
immr->im_cpm.cp_pbdir |= bit; /* output */ \
immr->im_cpm.cp_pbdat |= bit; /* set 1 */ \
udelay (5); \
} while (0)

#define RESET_PB_BIT(bit) do { \
immr->im_cpm.cp_pbdir |= bit; /* output */ \
immr->im_cpm.cp_pbdat &= ~bit; /* set 0 */ \
udelay (5); \
} while (0)
/*-----------------------------------------------------------------------
* START: High -> Low on SDA while SCL is High
*/
static void send_start (void)
{
volatile immap_t *immr = (immap_t *)CFG_IMMR;

SET_PB_BIT (PB_SCL);
udelay (10);
RESET_PB_BIT (PB_SDA);
udelay (20);
}

/*-----------------------------------------------------------------------
* STOP: Low -> High on SDA while SCL is High
*/
static void send_stop (void)
{
volatile immap_t *immr = (immap_t *)CFG_IMMR;

RESET_PB_BIT (PB_SDA);
udelay (10);
SET_PB_BIT (PB_SCL);
udelay (10);
SET_PB_BIT (PB_SDA);
udelay (20);
}

void my_i2c_reset(void)
{
volatile immap_t *immr = (immap_t *)CFG_IMMR;

immr->im_cpm.cp_pbpar &= ~(PB_SCL | PB_SDA); /* GPIO */
immr->im_cpm.cp_pbodr |= (PB_SCL | PB_SDA); /* Open Drain Output */

send_stop();
send_stop();
send_stop();
send_stop();
send_stop();
send_stop();
send_stop();
send_stop();

send_start();

send_stop();
}