Skip to content

Commit 92ba4fe

Browse files
Samu Onkalotorvalds
authored andcommitted
lis3: add skeletons for interrupt handlers
Original lis3 driver didn't provide interrupt handler(s) for click or threshold event handling. This patch adds threaded handlers for one or two interrupt lines for 8 bit device. Actual content for interrupt handling is provided in the separate patch. Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com> Tested-by: Daniel Mack <daniel@caiaq.de> Acked-by: Eric Piel <eric.piel@tremplin-utc.net> Cc: Pavel Machek <pavel@ucw.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 342c5f1 commit 92ba4fe

File tree

2 files changed

+65
-23
lines changed

2 files changed

+65
-23
lines changed

drivers/hwmon/lis3lv02d.c

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
251251

252252
static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
253253
{
254+
if (!test_bit(0, &lis3_dev.misc_opened))
255+
goto out;
256+
254257
/*
255258
* Be careful: on some HP laptops the bios force DD when on battery and
256259
* the lid is closed. This leads to interrupts as soon as a little move
@@ -260,44 +263,35 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
260263

261264
wake_up_interruptible(&lis3_dev.misc_wait);
262265
kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
266+
out:
267+
if (lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
268+
lis3_dev.idev->input->users)
269+
return IRQ_WAKE_THREAD;
263270
return IRQ_HANDLED;
264271
}
265272

266-
static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
273+
static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
267274
{
268-
int ret;
275+
return IRQ_HANDLED;
276+
}
269277

278+
static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
279+
{
280+
return IRQ_HANDLED;
281+
}
282+
283+
static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
284+
{
270285
if (test_and_set_bit(0, &lis3_dev.misc_opened))
271286
return -EBUSY; /* already open */
272287

273288
atomic_set(&lis3_dev.count, 0);
274-
275-
/*
276-
* The sensor can generate interrupts for free-fall and direction
277-
* detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
278-
* the things simple and _fast_ we activate it only for free-fall, so
279-
* no need to read register (very slow with ACPI). For the same reason,
280-
* we forbid shared interrupts.
281-
*
282-
* IRQF_TRIGGER_RISING seems pointless on HP laptops because the
283-
* io-apic is not configurable (and generates a warning) but I keep it
284-
* in case of support for other hardware.
285-
*/
286-
ret = request_irq(lis3_dev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING,
287-
DRIVER_NAME, &lis3_dev);
288-
289-
if (ret) {
290-
clear_bit(0, &lis3_dev.misc_opened);
291-
printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq);
292-
return -EBUSY;
293-
}
294289
return 0;
295290
}
296291

297292
static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
298293
{
299294
fasync_helper(-1, file, 0, &lis3_dev.async_queue);
300-
free_irq(lis3_dev.irq, &lis3_dev);
301295
clear_bit(0, &lis3_dev.misc_opened); /* release the device */
302296
return 0;
303297
}
@@ -434,6 +428,11 @@ EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
434428

435429
void lis3lv02d_joystick_disable(void)
436430
{
431+
if (lis3_dev.irq)
432+
free_irq(lis3_dev.irq, &lis3_dev);
433+
if (lis3_dev.pdata && lis3_dev.pdata->irq2)
434+
free_irq(lis3_dev.pdata->irq2, &lis3_dev);
435+
437436
if (!lis3_dev.idev)
438437
return;
439438

@@ -524,6 +523,7 @@ EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
524523
static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
525524
struct lis3lv02d_platform_data *p)
526525
{
526+
int err;
527527
int ctrl2 = p->hipass_ctrl;
528528

529529
if (p->click_flags) {
@@ -554,6 +554,18 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
554554
}
555555
/* Configure hipass filters */
556556
dev->write(dev, CTRL_REG2, ctrl2);
557+
558+
if (p->irq2) {
559+
err = request_threaded_irq(p->irq2,
560+
NULL,
561+
lis302dl_interrupt_thread2_8b,
562+
IRQF_TRIGGER_RISING |
563+
IRQF_ONESHOT,
564+
DRIVER_NAME, &lis3_dev);
565+
if (err < 0)
566+
printk(KERN_ERR DRIVER_NAME
567+
"No second IRQ. Limited functionality\n");
568+
}
557569
}
558570

559571
/*
@@ -562,6 +574,9 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
562574
*/
563575
int lis3lv02d_init_device(struct lis3lv02d *dev)
564576
{
577+
int err;
578+
irq_handler_t thread_fn;
579+
565580
dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
566581

567582
switch (dev->whoami) {
@@ -616,6 +631,32 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
616631
goto out;
617632
}
618633

634+
/*
635+
* The sensor can generate interrupts for free-fall and direction
636+
* detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
637+
* the things simple and _fast_ we activate it only for free-fall, so
638+
* no need to read register (very slow with ACPI). For the same reason,
639+
* we forbid shared interrupts.
640+
*
641+
* IRQF_TRIGGER_RISING seems pointless on HP laptops because the
642+
* io-apic is not configurable (and generates a warning) but I keep it
643+
* in case of support for other hardware.
644+
*/
645+
if (dev->whoami == WAI_8B)
646+
thread_fn = lis302dl_interrupt_thread1_8b;
647+
else
648+
thread_fn = NULL;
649+
650+
err = request_threaded_irq(dev->irq, lis302dl_interrupt,
651+
thread_fn,
652+
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
653+
DRIVER_NAME, &lis3_dev);
654+
655+
if (err < 0) {
656+
printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n");
657+
goto out;
658+
}
659+
619660
if (misc_register(&lis3lv02d_misc_device))
620661
printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
621662
out:

include/linux/lis3lv02d.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct lis3lv02d_platform_data {
6767
/* Limits for selftest are specified in chip data sheet */
6868
s16 st_min_limits[3]; /* min pass limit x, y, z */
6969
s16 st_max_limits[3]; /* max pass limit x, y, z */
70+
int irq2;
7071
};
7172

7273
#endif /* __LIS3LV02D_H_ */

0 commit comments

Comments
 (0)