/*
 *  linux/drivers/hil/hilkbd.c
 *
 *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
 *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
 *  Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
 *
 *  Very basic HP Human Interface Loop (HIL) driver.
 *  This driver handles the keyboard on HP300 (m68k) and on some 
 *  HP700 (parisc) series machines.
 *
 * 
 * This file is subject to the terms and conditions of the GNU General Public
 * License version 2.  See the file COPYING in the main directory of this
 * archive for more details.
 */

#include <linux/pci_ids.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/hil.h>
#include <linux/spinlock.h>


MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
MODULE_LICENSE("GPL v2");


#if defined(CONFIG_PARISC)

 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/parisc-device.h>
 static unsigned long hil_base;	/* HPA for the HIL device */
 static unsigned int hil_irq;
 #define HILBASE		hil_base /* HPPA (parisc) port address */
 #define HIL_DATA		0x800
 #define HIL_CMD		0x801
 #define HIL_IRQ		hil_irq
 #define hil_readb(p)		gsc_readb(p)
 #define hil_writeb(v,p)	gsc_writeb((v),(p))

#elif defined(CONFIG_HP300)

 #define HILBASE		0xf0428000 /* HP300 (m86k) port address */
 #define HIL_DATA		0x1
 #define HIL_CMD		0x3
 #define HIL_IRQ		2
 #define hil_readb(p)		readb(p)
 #define hil_writeb(v,p)	writeb((v),(p))

#else
#error "HIL is not supported on this platform"
#endif


 
/* HIL helper functions */
 
#define hil_busy()              (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
#define hil_data_available()    (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
#define hil_status()            (hil_readb(HILBASE + HIL_CMD))
#define hil_command(x)          do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
#define hil_read_data()         (hil_readb(HILBASE + HIL_DATA))
#define hil_write_data(x)       do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)

/* HIL constants */
 
#define	HIL_BUSY		0x02
#define	HIL_DATA_RDY		0x01

#define	HIL_SETARD		0xA0		/* set auto-repeat delay */
#define	HIL_SETARR		0xA2		/* set auto-repeat rate */
#define	HIL_SETTONE		0xA3		/* set tone generator */
#define	HIL_CNMT		0xB2		/* clear nmi */
#define	HIL_INTON		0x5C		/* Turn on interrupts. */
#define	HIL_INTOFF		0x5D		/* Turn off interrupts. */

#define	HIL_READKBDSADR	 	0xF9
#define	HIL_WRITEKBDSADR 	0xE9

static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = 
	{ HIL_KEYCODES_SET1 };

/* HIL structure */
static struct {
	struct input_dev *dev;

	unsigned int curdev;
	
	unsigned char s;
	unsigned char c;
	int valid;
	
	unsigned char data[16];
	unsigned int ptr;
	spinlock_t lock;

	void *dev_id;	/* native bus device */
} hil_dev;


static void poll_finished(void)
{
	int down;
	int key;
	unsigned char scode;
	
	switch (hil_dev.data[0]) {
	case 0x40:
		down = (hil_dev.data[1] & 1) == 0;
		scode = hil_dev.data[1] >> 1;
		key = hphilkeyb_keycode[scode];
		input_report_key(hil_dev.dev, key, down);
		break;
	}
	hil_dev.curdev = 0;
}

static inline void handle_status(unsigned char s, unsigned char c)
{
	if (c & 0x8) {
		/* End of block */
		if (c & 0x10)
			poll_finished();
	} else {
		if (c & 0x10) {
			if (hil_dev.curdev)
				poll_finished();  /* just in case */
			hil_dev.curdev = c & 7;
			hil_dev.ptr = 0;
		}
	}
}

static inline void handle_data(unsigned char s, unsigned char c)
{
	if (hil_dev.curdev) {
		hil_dev.data[hil_dev.ptr++] = c;
		hil_dev.ptr &= 15;
	}
}


/* 
 * Handle HIL interrupts.
 */
static irqreturn_t hil_interrupt(int irq, void *handle)
{
	unsigned char s, c;
	
	s = hil_status();
	c = hil_read_data();

	switch (s >> 4) {
	case 0x5:
		handle_status(s, c);
		break;
	case 0x6:
		handle_data(s, c);
		break;
	case 0x4:
		hil_dev.s = s;
		hil_dev.c = c;
		mb();
		hil_dev.valid = 1;
		break;
	}
	return IRQ_HANDLED;
}

