/*
 *  Driver for TANBAC TB0219 base board.
 *
 *  Copyright (C) 2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>

#include <asm/io.h>
#include <asm/reboot.h>

MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
MODULE_LICENSE("GPL");

static int major;	/* default is dynamic major device number */
module_param(major, int, 0);
MODULE_PARM_DESC(major, "Major device number");

static void (*old_machine_restart)(char *command);
static void __iomem *tb0219_base;
static spinlock_t tb0219_lock;

#define tb0219_read(offset)		readw(tb0219_base + (offset))
#define tb0219_write(offset, value)	writew((value), tb0219_base + (offset))

#define TB0219_START	0x0a000000UL
#define TB0219_SIZE	0x20UL

#define TB0219_LED			0x00
#define TB0219_GPIO_INPUT		0x02
#define TB0219_GPIO_OUTPUT		0x04
#define TB0219_DIP_SWITCH		0x06
#define TB0219_MISC			0x08
#define TB0219_RESET			0x0e
#define TB0219_PCI_SLOT1_IRQ_STATUS	0x10
#define TB0219_PCI_SLOT2_IRQ_STATUS	0x12
#define TB0219_PCI_SLOT3_IRQ_STATUS	0x14

typedef enum {
	TYPE_LED,
	TYPE_GPIO_OUTPUT,
} tb0219_type_t;

/*
 * Minor device number
 *	 0 = 7 segment LED
 *
 *	16 = GPIO IN 0
 *	17 = GPIO IN 1
 *	18 = GPIO IN 2
 *	19 = GPIO IN 3
 *	20 = GPIO IN 4
 *	21 = GPIO IN 5
 *	22 = GPIO IN 6
 *	23 = GPIO IN 7
 *
 *	32 = GPIO OUT 0
 *	33 = GPIO OUT 1
 *	34 = GPIO OUT 2
 *	35 = GPIO OUT 3
 *	36 = GPIO OUT 4
 *	37 = GPIO OUT 5
 *	38 = GPIO OUT 6
 *	39 = GPIO OUT 7
 *
 *	48 = DIP switch 1
 *	49 = DIP switch 2
 *	50 = DIP switch 3
 *	51 = DIP switch 4
 *	52 = DIP switch 5
 *	53 = DIP switch 6
 *	54 = DIP switch 7
 *	55 = DIP switch 8
 */

static inline char get_led(void)
{
	return (char)tb0219_read(TB0219_LED);
}

static inline char get_gpio_input_pin(unsigned int pin)
{
	uint16_t values;

	values = tb0219_read(TB0219_GPIO_INPUT);
	if (values & (1 << pin))
		return '1';

	return '0';
}

static inline char get_gpio_output_pin(unsigned int pin)
{
	uint16_t values;

	values = tb0219_read(TB0219_GPIO_OUTPUT);
	if (values & (1 << pin))
		return '1';

	return '0';
}

static inline char get_dip_switch(unsigned int pin)
{
	uint16_t values;

	values = tb0219_read(TB0219_DIP_SWITCH);
	if (values & (1 << pin))
		return '1';

	return '0';
}

static inline int set_led(char command)
{
	tb0219_write(TB0219_LED, command);

	return 0;
}

static inline int set_gpio_output_pin(unsigned int pin, char command)
{
	unsigned long flags;
	uint16_t value;

	if (command != '0' && command != '1')
		return -EINVAL;

	spin_lock_irqsave(&tb0219_lock, flags);
	value = tb0219_read(TB0219_GPIO_OUTPUT);
	if (command == '0')
		value &= ~(1 << pin);
	else
		value |= 1 << pin;
	tb0219_write(TB0219_GPIO_OUTPUT, value);
	spin_unlock_irqrestore(&tb0219_lock, flags);

	return 0;

}

