/*
 *  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/config.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, struct pt_regs *regs)
{
	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);

