Commit 3ad30417 authored by Alessandro Rubini's avatar Alessandro Rubini Committed by Federico Vaga

drivers: added zio-mini

zio-mini is a very simple driver, with no attributes, that can be used
to get accustomed with how ZIO and the ZIO bus work. You can create
as many devices as you want, with as many channels as you want.
Each device has only one input cset, that returns the struct timespec
collected at raw_io() time.

The driver always returns one sample only, even if the trigger
asks for more.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
Acked-by: 's avatarFederico Vaga <federico.vaga@gmail.com>
parent 371ff973
......@@ -4,6 +4,7 @@ EXTRA_CFLAGS += -I$(obj)/../include
obj-m = zio-zero.o
obj-m += zio-loop.o
obj-m += zio-mini.o
obj-m += zio-gpio.o
ifdef CONFIG_SPI
obj-m += zio-ad788x.o
......
/* Alessandro Rubini, 2012, public domain */
/*
* A minimal device: one input channel only: returns an 8-byte sample
* with a native-endianness timespec
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/zio.h>
#include <linux/zio-buffer.h>
ZIO_PARAM_TRIGGER(zmini_trigger);
ZIO_PARAM_BUFFER(zmini_buffer);
static int zmini_ndev = 1;
module_param_named(ndev, zmini_ndev, int, 0444);
static int zmini_nchan = 1;
module_param_named(nchan, zmini_nchan, int, 0444);
static int zmini_input(struct zio_cset *cset)
{
struct zio_channel *chan;
struct zio_block *block;
struct timespec *ts;
/* Return immediately: just fill the blocks */
chan_for_each(chan, cset) {
block = chan->active_block;
if (!block)
continue;
if (block->datalen < sizeof(*ts))
continue;
/* we are allowed to return less data than allocated */
chan->current_ctrl->nsamples = 1;
block->datalen = sizeof(struct timespec);
getnstimeofday(block->data);
}
return 0; /* Already done */
}
static struct zio_cset zmini_cset[] = {
{
ZIO_SET_OBJ_NAME("timespec-in"),
.raw_io = zmini_input,
.flags = ZIO_DIR_INPUT,
.n_chan = 1, /* changed at insmod */
.ssize = sizeof(struct timespec),
},
};
static struct zio_device zmini_tmpl = {
.owner = THIS_MODULE,
.cset = zmini_cset,
.n_cset = ARRAY_SIZE(zmini_cset),
};
/* The driver uses a table of templates */
static const struct zio_device_id zmini_table[] = {
{"zmini", &zmini_tmpl},
{},
};
static struct zio_driver zmini_zdrv = {
.driver = {
.name = "zmini",
.owner = THIS_MODULE,
},
.id_table = zmini_table,
};
/* The device is registered in the bus: we can have several */
static struct zio_device **zmini_dev_array;
static int __init zmini_init(void)
{
int err, i;
struct zio_device *zdev;
/* customize the driver and register it */
if (zmini_trigger)
zmini_tmpl.preferred_trigger = zmini_trigger;
if (zmini_buffer)
zmini_tmpl.preferred_buffer = zmini_buffer;
zmini_cset[0].n_chan = zmini_nchan;
err = zio_register_driver(&zmini_zdrv);
if (err)
return err;
/* allocate the devices and register them */
if (zmini_ndev < 0 || zmini_ndev > 1024) {
pr_err("%s: ndev is %i: out of range\n", KBUILD_MODNAME,
zmini_ndev);
return -EINVAL;
}
zmini_dev_array = kzalloc(zmini_ndev *sizeof(*zdev), GFP_KERNEL);
for (i = 0; i < zmini_ndev; i++) {
zdev = zio_allocate_device();
if (IS_ERR(zdev)) {
err = PTR_ERR(zdev);
goto out;
}
zdev->owner = THIS_MODULE;
err = zio_register_device(zdev, "zmini", 0);
if (err) {
zio_free_device(zdev);
goto out;
}
zmini_dev_array[i] = zdev;
}
return 0;
out:
for (i = 0; i < zmini_ndev && zmini_dev_array[i]; i++) {
zio_unregister_device(zmini_dev_array[i]);
zio_free_device(zmini_dev_array[i]);
}
zio_unregister_driver(&zmini_zdrv);
kfree(zmini_dev_array);
return err;
}
static void __exit zmini_exit(void)
{
int i;
for (i = 0; i < zmini_ndev && zmini_dev_array[i]; i++) {
zio_unregister_device(zmini_dev_array[i]);
zio_free_device(zmini_dev_array[i]);
}
zio_unregister_driver(&zmini_zdrv);
kfree(zmini_dev_array);
return;
}
module_init(zmini_init);
module_exit(zmini_exit);
MODULE_LICENSE("GPL and additional rights");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment