/*
 *  linux/drivers/input/serio/sa1111ps2.c
 *
 *  Copyright (C) 2002 Russell King
 *
 * 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.
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

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

#include <asm/hardware/sa1111.h>

struct ps2if {
	struct serio		*io;
	struct sa1111_dev	*dev;
	void __iomem		*base;
	unsigned int		open;
	spinlock_t		lock;
	unsigned int		head;
	unsigned int		tail;
	unsigned char		buf[4];
};

/*
 * Read all bytes waiting in the PS2 port.  There should be
 * at the most one, but we loop for safety.  If there was a
 * framing error, we have to manually clear the status.
 */
static irqreturn_t ps2_rxint(int irq, void *dev_id)
{
	struct ps2if *ps2if = dev_id;
	unsigned int scancode, flag, status;

	status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
	while (status & PS2STAT_RXF) {
		if (status & PS2STAT_STP)
			sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);

		flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
		       (status & PS2STAT_RXP ? 0 : SERIO_PARITY);

		scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;

		if (hweight8(scancode) & 1)
			flag ^= SERIO_PARITY;

		serio_interrupt(ps2if->io, scancode, flag);

		status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
        }

        return IRQ_HANDLED;
}

/*
 * Completion of ps2 write
 */
static irqreturn_t ps2_txint(int irq, void *dev_id)
{
	struct ps2if *ps2if = dev_id;
	unsigned int status;

	spin_lock(&ps2if->lock);
	status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
	if (ps2if->head == ps2if->tail) {
		disable_irq(irq);
		/* done */
	} else if (status & PS2STAT_TXE) {
		sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
		ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
	}
	spin_unlock(&ps2if->lock);

	return IRQ_HANDLED;
}

/*
 * Write a byte to the PS2 port.  We have to wait for the
 * port to indicate that the transmitter is empty.
 */
static int ps2_write(struct serio *io, unsigned char val)
{
	struct ps2if *ps2if = io->port_data;
	unsigned long flags;
	unsigned int head;

	spin_lock_irqsave(&ps2if->lock, flags);

	/*
	 * If the TX register is empty, we can go straight out.
	 */
	if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
		sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
	} else {
		if (ps2if->head == ps2if->tail)
			enable_irq(ps2if->dev->irq[1]);
		head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
		if (head != ps2if->tail) {
			ps2if->buf[ps2if->head] = val;
			ps2if->head = head;
		}
	}

	spin_unlock_irqrestore(&ps2if->lock, flags);
	return 0;
}

static int ps2_open(struct serio *io)
{
	struct ps2if *ps2if = io->port_data;
	int ret;

	sa1111_enable_device(ps2if->dev);

	ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
			  SA1111_DRIVER_NAME(ps2if->dev), ps2if);
	if (ret) {
		printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
			ps2if->dev->irq[0], ret);
		return ret;
	}

	ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
			  SA1111_DRIVER_NAME(ps2if->dev), ps2if);
	if (ret) {
		printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
			ps2if->dev->irq[1], ret);
		free_irq(ps2if->dev->irq[0], ps2if);
		return ret;
	}

	ps2if->open = 1;

	enable_irq_wake(ps2if->dev->irq[0]);

	sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
	return 0;
}

static void ps2_close(struct serio *io)
{
	struct ps2if *ps2if = io->port_data;

	sa1111_writel(0, ps2if->base + SA1111_PS2CR);

	disable_irq_wake(ps2if->dev->irq[0]);

	ps2if->open = 0;

	free_irq(ps2if->dev->irq[1], ps2if);
	free_irq(ps2if->dev->irq[0], ps2if);

	sa1111_disable_device(ps2if->dev);
}

/*
 * Clear the input buffer.
 */
static void __devinit ps2_clear_input(struct ps2if *ps2if)
{
	int maxread = 100;

	while (maxread--) {
		if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
			break;
	}
}

static inline unsigned int
ps2_test_one(struct ps2if *ps2if, unsigned int mask)
{
	unsigned int val;

	sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);

	udelay(2);

	val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
	return val & (PS2STAT_KBC | PS2STAT_KBD);
}

