/*
 * Industrial I/O - gpio based trigger support
 *
 * Copyright (c) 2008 Jonathan Cameron
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * Currently this is more of a functioning proof of concept that a fully
 * fledged trigger driver.
 *
 * TODO:
 *
 * Add board config elements to allow specification of startup settings.
 * Add configuration settings (irq type etc)
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/slab.h>

#include "../iio.h"
#include "../trigger.h"

LIST_HEAD(iio_gpio_trigger_list);
DEFINE_MUTEX(iio_gpio_trigger_list_lock);

struct iio_gpio_trigger_info {
	struct mutex in_use;
	int gpio;
};
/*
 * Need to reference count these triggers and only enable gpio interrupts
 * as appropriate.
 */

/* So what functionality do we want in here?... */
/* set high / low as interrupt type? */

static irqreturn_t iio_gpio_trigger_poll(int irq, void *private)
{
	iio_trigger_poll(private);
	return IRQ_HANDLED;
}

static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);

static struct attribute *iio_gpio_trigger_attrs[] = {
	&dev_attr_name.attr,
	NULL,
};

static const struct attribute_group iio_gpio_trigger_attr_group = {
	.attrs = iio_gpio_trigger_attrs,
};

static int iio_gpio_trigger_probe(struct platform_device *dev)
{
	int *pdata = dev->dev.platform_data;
	struct iio_gpio_trigger_info *trig_info;
	struct iio_trigger *trig, *trig2;
	int i, irq, ret = 0;
	if (!pdata) {
		printk(KERN_ERR "No IIO gpio trigger platform data found\n");
		goto error_ret;
	}
	for (i = 0;; i++) {
		if (!gpio_is_valid(pdata[i]))
			break;
		trig = iio_allocate_trigger();
		if (!trig) {
			ret = -ENOMEM;
			goto error_free_completed_registrations;
		}

		trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
		if (!trig_info) {
			ret = -ENOMEM;
			goto error_put_trigger;
		}
		trig->control_attrs = &iio_gpio_trigger_attr_group;
		trig->private_data = trig_info;
		trig_info->gpio = pdata[i];
		trig->owner = THIS_MODULE;
		trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);
		if (!trig->name) {
			ret = -ENOMEM;
			goto error_free_trig_info;
		}
		snprintf((char *)trig->name,
			 IIO_TRIGGER_NAME_LENGTH,
			 "gpiotrig%d",
			 pdata[i]);
		ret = gpio_request(trig_info->gpio, trig->name);
		if (ret)
			goto error_free_name;

		ret = gpio_direction_input(trig_info->gpio);
		if (ret)
			goto error_release_gpio;

		irq = gpio_to_irq(trig_info->gpio);
		if (irq < 0) {
			ret = irq;
			goto error_release_gpio;
		}

		ret = request_irq(irq, iio_gpio_trigger_poll,
				  IRQF_TRIGGER_RISING,
				  trig->name,
				  trig);
		if (ret)
			goto error_release_gpio;

		ret = iio_trigger_register(trig);
		if (ret)
			goto error_release_irq;

		list_add_tail(&trig->alloc_list, &iio_gpio_trigger_list);

	}
	return 0;

/* First clean up the partly allocated trigger */
error_release_irq:
	free_irq(irq, trig);
error_release_gpio:
	gpio_free(trig_info->gpio);
error_free_name:
	kfree(trig->name);
error_free_trig_info:
	kfree(trig_info);
error_put_trigger:
	iio_put_trigger(trig);
error_free_completed_registrations:
	/* The rest should have been added to the iio_gpio_trigger_list */
	list_for_each_entry_safe(trig,
				 trig2,
				 &iio_gpio_trigger_list,
				 alloc_list) {
		trig_info = trig->private_data;
		free_irq(gpio_to_irq(trig_info->gpio), trig);
		gpio_free(trig_info->gpio);
		kfree(trig->name);
		kfree(trig_info);
		iio_trigger_unregister(trig);
	}

error_ret:
	return ret;
}

static int iio_gpio_trigger_remove(struct platform_device *dev)
{
	struct iio_trigger *trig, *trig2;
	struct iio_gpio_trigger_info *trig_info;

	mutex_lock(&iio_gpio_trigger_list_lock);
	list_for_each_entry_safe(trig,
				 trig2,
				 &iio_gpio_trigger_list,
				 alloc_list) {
		trig_info = trig->private_data;
		iio_trigger_unregister(trig);
		free_irq(gpio_to_irq(trig_info->gpio), trig);
		gpio_free(trig_info->gpio);
		kfree(trig->name);
		kfree(trig_info);
		iio_put_trigger(trig);
	}
	mutex_unlock(&iio_gpio_trigger_list_lock);

	return 0;
}

static struct platform_driver iio_gpio_trigger_driver = {
	.probe = iio_gpio_trigger_probe,
	.remove = iio_gpio_trigger_remove,
	.driver = {
		.name = "iio_gpio_trigger",
		.owner = THIS_MODULE,
	},
};

static int __init iio_gpio_trig_init(void)
{
	return platform_driver_register(&iio_gpio_trigger_driver);
}
module_init(iio_gpio_trig_init);

static void __exit iio_gpio_trig_exit(void)
{
	platform_driver_unregister(&iio_gpio_trigger_driver);
}
module_exit(iio_gpio_trig_exit);

MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_DESCRIPTION("Example gpio trigger for the iio subsystem");
MODULE_LICENSE("GPL v2");
