diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 05:17:02 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-28 05:17:02 +0400 |
commit | 9e4db1c3eed55c22328d8022c2c80adb3093833f (patch) | |
tree | 9643545e6bd182f1d3e19942f590a6a1e3198320 /drivers/mfd/ucb1x00-ts.c | |
parent | de8856d2c11f562c60ed9340a83db4a4f829a6e6 (diff) | |
parent | aae528d9a8ad79d4b21b1b723abc9447fdb0d200 (diff) | |
download | linux-9e4db1c3eed55c22328d8022c2c80adb3093833f.tar.xz |
Merge branch 'platforms' of git://git.linaro.org/people/rmk/linux-arm
Pull ARM platform updates from Russell King:
"This covers platform stuff for platforms I have a direct interest in
(iow, I have the hardware). Essentially:
- as we no longer support any other Acorn platforms other than RiscPC
anymore, we can collect all that code into mach-rpc.
- convert Acorn expansion card stuff to use IRQ allocation functions,
and get rid of NO_IRQ from there.
- cleanups to the ebsa110 platform to move some private stuff out of
its header files.
- large amount of SA11x0 updates:
- conversion of private DMA implementation to DMA engine support
(this actually gives us greater flexibility in drivers over the old
API.)
- re-worked ucb1x00 updates - convert to genirq, remove sa11x0
dependencies, fix various minor issues
- move platform specific sa11x0 framebuffer data into platform files
in arch/arm instead of keeping this in the driver itself
- update sa11x0 IrDA driver for DMA engine, and allow it to use DMA
for SIR transmissions as well as FIR
- rework sa1111 support for genirq, and irq allocation
- fix sa1111 IRQ support so it works again
- use sparse IRQ support
After this, I have one more pull request remaining from my current
set, which I think is going to be the most problematical as it
generates 8 conflicts."
Fixed up the trivial conflict in arch/arm/mach-rpc/Makefile as per
Russell.
* 'platforms' of git://git.linaro.org/people/rmk/linux-arm: (125 commits)
ARM: 7343/1: sa11x0: convert to sparse IRQ
ARM: 7342/2: sa1100: prepare for sparse irq conversion
ARM: 7341/1: input: prepare jornada720 keyboard and ts for sa11x0 sparse irq
ARM: 7340/1: rtc: sa1100: include mach/irqs.h instead of asm/irq.h
ARM: sa11x0: remove unused DMA controller definitions
ARM: sa11x0: remove old SoC private DMA driver
USB: sa1111: add hcd .reset method
USB: sa1111: add OHCI shutdown methods
USB: sa1111: reorganize ohci-sa1111.c
USB: sa1111: get rid of nasty printk(KERN_DEBUG "%s: ...", __FILE__)
USB: sa1111: sparse and checkpatch cleanups
ARM: sa11x0: don't static map sa1111
ARM: sa1111: use dev_err() rather than printk()
ARM: sa1111: cleanup sub-device registration and unregistration
ARM: sa1111: only setup DMA for DMA capable devices
ARM: sa1111: register sa1111 devices with dmabounce in bus notifier
ARM: sa1111: move USB interface register definitions to ohci-sa1111.c
ARM: sa1111: move PCMCIA interface register definitions to sa1111_generic.c
ARM: sa1111: move PS/2 interface register definitions to sa1111p2.c
ARM: sa1111: delete unused physical GPIO register definitions
...
Diffstat (limited to 'drivers/mfd/ucb1x00-ts.c')
-rw-r--r-- | drivers/mfd/ucb1x00-ts.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 63a3cbdfa3f3..1e0e20c0e082 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -20,8 +20,9 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#include <linux/smp.h> +#include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/spinlock.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/string.h> @@ -32,7 +33,6 @@ #include <linux/kthread.h> #include <linux/mfd/ucb1x00.h> -#include <mach/dma.h> #include <mach/collie.h> #include <asm/mach-types.h> @@ -42,6 +42,8 @@ struct ucb1x00_ts { struct input_dev *idev; struct ucb1x00 *ucb; + spinlock_t irq_lock; + unsigned irq_disabled; wait_queue_head_t irq_wait; struct task_struct *rtask; u16 x_res; @@ -238,7 +240,12 @@ static int ucb1x00_thread(void *_ts) if (ucb1x00_ts_pen_down(ts)) { set_current_state(TASK_INTERRUPTIBLE); - ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); + spin_lock_irq(&ts->irq_lock); + if (ts->irq_disabled) { + ts->irq_disabled = 0; + enable_irq(ts->ucb->irq_base + UCB_IRQ_TSPX); + } + spin_unlock_irq(&ts->irq_lock); ucb1x00_disable(ts->ucb); /* @@ -281,23 +288,37 @@ static int ucb1x00_thread(void *_ts) * We only detect touch screen _touches_ with this interrupt * handler, and even then we just schedule our task. */ -static void ucb1x00_ts_irq(int idx, void *id) +static irqreturn_t ucb1x00_ts_irq(int irq, void *id) { struct ucb1x00_ts *ts = id; - ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); + spin_lock(&ts->irq_lock); + ts->irq_disabled = 1; + disable_irq_nosync(ts->ucb->irq_base + UCB_IRQ_TSPX); + spin_unlock(&ts->irq_lock); wake_up(&ts->irq_wait); + + return IRQ_HANDLED; } static int ucb1x00_ts_open(struct input_dev *idev) { struct ucb1x00_ts *ts = input_get_drvdata(idev); + unsigned long flags = 0; int ret = 0; BUG_ON(ts->rtask); + if (machine_is_collie()) + flags = IRQF_TRIGGER_RISING; + else + flags = IRQF_TRIGGER_FALLING; + + ts->irq_disabled = 0; + init_waitqueue_head(&ts->irq_wait); - ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); + ret = request_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ucb1x00_ts_irq, + flags, "ucb1x00-ts", ts); if (ret < 0) goto out; @@ -314,7 +335,7 @@ static int ucb1x00_ts_open(struct input_dev *idev) if (!IS_ERR(ts->rtask)) { ret = 0; } else { - ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); + free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts); ts->rtask = NULL; ret = -EFAULT; } @@ -334,7 +355,7 @@ static void ucb1x00_ts_close(struct input_dev *idev) kthread_stop(ts->rtask); ucb1x00_enable(ts->ucb); - ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); + free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts); ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); ucb1x00_disable(ts->ucb); } @@ -359,11 +380,13 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) ts->ucb = dev->ucb; ts->idev = idev; ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; + spin_lock_init(&ts->irq_lock); idev->name = "Touchscreen panel"; idev->id.product = ts->ucb->id; idev->open = ucb1x00_ts_open; idev->close = ucb1x00_ts_close; + idev->dev.parent = &ts->ucb->dev; idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |