[PATCH] powermac: Fix i2c on keywest based chips

The new i2c implementation for PowerMac has a regression that causes the
hardware to go out of state when probing non-existent devices. While
fixing that, I also found & fixed a couple of other corner cases. This
fixes booting with a pbbuttons version that scans the i2c bus for an LMU
controller among others. Tested on a dual G5 with thermal control (which
has heavy i2c activity) with no problem so far.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by Benjamin Herrenschmidt and committed by Paul Mackerras 60162e49 28897731

+35 -43
+35 -43
arch/powerpc/platforms/powermac/low_i2c.c
··· 231 return isr; 232 } 233 234 static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr) 235 { 236 u8 ack; ··· 254 } 255 256 if (isr == 0) { 257 if (host->state != state_stop) { 258 - DBG_LOW("KW: Timeout !\n"); 259 - host->result = -EIO; 260 - goto stop; 261 } 262 - if (host->state == state_stop) { 263 - ack = kw_read_reg(reg_status); 264 - if (ack & KW_I2C_STAT_BUSY) 265 - kw_write_reg(reg_status, 0); 266 - host->state = state_idle; 267 - kw_write_reg(reg_ier, 0x00); 268 - if (!host->polled) 269 - complete(&host->complete); 270 - } 271 return; 272 } 273 274 if (isr & KW_I2C_IRQ_ADDR) { 275 ack = kw_read_reg(reg_status); 276 if (host->state != state_addr) { 277 - kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); 278 WRONG_STATE("KW_I2C_IRQ_ADDR"); 279 - host->result = -EIO; 280 - goto stop; 281 } 282 if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { 283 - host->result = -ENODEV; 284 - DBG_LOW("KW: NAK on address\n"); 285 host->state = state_stop; 286 - return; 287 } else { 288 - if (host->len == 0) { 289 - kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); 290 - goto stop; 291 - } 292 - if (host->rw) { 293 host->state = state_read; 294 if (host->len > 1) 295 kw_write_reg(reg_control, ··· 310 ack = kw_read_reg(reg_status); 311 if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { 312 DBG_LOW("KW: nack on data write\n"); 313 - host->result = -EIO; 314 - goto stop; 315 } else if (host->len) { 316 kw_write_reg(reg_data, *(host->data++)); 317 host->len--; 318 - } else { 319 - kw_write_reg(reg_control, KW_I2C_CTL_STOP); 320 - host->state = state_stop; 321 - host->result = 0; 322 - } 323 - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); 324 } else { 325 - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); 326 WRONG_STATE("KW_I2C_IRQ_DATA"); 327 - if (host->state != state_stop) { 328 - host->result = -EIO; 329 - goto stop; 330 - } 331 } 332 } 333 334 if (isr & KW_I2C_IRQ_STOP) { ··· 336 complete(&host->complete); 337 } 338 339 if (isr & KW_I2C_IRQ_START) 340 kw_write_reg(reg_isr, KW_I2C_IRQ_START); 341 342 - return; 343 - stop: 344 - kw_write_reg(reg_control, KW_I2C_CTL_STOP); 345 - host->state = state_stop; 346 - return; 347 } 348 349 /* Interrupt handler */ ··· 536 return NULL; 537 } 538 539 - /* Make sure IRA is disabled */ 540 kw_write_reg(reg_ier, 0); 541 542 /* Request chip interrupt */ 543 - if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host)) 544 host->irq = NO_IRQ; 545 546 printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
··· 231 return isr; 232 } 233 234 + static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result) 235 + { 236 + kw_write_reg(reg_control, KW_I2C_CTL_STOP); 237 + host->state = state_stop; 238 + host->result = result; 239 + } 240 + 241 + 242 static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr) 243 { 244 u8 ack; ··· 246 } 247 248 if (isr == 0) { 249 + printk(KERN_WARNING "low_i2c: Timeout in i2c transfer" 250 + " on keywest !\n"); 251 if (host->state != state_stop) { 252 + kw_i2c_do_stop(host, -EIO); 253 + return; 254 } 255 + ack = kw_read_reg(reg_status); 256 + if (ack & KW_I2C_STAT_BUSY) 257 + kw_write_reg(reg_status, 0); 258 + host->state = state_idle; 259 + kw_write_reg(reg_ier, 0x00); 260 + if (!host->polled) 261 + complete(&host->complete); 262 return; 263 } 264 265 if (isr & KW_I2C_IRQ_ADDR) { 266 ack = kw_read_reg(reg_status); 267 if (host->state != state_addr) { 268 WRONG_STATE("KW_I2C_IRQ_ADDR"); 269 + kw_i2c_do_stop(host, -EIO); 270 } 271 if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { 272 + host->result = -ENXIO; 273 host->state = state_stop; 274 + DBG_LOW("KW: NAK on address\n"); 275 } else { 276 + if (host->len == 0) 277 + kw_i2c_do_stop(host, 0); 278 + else if (host->rw) { 279 host->state = state_read; 280 if (host->len > 1) 281 kw_write_reg(reg_control, ··· 308 ack = kw_read_reg(reg_status); 309 if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { 310 DBG_LOW("KW: nack on data write\n"); 311 + host->result = -EFBIG; 312 + host->state = state_stop; 313 } else if (host->len) { 314 kw_write_reg(reg_data, *(host->data++)); 315 host->len--; 316 + } else 317 + kw_i2c_do_stop(host, 0); 318 } else { 319 WRONG_STATE("KW_I2C_IRQ_DATA"); 320 + if (host->state != state_stop) 321 + kw_i2c_do_stop(host, -EIO); 322 } 323 + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); 324 } 325 326 if (isr & KW_I2C_IRQ_STOP) { ··· 340 complete(&host->complete); 341 } 342 343 + /* Below should only happen in manual mode which we don't use ... */ 344 if (isr & KW_I2C_IRQ_START) 345 kw_write_reg(reg_isr, KW_I2C_IRQ_START); 346 347 } 348 349 /* Interrupt handler */ ··· 544 return NULL; 545 } 546 547 + /* Make sure IRQ is disabled */ 548 kw_write_reg(reg_ier, 0); 549 550 /* Request chip interrupt */ 551 + if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host)) 552 host->irq = NO_IRQ; 553 554 printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",