When working with an SMBUS device that implements the SMBUS reset function, there is a basic problem with the i2c-mpc driver. Even in the interrupt driven mode, the indirect call to schedule() in i2c_wait() can cause a delay exceeding 35ms while SCL is low. SCL low for >35ms will reset the I2C interface of certain slave devices. This behavior has been observed with the ADT74xx series fan controllers controlled with i2c-mpc.c on an MPC8347 processor. A workaround is to have application layer code retry the failed operation until it wins the race [schedule() vs. SMBUS reset]. However, it would be best to follow the lead of other I2C drivers and perform realtime operations in the ISR. Ben Stoltz line numbers reference http://lxr.linux.no/linux+v2.6.39/drivers/i2c/busses/i2c-mpc.c 85 static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) 86 { 87 struct mpc_i2c *i2c = dev_id; 88 if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) { 89 /* Read again to allow register to stabilise */ 90 i2c->interrupt = readb(i2c->base + MPC_I2C_SR); 91 writeb(0, i2c->base + MPC_I2C_SR); Note: SCL is held low. The HW controller does not know if next change is to SCL or SDA, so it maintains SCL low until the driver reads or writes I2Cn.DR or writes I2Cn.CR. 92 wake_up(&i2c->queue); 93 } 94 return IRQ_HANDLED; 95 } 119 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) 120 { 121 unsigned long orig_jiffies = jiffies; 122 u32 x; 123 int result = 0; 124 125 if (!i2c->irq) { ... 137 } else { 138 /* Interrupt mode */ 139 result = wait_event_timeout(i2c->queue, 140 (i2c->interrupt & CSR_MIF), timeout); 141 142 if (unlikely(!(i2c->interrupt & CSR_MIF))) { 143 dev_dbg(i2c->dev, "wait timeout\n"); 144 writeccr(i2c, 0); 145 result = -ETIMEDOUT; 146 } 147 148 x = i2c->interrupt; 149 ... 171 return 0; 172 } 428 static int mpc_write(struct mpc_i2c *i2c, int target, 429 const u8 *data, int length, int restart) 430 { 431 int i, result; 432 unsigned timeout = i2c->adap.timeout; 433 u32 flags = restart ? CCR_RSTA : 0; 434 435 /* Start as master */ 436 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); 437 /* Write target byte */ 438 writeb((target << 1), i2c->base + MPC_I2C_DR); 439 440 result = i2c_wait(i2c, timeout, 1); 441 if (result < 0) 442 return result; // BUG W.R.T. SMBUS reset. delay due to schedule() called at line 139 may exceed 35ms while SCL was low. // Next byte will be NoAck. 443 444 for (i = 0; i < length; i ++) { 445 /* Write data byte */ 446 writeb(data[i], i2c->base + MPC_I2C_DR); 447 448 result = i2c_wait(i2c, timeout, 1); // BUG W.R.T. SMBUS reset. delay due to schedule() called at line 139 may exceed 35ms while SCL was low. // Next byte will be NoAck. 449 if (result < 0) 450 return result; 451 } 452 453 return 0; 454} -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html