X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fplatforms%2Fpowermac%2Flow_i2c.c;h=87eb6bb7f0e72a406baf9d129476d4e2cd4c5f6c;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=c896ce83d412917da2820292c32c9b6e4c32dcd1;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index c896ce83d..87eb6bb7f 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -231,14 +231,6 @@ static u8 kw_i2c_wait_interrupt(struct pmac_i2c_host_kw *host) return isr; } -static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result) -{ - kw_write_reg(reg_control, KW_I2C_CTL_STOP); - host->state = state_stop; - host->result = result; -} - - static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr) { u8 ack; @@ -254,36 +246,42 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr) } if (isr == 0) { - printk(KERN_WARNING "low_i2c: Timeout in i2c transfer" - " on keywest !\n"); if (host->state != state_stop) { - kw_i2c_do_stop(host, -EIO); - return; + DBG_LOW("KW: Timeout !\n"); + host->result = -EIO; + goto stop; + } + if (host->state == state_stop) { + ack = kw_read_reg(reg_status); + if (ack & KW_I2C_STAT_BUSY) + kw_write_reg(reg_status, 0); + host->state = state_idle; + kw_write_reg(reg_ier, 0x00); + if (!host->polled) + complete(&host->complete); } - ack = kw_read_reg(reg_status); - if (ack & KW_I2C_STAT_BUSY) - kw_write_reg(reg_status, 0); - host->state = state_idle; - kw_write_reg(reg_ier, 0x00); - if (!host->polled) - complete(&host->complete); return; } if (isr & KW_I2C_IRQ_ADDR) { ack = kw_read_reg(reg_status); if (host->state != state_addr) { + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); WRONG_STATE("KW_I2C_IRQ_ADDR"); - kw_i2c_do_stop(host, -EIO); + host->result = -EIO; + goto stop; } if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { - host->result = -ENXIO; - host->state = state_stop; + host->result = -ENODEV; DBG_LOW("KW: NAK on address\n"); + host->state = state_stop; + return; } else { - if (host->len == 0) - kw_i2c_do_stop(host, 0); - else if (host->rw) { + if (host->len == 0) { + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + goto stop; + } + if (host->rw) { host->state = state_read; if (host->len > 1) kw_write_reg(reg_control, @@ -310,19 +308,25 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr) ack = kw_read_reg(reg_status); if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { DBG_LOW("KW: nack on data write\n"); - host->result = -EFBIG; - host->state = state_stop; + host->result = -EIO; + goto stop; } else if (host->len) { kw_write_reg(reg_data, *(host->data++)); host->len--; - } else - kw_i2c_do_stop(host, 0); + } else { + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + host->state = state_stop; + host->result = 0; + } + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); } else { + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); WRONG_STATE("KW_I2C_IRQ_DATA"); - if (host->state != state_stop) - kw_i2c_do_stop(host, -EIO); + if (host->state != state_stop) { + host->result = -EIO; + goto stop; + } } - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); } if (isr & KW_I2C_IRQ_STOP) { @@ -336,10 +340,14 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr) complete(&host->complete); } - /* Below should only happen in manual mode which we don't use ... */ if (isr & KW_I2C_IRQ_START) kw_write_reg(reg_isr, KW_I2C_IRQ_START); + return; + stop: + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + host->state = state_stop; + return; } /* Interrupt handler */ @@ -536,11 +544,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) return NULL; } - /* Make sure IRQ is disabled */ + /* Make sure IRA is disabled */ kw_write_reg(reg_ier, 0); /* Request chip interrupt */ - if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host)) + if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host)) host->irq = NO_IRQ; printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n", @@ -1157,7 +1165,6 @@ EXPORT_SYMBOL_GPL(pmac_i2c_xfer); /* some quirks for platform function decoding */ enum { pmac_i2c_quirk_invmask = 0x00000001u, - pmac_i2c_quirk_skip = 0x00000002u, }; static void pmac_i2c_devscan(void (*callback)(struct device_node *dev, @@ -1173,15 +1180,6 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev, /* XXX Study device-tree's & apple drivers are get the quirks * right ! */ - /* Workaround: It seems that running the clockspreading - * properties on the eMac will cause lockups during boot. - * The machine seems to work fine without that. So for now, - * let's make sure i2c-hwclock doesn't match about "imic" - * clocks and we'll figure out if we really need to do - * something special about those later. - */ - { "i2c-hwclock", "imic5002", pmac_i2c_quirk_skip }, - { "i2c-hwclock", "imic5003", pmac_i2c_quirk_skip }, { "i2c-hwclock", NULL, pmac_i2c_quirk_invmask }, { "i2c-cpu-voltage", NULL, 0}, { "temp-monitor", NULL, 0 }, @@ -1208,8 +1206,6 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev, if (p->compatible && !device_is_compatible(np, p->compatible)) continue; - if (p->quirks & pmac_i2c_quirk_skip) - break; callback(np, p->quirks); break; } @@ -1461,9 +1457,6 @@ int __init pmac_i2c_init(void) return 0; i2c_inited = 1; - if (!machine_is(powermac)) - return 0; - /* Probe keywest-i2c busses */ kw_i2c_probe();