Commit ca481398 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Jonathan Cameron
Browse files

iio: dummy: evgen: use irq_sim



Switch to using the recently added interrupt simulator for dummy irqs.

Signed-off-by: default avatarBartosz Golaszewski <brgl@bgdev.pl>
Reviewed-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Tested-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 4546813a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ menu "IIO dummy driver"
	depends on IIO

config IIO_DUMMY_EVGEN
	select IRQ_WORK
	select IRQ_SIM
	tristate

config IIO_SIMPLE_DUMMY
+19 −70
Original line number Diff line number Diff line
@@ -24,97 +24,46 @@
#include "iio_dummy_evgen.h"
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/irq_work.h>
#include <linux/irq_sim.h>

/* Fiddly bit of faking and irq without hardware */
#define IIO_EVENTGEN_NO 10

/**
 * struct iio_dummy_handle_irq - helper struct to simulate interrupt generation
 * @work: irq_work used to run handlers from hardirq context
 * @irq: fake irq line number to trigger an interrupt
 */
struct iio_dummy_handle_irq {
	struct irq_work work;
	int irq;
};

/**
 * struct iio_dummy_evgen - evgen state
 * @chip: irq chip we are faking
 * @base: base of irq range
 * @enabled: mask of which irqs are enabled
 * @inuse: mask of which irqs are connected
 * @regs: irq regs we are faking
 * @lock: protect the evgen state
 * @handler: helper for a 'hardware-like' interrupt simulation
 * @inuse: mask of which irqs are connected
 * @irq_sim: interrupt simulator
 * @base: base of irq range
 */
struct iio_dummy_eventgen {
	struct irq_chip chip;
	int base;
	bool enabled[IIO_EVENTGEN_NO];
	bool inuse[IIO_EVENTGEN_NO];
	struct iio_dummy_regs regs[IIO_EVENTGEN_NO];
	struct mutex lock;
	struct iio_dummy_handle_irq handler;
	bool inuse[IIO_EVENTGEN_NO];
	struct irq_sim irq_sim;
	int base;
};

/* We can only ever have one instance of this 'device' */
static struct iio_dummy_eventgen *iio_evgen;
static const char *iio_evgen_name = "iio_dummy_evgen";

static void iio_dummy_event_irqmask(struct irq_data *d)
{
	struct irq_chip *chip = irq_data_get_irq_chip(d);
	struct iio_dummy_eventgen *evgen =
		container_of(chip, struct iio_dummy_eventgen, chip);

	evgen->enabled[d->irq - evgen->base] = false;
}

static void iio_dummy_event_irqunmask(struct irq_data *d)
{
	struct irq_chip *chip = irq_data_get_irq_chip(d);
	struct iio_dummy_eventgen *evgen =
		container_of(chip, struct iio_dummy_eventgen, chip);

	evgen->enabled[d->irq - evgen->base] = true;
}

static void iio_dummy_work_handler(struct irq_work *work)
{
	struct iio_dummy_handle_irq *irq_handler;

	irq_handler = container_of(work, struct iio_dummy_handle_irq, work);
	handle_simple_irq(irq_to_desc(irq_handler->irq));
}

static int iio_dummy_evgen_create(void)
{
	int ret, i;
	int ret;

	iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL);
	if (!iio_evgen)
		return -ENOMEM;

	iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0);
	if (iio_evgen->base < 0) {
		ret = iio_evgen->base;
	ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
	if (ret) {
		kfree(iio_evgen);
		return ret;
	}
	iio_evgen->chip.name = iio_evgen_name;
	iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask;
	iio_evgen->chip.irq_unmask = &iio_dummy_event_irqunmask;
	for (i = 0; i < IIO_EVENTGEN_NO; i++) {
		irq_set_chip(iio_evgen->base + i, &iio_evgen->chip);
		irq_set_handler(iio_evgen->base + i, &handle_simple_irq);
		irq_modify_status(iio_evgen->base + i,
				  IRQ_NOREQUEST | IRQ_NOAUTOEN,
				  IRQ_NOPROBE);
	}
	init_irq_work(&iio_evgen->handler.work, iio_dummy_work_handler);

	iio_evgen->base = irq_sim_irqnum(&iio_evgen->irq_sim, 0);
	mutex_init(&iio_evgen->lock);

	return 0;
}

@@ -132,15 +81,17 @@ int iio_dummy_evgen_get_irq(void)
		return -ENODEV;

	mutex_lock(&iio_evgen->lock);
	for (i = 0; i < IIO_EVENTGEN_NO; i++)
	for (i = 0; i < IIO_EVENTGEN_NO; i++) {
		if (!iio_evgen->inuse[i]) {
			ret = iio_evgen->base + i;
			ret = irq_sim_irqnum(&iio_evgen->irq_sim, i);
			iio_evgen->inuse[i] = true;
			break;
		}
	}
	mutex_unlock(&iio_evgen->lock);
	if (i == IIO_EVENTGEN_NO)
		return -ENOMEM;

	return ret;
}
EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq);
@@ -167,7 +118,7 @@ EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs);

static void iio_dummy_evgen_free(void)
{
	irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO);
	irq_sim_fini(&iio_evgen->irq_sim);
	kfree(iio_evgen);
}

@@ -192,9 +143,7 @@ static ssize_t iio_evgen_poke(struct device *dev,
	iio_evgen->regs[this_attr->address].reg_id   = this_attr->address;
	iio_evgen->regs[this_attr->address].reg_data = event;

	iio_evgen->handler.irq = iio_evgen->base + this_attr->address;
	if (iio_evgen->enabled[this_attr->address])
		irq_work_queue(&iio_evgen->handler.work);
	irq_sim_fire(&iio_evgen->irq_sim, this_attr->address);

	return len;
}