iio: dummy: evgen: use irq_sim
Switch to using the recently added interrupt simulator for dummy irqs. Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Tested-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Родитель
4546813a7f
Коммит
ca48139856
|
@ -5,7 +5,7 @@ menu "IIO dummy driver"
|
||||||
depends on IIO
|
depends on IIO
|
||||||
|
|
||||||
config IIO_DUMMY_EVGEN
|
config IIO_DUMMY_EVGEN
|
||||||
select IRQ_WORK
|
select IRQ_SIM
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
config IIO_SIMPLE_DUMMY
|
config IIO_SIMPLE_DUMMY
|
||||||
|
|
|
@ -24,97 +24,46 @@
|
||||||
#include "iio_dummy_evgen.h"
|
#include "iio_dummy_evgen.h"
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/sysfs.h>
|
#include <linux/iio/sysfs.h>
|
||||||
#include <linux/irq_work.h>
|
#include <linux/irq_sim.h>
|
||||||
|
|
||||||
/* Fiddly bit of faking and irq without hardware */
|
/* Fiddly bit of faking and irq without hardware */
|
||||||
#define IIO_EVENTGEN_NO 10
|
#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
|
* @regs: irq regs we are faking
|
||||||
* @lock: protect the evgen state
|
* @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 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 iio_dummy_regs regs[IIO_EVENTGEN_NO];
|
||||||
struct mutex lock;
|
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' */
|
/* We can only ever have one instance of this 'device' */
|
||||||
static struct iio_dummy_eventgen *iio_evgen;
|
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)
|
static int iio_dummy_evgen_create(void)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret;
|
||||||
|
|
||||||
iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL);
|
iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL);
|
||||||
if (!iio_evgen)
|
if (!iio_evgen)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0);
|
ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
|
||||||
if (iio_evgen->base < 0) {
|
if (ret) {
|
||||||
ret = iio_evgen->base;
|
|
||||||
kfree(iio_evgen);
|
kfree(iio_evgen);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
iio_evgen->chip.name = iio_evgen_name;
|
|
||||||
iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask;
|
iio_evgen->base = irq_sim_irqnum(&iio_evgen->irq_sim, 0);
|
||||||
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);
|
|
||||||
mutex_init(&iio_evgen->lock);
|
mutex_init(&iio_evgen->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,15 +81,17 @@ int iio_dummy_evgen_get_irq(void)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mutex_lock(&iio_evgen->lock);
|
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]) {
|
if (!iio_evgen->inuse[i]) {
|
||||||
ret = iio_evgen->base + i;
|
ret = irq_sim_irqnum(&iio_evgen->irq_sim, i);
|
||||||
iio_evgen->inuse[i] = true;
|
iio_evgen->inuse[i] = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mutex_unlock(&iio_evgen->lock);
|
mutex_unlock(&iio_evgen->lock);
|
||||||
if (i == IIO_EVENTGEN_NO)
|
if (i == IIO_EVENTGEN_NO)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq);
|
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)
|
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);
|
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_id = this_attr->address;
|
||||||
iio_evgen->regs[this_attr->address].reg_data = event;
|
iio_evgen->regs[this_attr->address].reg_data = event;
|
||||||
|
|
||||||
iio_evgen->handler.irq = iio_evgen->base + this_attr->address;
|
irq_sim_fire(&iio_evgen->irq_sim, this_attr->address);
|
||||||
if (iio_evgen->enabled[this_attr->address])
|
|
||||||
irq_work_queue(&iio_evgen->handler.work);
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче