cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iio-trig-interrupt.c (2494B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Industrial I/O - generic interrupt based trigger support
      4 *
      5 * Copyright (c) 2008-2013 Jonathan Cameron
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/platform_device.h>
     11#include <linux/interrupt.h>
     12#include <linux/slab.h>
     13
     14#include <linux/iio/iio.h>
     15#include <linux/iio/trigger.h>
     16
     17
     18struct iio_interrupt_trigger_info {
     19	unsigned int irq;
     20};
     21
     22static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private)
     23{
     24	iio_trigger_poll(private);
     25	return IRQ_HANDLED;
     26}
     27
     28static int iio_interrupt_trigger_probe(struct platform_device *pdev)
     29{
     30	struct iio_interrupt_trigger_info *trig_info;
     31	struct iio_trigger *trig;
     32	unsigned long irqflags;
     33	struct resource *irq_res;
     34	int irq, ret = 0;
     35
     36	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
     37
     38	if (irq_res == NULL)
     39		return -ENODEV;
     40
     41	irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
     42
     43	irq = irq_res->start;
     44
     45	trig = iio_trigger_alloc(NULL, "irqtrig%d", irq);
     46	if (!trig) {
     47		ret = -ENOMEM;
     48		goto error_ret;
     49	}
     50
     51	trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
     52	if (!trig_info) {
     53		ret = -ENOMEM;
     54		goto error_free_trigger;
     55	}
     56	iio_trigger_set_drvdata(trig, trig_info);
     57	trig_info->irq = irq;
     58	ret = request_irq(irq, iio_interrupt_trigger_poll,
     59			  irqflags, trig->name, trig);
     60	if (ret) {
     61		dev_err(&pdev->dev,
     62			"request IRQ-%d failed", irq);
     63		goto error_free_trig_info;
     64	}
     65
     66	ret = iio_trigger_register(trig);
     67	if (ret)
     68		goto error_release_irq;
     69	platform_set_drvdata(pdev, trig);
     70
     71	return 0;
     72
     73/* First clean up the partly allocated trigger */
     74error_release_irq:
     75	free_irq(irq, trig);
     76error_free_trig_info:
     77	kfree(trig_info);
     78error_free_trigger:
     79	iio_trigger_free(trig);
     80error_ret:
     81	return ret;
     82}
     83
     84static int iio_interrupt_trigger_remove(struct platform_device *pdev)
     85{
     86	struct iio_trigger *trig;
     87	struct iio_interrupt_trigger_info *trig_info;
     88
     89	trig = platform_get_drvdata(pdev);
     90	trig_info = iio_trigger_get_drvdata(trig);
     91	iio_trigger_unregister(trig);
     92	free_irq(trig_info->irq, trig);
     93	kfree(trig_info);
     94	iio_trigger_free(trig);
     95
     96	return 0;
     97}
     98
     99static struct platform_driver iio_interrupt_trigger_driver = {
    100	.probe = iio_interrupt_trigger_probe,
    101	.remove = iio_interrupt_trigger_remove,
    102	.driver = {
    103		.name = "iio_interrupt_trigger",
    104	},
    105};
    106
    107module_platform_driver(iio_interrupt_trigger_driver);
    108
    109MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
    110MODULE_DESCRIPTION("Interrupt trigger for the iio subsystem");
    111MODULE_LICENSE("GPL v2");