/*
 * linux/drivers/input/serio/pcips2.c
 *
 *  Copyright (C) 2003 Russell King, All Rights Reserved.
 *
 * 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.
 *
 *  I'm not sure if this is a generic PS/2 PCI interface or specific to
 *  the Mobility Electronics docking station.
 */
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <asm/io.h>

#define PS2_CTRL		(0)
#define PS2_STATUS		(1)
#define PS2_DATA		(2)

#define PS2_CTRL_CLK		(1<<0)
#define PS2_CTRL_DAT		(1<<1)
#define PS2_CTRL_TXIRQ		(1<<2)
#define PS2_CTRL_ENABLE		(1<<3)
#define PS2_CTRL_RXIRQ		(1<<4)

#define PS2_STAT_CLK		(1<<0)
#define PS2_STAT_DAT		(1<<1)
#define PS2_STAT_PARITY		(1<<2)
#define PS2_STAT_RXFULL		(1<<5)
#define PS2_STAT_TXBUSY		(1<<6)
#define PS2_STAT_TXEMPTY	(1<<7)

struct pcips2_data {
	struct serio	*io;
	unsigned int	base;
	struct pci_dev	*dev;
};

static int pcips2_write(struct serio *io, unsigned char val)
{
	struct pcips2_data *ps2if = io->port_data;
	unsigned int stat;

	do {
		stat = inb(ps2if->base + PS2_STATUS);
		cpu_relax();
	} while (!(stat & PS2_STAT_TXEMPTY));

	outb(val, ps2if->base + PS2_DATA);

	return 0;
}

static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
{
	struct pcips2_data *ps2if = devid;
	unsigned char status, scancode;
	int handled = 0;

	do {
		unsigned int flag;

		status = inb(ps2if->base + PS2_STATUS);
		if (!(status & PS2_STAT_RXFULL))
			break;
		handled = 1;
		scancode = inb(ps2if->base + PS2_DATA);
		if (status == 0xff && scancode == 0xff)
			break;

		flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;

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

		serio_interrupt(ps2if->io, scancode, flag, regs);
	} while (1);
	return IRQ_RETVAL(handled);
}

static void pcips2_flush_input(struct pcips2_data *ps2if)
{
	unsigned char status, scancode;

	do {
		status = inb(ps2if->base + PS2_STATUS);
		if (!(status & PS2_STAT_RXFULL))
			break;
		scancode = inb(ps2if->base + PS2_DATA);
		if (status == 0xff && scancode == 0xff)
			break;
	} while (1);
}

static int pcips2_open(struct serio *io)
{
	struct pcips2_data *ps2if = io->port_data;
	int ret, val = 0;

	outb(PS2_CTRL_ENABLE, ps2if->base);
	pcips2_flush_input(ps2if);

	ret = request_irq(ps2if->dev->irq, pcips2_interrupt, IRQF_SHARED,
			  "pcips2", ps2if);
	if (ret == 0)
		val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;

	outb(val, ps2if->base);

	return ret;
}

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

	outb(0, ps2if->base);

	free_irq(ps2if->dev->irq, ps2if);
}

static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
	struct pcips2_data *ps2if;
	struct serio *serio;
	int ret;

	ret = pci_enable_device(dev);
	if (ret)
		goto out;

	ret = pci_request_regions(dev, "pcips2");
	if (ret)
		goto disable;

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

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

	serio->id.type		= SERIO_8042;
	serio->write		= pcips2_write;
	serio->open		= pcips2_open;
	serio->close		= pcips2_close;
	strlcpy(serio->name, pci_name(dev), 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;
	ps2if->base		= pci_resource_start(dev, 0);

	pci_set_drvdata(dev, ps2if);

	serio_register_port(ps2if->io);
	return 0;

 release:
	kfree(ps2if);
	kfree(serio);
	pci_release_regions(dev);
 disable:
	pci_disable_device(dev);
 out:
	return ret;
}

static void __devexit pcips2_remove(struct pci_dev *dev)
{
	struct pcips2_data *ps2if = pci_get_drvdata(dev);

	serio_unregister_port(ps2if->io);
	pci_set_drvdata(dev, NULL);
	kfree(ps2if);
	pci_release_regions(dev);
	pci_disable_device(dev);
}

static struct pci_device_id pcips2_ids[] = {
	{
		.vendor		= 0x14f2,	/* MOBILITY */
		.device		= 0x0123,	/* Keyboard */
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= PCI_CLASS_INPUT_KEYBOARD << 8,
		.class_mask	= 0xffff00,
	},
	{
		.vendor		= 0x14f2,	/* MOBILITY */
		.device		= 0x0124,	/* Mouse */
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= PCI_CLASS_INPUT_MOUSE << 8,
		.class_mask	= 0xffff00,
	},
	{ 0, }
};

static struct pci_driver pcips2_driver = {
	.name			= "pcips2",
	.id_table		= pcips2_ids,
	.probe			= pcips2_probe,
	.remove			= __devexit_p(pcips2_remove),
};

static int __init pcips2_init(void)
{
	return pci_register_driver(&pcips2_driver);
}

static void __exit pcips2_exit(void)
{
	pci_unregister_driver(&pcips2_driver);
}

module_init(pcips2_init);
module_exit(pcips2_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
MODULE_DEVICE_TABLE(pci, pcips2_ids);
