/* * I2C is a synchronous protocol and resets of the processor in the middle * of an access can block the I2C Bus until a powerdown of the full unit is * done. This function toggles the SCL until the SCL and SCA line are * released, but max. 16 times, after this a I2C start-sequence is sent. * This I2C Deblocking mechanism was developed by Keymile in association * with Anatech and Atmel in 1998. */ int i2c_make_abort(void) { #if defined(CONFIG_HARD_I2C) && !defined(MACH_TYPE_KM_KIRKWOOD) immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ; i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c; /* * disable I2C controller first, otherwhise it thinks we want to * talk to the slave port... */ clrbits_8(&i2c->i2c_i2mod, 0x01); /* Set the PortPins to GPIO */ setports(1); #endif int scl_state = 0; int sda_state = 0; int i = 0; int ret = 0; if (!get_sda()) { ret = -1; while (i < 16) { i++; set_scl(0); udelay(DELAY_ABORT_SEQ); set_scl(1); udelay(DELAY_ABORT_SEQ); scl_state = get_scl(); sda_state = get_sda(); if (scl_state && sda_state) { ret = 0; printf("[INFO] i2c abort after %d clocks\n", i); break; } } } if (ret == 0) for (i = 0; i < 5; i++) i2c_write_start_seq(); else printf("[ERROR] i2c abort failed\n"); /* respect stop setup time */ udelay(DELAY_ABORT_SEQ); set_scl(1); udelay(DELAY_ABORT_SEQ); set_sda(1); get_sda(); #if defined(CONFIG_HARD_I2C) /* Set the PortPins back to use for I2C */ setports(0); #endif return ret; }
/* * I2C is a synchronous protocol and resets of the processor in the middle * of an access can block the I2C Bus until a powerdown of the full unit is * done. This function toggles the SCL until the SCL and SCA line are * released, but max. 16 times, after this a I2C start-sequence is sent. * This I2C Deblocking mechanism was developed by Keymile in association * with Anatech and Atmel in 1998. */ int i2c_make_abort(void) { int scl_state = 0; int sda_state = 0; int i = 0; int ret = 0; if (!get_sda()) { ret = -1; while (i < 16) { i++; set_scl(0); udelay(DELAY_ABORT_SEQ); set_scl(1); udelay(DELAY_ABORT_SEQ); scl_state = get_scl(); sda_state = get_sda(); if (scl_state && sda_state) { ret = 0; break; } } } if (ret == 0) for (i = 0; i < 5; i++) i2c_write_start_seq(); /* respect stop setup time */ udelay(DELAY_ABORT_SEQ); set_scl(1); udelay(DELAY_ABORT_SEQ); set_sda(1); get_sda(); return ret; }