diff options
Diffstat (limited to 'arch/powerpc/platforms/powermac/low_i2c.c')
| -rw-r--r-- | arch/powerpc/platforms/powermac/low_i2c.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 345e2da5676..7553b6a77c6 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -33,7 +33,7 @@ #include <linux/types.h> #include <linux/sched.h> #include <linux/init.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/adb.h> #include <linux/pmu.h> #include <linux/delay.h> @@ -43,6 +43,7 @@ #include <linux/timer.h> #include <linux/mutex.h> #include <linux/i2c.h> +#include <linux/slab.h> #include <asm/keylargo.h> #include <asm/uninorth.h> #include <asm/io.h> @@ -365,11 +366,20 @@ static void kw_i2c_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&host->lock, flags); + + /* + * If the timer is pending, that means we raced with the + * irq, in which case we just return + */ + if (timer_pending(&host->timeout_timer)) + goto skip; + kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr)); if (host->state != state_idle) { host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT; add_timer(&host->timeout_timer); } + skip: spin_unlock_irqrestore(&host->lock, flags); } @@ -442,7 +452,7 @@ static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, */ if (use_irq) { /* Clear completion */ - INIT_COMPLETION(host->complete); + reinit_completion(&host->complete); /* Ack stale interrupts */ kw_write_reg(reg_isr, kw_read_reg(reg_isr)); /* Arm timeout */ @@ -541,11 +551,12 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) /* Make sure IRQ is disabled */ kw_write_reg(reg_ier, 0); - /* Request chip interrupt. We set IRQF_TIMER because we don't + /* Request chip interrupt. We set IRQF_NO_SUSPEND because we don't * want that interrupt disabled between the 2 passes of driver * suspend or we'll have issues running the pfuncs */ - if (request_irq(host->irq, kw_i2c_irq, IRQF_TIMER, "keywest i2c", host)) + if (request_irq(host->irq, kw_i2c_irq, IRQF_NO_SUSPEND, + "keywest i2c", host)) host->irq = NO_IRQ; printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n", @@ -591,7 +602,7 @@ static void __init kw_i2c_probe(void) /* Probe keywest-i2c busses */ for_each_compatible_node(np, "i2c","keywest-i2c") { struct pmac_i2c_host_kw *host; - int multibus, chans, i; + int multibus; /* Found one, init a host structure */ host = kw_i2c_host_init(np); @@ -613,6 +624,8 @@ static void __init kw_i2c_probe(void) * parent type */ if (multibus) { + int chans, i; + parent = of_get_parent(np); if (parent == NULL) continue; @@ -704,7 +717,7 @@ static int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, return -EINVAL; } - INIT_COMPLETION(comp); + reinit_completion(&comp); req->data[0] = PMU_I2C_CMD; req->reply[0] = 0xff; req->nbytes = sizeof(struct pmu_i2c_hdr) + 1; @@ -735,7 +748,7 @@ static int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, hdr->bus = PMU_I2C_BUS_STATUS; - INIT_COMPLETION(comp); + reinit_completion(&comp); req->data[0] = PMU_I2C_CMD; req->reply[0] = 0xff; req->nbytes = 2; @@ -900,7 +913,7 @@ static void __init smu_i2c_probe(void) printk(KERN_INFO "SMU i2c %s\n", controller->full_name); /* Look for childs, note that they might not be of the right - * type as older device trees mix i2c busses and other thigns + * type as older device trees mix i2c busses and other things * at the same level */ for (busnode = NULL; @@ -1257,8 +1270,7 @@ static void pmac_i2c_do_end(struct pmf_function *func, void *instdata) if (inst == NULL) return; pmac_i2c_close(inst->bus); - if (inst) - kfree(inst); + kfree(inst); } static int pmac_i2c_do_read(PMF_STD_ARGS, u32 len) @@ -1491,6 +1503,7 @@ static int __init pmac_i2c_create_platform_devices(void) if (bus->platform_dev == NULL) return -ENOMEM; bus->platform_dev->dev.platform_data = bus; + bus->platform_dev->dev.of_node = bus->busnode; platform_device_add(bus->platform_dev); } |
