Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Industrial I/O - generic interrupt based trigger support
0004  *
0005  * Copyright (c) 2008-2013 Jonathan Cameron
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/slab.h>
0013 
0014 #include <linux/iio/iio.h>
0015 #include <linux/iio/trigger.h>
0016 
0017 
0018 struct iio_interrupt_trigger_info {
0019     unsigned int irq;
0020 };
0021 
0022 static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private)
0023 {
0024     iio_trigger_poll(private);
0025     return IRQ_HANDLED;
0026 }
0027 
0028 static int iio_interrupt_trigger_probe(struct platform_device *pdev)
0029 {
0030     struct iio_interrupt_trigger_info *trig_info;
0031     struct iio_trigger *trig;
0032     unsigned long irqflags;
0033     struct resource *irq_res;
0034     int irq, ret = 0;
0035 
0036     irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
0037 
0038     if (irq_res == NULL)
0039         return -ENODEV;
0040 
0041     irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
0042 
0043     irq = irq_res->start;
0044 
0045     trig = iio_trigger_alloc(NULL, "irqtrig%d", irq);
0046     if (!trig) {
0047         ret = -ENOMEM;
0048         goto error_ret;
0049     }
0050 
0051     trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
0052     if (!trig_info) {
0053         ret = -ENOMEM;
0054         goto error_free_trigger;
0055     }
0056     iio_trigger_set_drvdata(trig, trig_info);
0057     trig_info->irq = irq;
0058     ret = request_irq(irq, iio_interrupt_trigger_poll,
0059               irqflags, trig->name, trig);
0060     if (ret) {
0061         dev_err(&pdev->dev,
0062             "request IRQ-%d failed", irq);
0063         goto error_free_trig_info;
0064     }
0065 
0066     ret = iio_trigger_register(trig);
0067     if (ret)
0068         goto error_release_irq;
0069     platform_set_drvdata(pdev, trig);
0070 
0071     return 0;
0072 
0073 /* First clean up the partly allocated trigger */
0074 error_release_irq:
0075     free_irq(irq, trig);
0076 error_free_trig_info:
0077     kfree(trig_info);
0078 error_free_trigger:
0079     iio_trigger_free(trig);
0080 error_ret:
0081     return ret;
0082 }
0083 
0084 static int iio_interrupt_trigger_remove(struct platform_device *pdev)
0085 {
0086     struct iio_trigger *trig;
0087     struct iio_interrupt_trigger_info *trig_info;
0088 
0089     trig = platform_get_drvdata(pdev);
0090     trig_info = iio_trigger_get_drvdata(trig);
0091     iio_trigger_unregister(trig);
0092     free_irq(trig_info->irq, trig);
0093     kfree(trig_info);
0094     iio_trigger_free(trig);
0095 
0096     return 0;
0097 }
0098 
0099 static struct platform_driver iio_interrupt_trigger_driver = {
0100     .probe = iio_interrupt_trigger_probe,
0101     .remove = iio_interrupt_trigger_remove,
0102     .driver = {
0103         .name = "iio_interrupt_trigger",
0104     },
0105 };
0106 
0107 module_platform_driver(iio_interrupt_trigger_driver);
0108 
0109 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
0110 MODULE_DESCRIPTION("Interrupt trigger for the iio subsystem");
0111 MODULE_LICENSE("GPL v2");