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