static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t len,
                                  loff_t *ppos)
{
	unsigned int minor;
	char value;

	minor = iminor(file->f_dentry->d_inode);
	switch (minor) {
	case 0:
		value = get_led();
		break;
	case 16 ... 23:
		value = get_gpio_input_pin(minor - 16);
		break;
	case 32 ... 39:
		value = get_gpio_output_pin(minor - 32);
		break;
	case 48 ... 55:
		value = get_dip_switch(minor - 48);
		break;
	default:
		return -EBADF;
	}

	if (len <= 0)
		return -EFAULT;

	if (put_user(value, buf))
		return -EFAULT;

	return 1;
}

static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
                                   size_t len, loff_t *ppos)
{
	unsigned int minor;
	tb0219_type_t type;
	size_t i;
	int retval = 0;
	char c;

	minor = iminor(file->f_dentry->d_inode);
	switch (minor) {
	case 0:
		type = TYPE_LED;
		break;
	case 32 ... 39:
		type = TYPE_GPIO_OUTPUT;
		break;
	default:
		return -EBADF;
	}

	for (i = 0; i < len; i++) {
		if (get_user(c, data + i))
			return -EFAULT;

		switch (type) {
		case TYPE_LED:
			retval = set_led(c);
			break;
		case TYPE_GPIO_OUTPUT:
			retval = set_gpio_output_pin(minor - 32, c);
			break;
		}

		if (retval < 0)
			break;
	}

	return i;
}

static int tanbac_tb0219_open(struct inode *inode, struct file *file)
{
	unsigned int minor;

	minor = iminor(inode);
	switch (minor) {
	case 0:
	case 16 ... 23:
	case 32 ... 39:
	case 48 ... 55:
		return nonseekable_open(inode, file);
	default:
		break;
	}

	return -EBADF;
}

static int tanbac_tb0219_release(struct inode *inode, struct file *file)
{
	return 0;
}

static struct file_operations tb0219_fops = {
	.owner		= THIS_MODULE,
	.read		= tanbac_tb0219_read,
	.write		= tanbac_tb0219_write,
	.open		= tanbac_tb0219_open,
	.release	= tanbac_tb0219_release,
};

static void tb0219_restart(char *command)
{
	tb0219_write(TB0219_RESET, 0);
}

static int tb0219_probe(struct device *dev)
{
	int retval;

	if (request_mem_region(TB0219_START, TB0219_SIZE, "TB0219") == NULL)
		return -EBUSY;

	tb0219_base = ioremap(TB0219_START, TB0219_SIZE);
	if (tb0219_base == NULL) {
		release_mem_region(TB0219_START, TB0219_SIZE);
		return -ENOMEM;
	}

	retval = register_chrdev(major, "TB0219", &tb0219_fops);
	if (retval < 0) {
		iounmap(tb0219_base);
		tb0219_base = NULL;
		release_mem_region(TB0219_START, TB0219_SIZE);
		return retval;
	}

	spin_lock_init(&tb0219_lock);

	old_machine_restart = _machine_restart;
	_machine_restart = tb0219_restart;

	if (major == 0) {
		major = retval;
		printk(KERN_INFO "TB0219: major number %d\n", major);
	}

	return 0;
}

static int tb0219_remove(struct device *dev)
{
	_machine_restart = old_machine_restart;

	iounmap(tb0219_base);
	tb0219_base = NULL;

	release_mem_region(TB0219_START, TB0219_SIZE);

	return 0;
}

static struct platform_device *tb0219_platform_device;

static struct device_driver tb0219_device_driver = {
	.name		= "TB0219",
	.bus		= &platform_bus_type,
	.probe		= tb0219_probe,
	.remove		= tb0219_remove,
};

static int __devinit tanbac_tb0219_init(void)
{
	int retval;

	tb0219_platform_device = platform_device_register_simple("TB0219", -1, NULL, 0);
	if (IS_ERR(tb0219_platform_device))
		return PTR_ERR(tb0219_platform_device);

	retval = driver_register(&tb0219_device_driver);
	if (retval < 0)
		platform_device_unregister(tb0219_platform_device);

	return retval;
}

static void __devexit tanbac_tb0219_exit(void)
{
	driver_unregister(&tb0219_device_driver);

	platform_device_unregister(tb0219_platform_device);
}

module_init(tanbac_tb0219_init);
module_exit(tanbac_tb0219_exit);