/*
 * Test the keyboard interface.  We basically check to make sure that
 * we can drive each line to the keyboard independently of each other.
 */
static int __init ps2_test(struct ps2if *ps2if)
{
	unsigned int stat;
	int ret = 0;

	stat = ps2_test_one(ps2if, PS2CR_FKC);
	if (stat != PS2STAT_KBD) {
		printk("PS/2 interface test failed[1]: %02x\n", stat);
		ret = -ENODEV;
	}

	stat = ps2_test_one(ps2if, 0);
	if (stat != (PS2STAT_KBC | PS2STAT_KBD)) {
		printk("PS/2 interface test failed[2]: %02x\n", stat);
		ret = -ENODEV;
	}

	stat = ps2_test_one(ps2if, PS2CR_FKD);
	if (stat != PS2STAT_KBC) {
		printk("PS/2 interface test failed[3]: %02x\n", stat);
		ret = -ENODEV;
	}

	sa1111_writel(0, ps2if->base + SA1111_PS2CR);

	return ret;
}

/*
 * Add one device to this driver.
 */
static int __devinit ps2_probe(struct sa1111_dev *dev)
{
	struct ps2if *ps2if;
	struct serio *serio;
	int ret;

	ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
	if (!ps2if || !serio) {
		ret = -ENOMEM;
		goto free;
	}

	memset(ps2if, 0, sizeof(struct ps2if));
	memset(serio, 0, sizeof(struct serio));

	serio->id.type		= SERIO_8042;
	serio->write		= ps2_write;
	serio->open		= ps2_open;
	serio->close		= ps2_close;
	strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
	serio->port_data	= ps2if;
	serio->dev.parent	= &dev->dev;
	ps2if->io		= serio;
	ps2if->dev		= dev;
	sa1111_set_drvdata(dev, ps2if);

	spin_lock_init(&ps2if->lock);

	/*
	 * Request the physical region for this PS2 port.
	 */
	if (!request_mem_region(dev->res.start,
				dev->res.end - dev->res.start + 1,
				SA1111_DRIVER_NAME(dev))) {
		ret = -EBUSY;
		goto free;
	}

	/*
	 * Our parent device has already mapped the region.
	 */
	ps2if->base = dev->mapbase;

	sa1111_enable_device(ps2if->dev);

	/* Incoming clock is 8MHz */
	sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
	sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);

	/*
	 * Flush any pending input.
	 */
	ps2_clear_input(ps2if);

	/*
	 * Test the keyboard interface.
	 */
	ret = ps2_test(ps2if);
	if (ret)
		goto out;

	/*
	 * Flush any pending input.
	 */
	ps2_clear_input(ps2if);

	sa1111_disable_device(ps2if->dev);
	serio_register_port(ps2if->io);
	return 0;

 out:
	sa1111_disable_device(ps2if->dev);
	release_mem_region(dev->res.start,
			   dev->res.end - dev->res.start + 1);
 free:
	sa1111_set_drvdata(dev, NULL);
	kfree(ps2if);
	kfree(serio);
	return ret;
}

/*
 * Remove one device from this driver.
 */
static int ps2_remove(struct sa1111_dev *dev)
{
	struct ps2if *ps2if = sa1111_get_drvdata(dev);

	serio_unregister_port(ps2if->io);
	release_mem_region(dev->res.start,
			   dev->res.end - dev->res.start + 1);
	sa1111_set_drvdata(dev, NULL);

	kfree(ps2if);

	return 0;
}

/*
 * Our device driver structure
 */
static struct sa1111_driver ps2_driver = {
	.drv = {
		.name	= "sa1111-ps2",
	},
	.devid		= SA1111_DEVID_PS2,
	.probe		= ps2_probe,
	.remove		= ps2_remove,
};

static int __init ps2_init(void)
{
	return sa1111_driver_register(&ps2_driver);
}

static void __exit ps2_exit(void)
{
	sa1111_driver_unregister(&ps2_driver);
}

module_init(ps2_init);
module_exit(ps2_exit);

MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("SA1111 PS2 controller driver");
MODULE_LICENSE("GPL");