/*
 * Send a command to the HIL
 */

static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
{
	unsigned long flags;

	spin_lock_irqsave(&hil_dev.lock, flags);
	while (hil_busy())
		/* wait */;
	hil_command(cmd);
	while (len--) {
		while (hil_busy())
			/* wait */;
		hil_write_data(*(data++));
	}
	spin_unlock_irqrestore(&hil_dev.lock, flags);
}


/*
 * Initialise HIL. 
 */

static int __init
hil_keyb_init(void)
{
	unsigned char c;
	unsigned int i, kbid;
	wait_queue_head_t hil_wait;

	if (hil_dev.dev) {
		return -ENODEV; /* already initialized */
	}

	hil_dev.dev = input_allocate_device();
	if (!hil_dev.dev)
		return -ENOMEM;
	hil_dev.dev->private = &hil_dev;
	
#if defined(CONFIG_HP300)
	if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
		return -ENODEV;
	
	request_region(HILBASE+HIL_DATA, 2, "hil");
#endif
	
	request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);

	/* Turn on interrupts */
	hil_do(HIL_INTON, NULL, 0);

	/* Look for keyboards */
	hil_dev.valid = 0;	/* clear any pending data */
	hil_do(HIL_READKBDSADR, NULL, 0);

	init_waitqueue_head(&hil_wait);
	wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
	if (!hil_dev.valid) {
		printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
	}

	c = hil_dev.c; 
	hil_dev.valid = 0;
	if (c == 0) {
		kbid = -1;
		printk(KERN_WARNING "HIL: no keyboard present.\n");
	} else {
		kbid = ffz(~c);
		/* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
	}

	/* set it to raw mode */
	c = 0;
	hil_do(HIL_WRITEKBDSADR, &c, 1);
	
	for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
		if (hphilkeyb_keycode[i] != KEY_RESERVED)
			set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);

	hil_dev.dev->evbit[0]    = BIT(EV_KEY) | BIT(EV_REP);
	hil_dev.dev->ledbit[0]   = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
	hil_dev.dev->keycodemax  = HIL_KEYCODES_SET1_TBLSIZE;
	hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]);
	hil_dev.dev->keycode     = hphilkeyb_keycode;
	hil_dev.dev->name 	= "HIL keyboard";
	hil_dev.dev->phys 	= "hpkbd/input0";

	hil_dev.dev->id.bustype	= BUS_HIL;
	hil_dev.dev->id.vendor	= PCI_VENDOR_ID_HP;
	hil_dev.dev->id.product	= 0x0001;
	hil_dev.dev->id.version	= 0x0010;

	input_register_device(hil_dev.dev);
	printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
		hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);

	return 0;
}

#if defined(CONFIG_PARISC)
static int __init
hil_init_chip(struct parisc_device *dev)
{
	if (!dev->irq) {
		printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start);
		return -ENODEV;
	}

	hil_base = dev->hpa.start;
	hil_irq  = dev->irq;
	hil_dev.dev_id = dev;
	
	printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);

	return hil_keyb_init();
}

static struct parisc_device_id hil_tbl[] = {
	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
	{ 0, }
};

MODULE_DEVICE_TABLE(parisc, hil_tbl);

static struct parisc_driver hil_driver = {
	.name =		"hil",
	.id_table =	hil_tbl,
	.probe =	hil_init_chip,
};
#endif /* CONFIG_PARISC */





static int __init hil_init(void)
{
#if defined(CONFIG_PARISC)
	return register_parisc_driver(&hil_driver);
#else
	return hil_keyb_init();
#endif
}


static void __exit hil_exit(void)
{
	if (HIL_IRQ) {
		disable_irq(HIL_IRQ);
		free_irq(HIL_IRQ, hil_dev.dev_id);
	}

	/* Turn off interrupts */
	hil_do(HIL_INTOFF, NULL, 0);

	input_unregister_device(hil_dev.dev);

	hil_dev.dev = NULL;

#if defined(CONFIG_PARISC)
	unregister_parisc_driver(&hil_driver);
#else
	release_region(HILBASE+HIL_DATA, 2);
#endif
}

module_init(hil_init);
module_exit(hil_exit);

