Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / input / keyboard / hilkbd.c
blob54bc569db4b014e999068a57c5ae11b1f41f6a69
1 /*
2 * linux/drivers/hil/hilkbd.c
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 * Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
6 * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
8 * Very basic HP Human Interface Loop (HIL) driver.
9 * This driver handles the keyboard on HP300 (m68k) and on some
10 * HP700 (parisc) series machines.
13 * This file is subject to the terms and conditions of the GNU General Public
14 * License version 2. See the file COPYING in the main directory of this
15 * archive for more details.
18 #include <linux/pci_ids.h>
19 #include <linux/ioport.h>
20 #include <linux/module.h>
21 #include <linux/errno.h>
22 #include <linux/input.h>
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/hil.h>
26 #include <linux/spinlock.h>
29 MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
30 MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
31 MODULE_LICENSE("GPL v2");
34 #if defined(CONFIG_PARISC)
36 #include <asm/io.h>
37 #include <asm/hardware.h>
38 #include <asm/parisc-device.h>
39 static unsigned long hil_base; /* HPA for the HIL device */
40 static unsigned int hil_irq;
41 #define HILBASE hil_base /* HPPA (parisc) port address */
42 #define HIL_DATA 0x800
43 #define HIL_CMD 0x801
44 #define HIL_IRQ hil_irq
45 #define hil_readb(p) gsc_readb(p)
46 #define hil_writeb(v,p) gsc_writeb((v),(p))
48 #elif defined(CONFIG_HP300)
50 #define HILBASE 0xf0428000 /* HP300 (m86k) port address */
51 #define HIL_DATA 0x1
52 #define HIL_CMD 0x3
53 #define HIL_IRQ 2
54 #define hil_readb(p) readb(p)
55 #define hil_writeb(v,p) writeb((v),(p))
57 #else
58 #error "HIL is not supported on this platform"
59 #endif
63 /* HIL helper functions */
65 #define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
66 #define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
67 #define hil_status() (hil_readb(HILBASE + HIL_CMD))
68 #define hil_command(x) do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
69 #define hil_read_data() (hil_readb(HILBASE + HIL_DATA))
70 #define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
72 /* HIL constants */
74 #define HIL_BUSY 0x02
75 #define HIL_DATA_RDY 0x01
77 #define HIL_SETARD 0xA0 /* set auto-repeat delay */
78 #define HIL_SETARR 0xA2 /* set auto-repeat rate */
79 #define HIL_SETTONE 0xA3 /* set tone generator */
80 #define HIL_CNMT 0xB2 /* clear nmi */
81 #define HIL_INTON 0x5C /* Turn on interrupts. */
82 #define HIL_INTOFF 0x5D /* Turn off interrupts. */
84 #define HIL_READKBDSADR 0xF9
85 #define HIL_WRITEKBDSADR 0xE9
87 static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
88 { HIL_KEYCODES_SET1 };
90 /* HIL structure */
91 static struct {
92 struct input_dev *dev;
94 unsigned int curdev;
96 unsigned char s;
97 unsigned char c;
98 int valid;
100 unsigned char data[16];
101 unsigned int ptr;
102 spinlock_t lock;
104 void *dev_id; /* native bus device */
105 } hil_dev;
108 static void poll_finished(void)
110 int down;
111 int key;
112 unsigned char scode;
114 switch (hil_dev.data[0]) {
115 case 0x40:
116 down = (hil_dev.data[1] & 1) == 0;
117 scode = hil_dev.data[1] >> 1;
118 key = hphilkeyb_keycode[scode];
119 input_report_key(hil_dev.dev, key, down);
120 break;
122 hil_dev.curdev = 0;
125 static inline void handle_status(unsigned char s, unsigned char c)
127 if (c & 0x8) {
128 /* End of block */
129 if (c & 0x10)
130 poll_finished();
131 } else {
132 if (c & 0x10) {
133 if (hil_dev.curdev)
134 poll_finished(); /* just in case */
135 hil_dev.curdev = c & 7;
136 hil_dev.ptr = 0;
141 static inline void handle_data(unsigned char s, unsigned char c)
143 if (hil_dev.curdev) {
144 hil_dev.data[hil_dev.ptr++] = c;
145 hil_dev.ptr &= 15;
151 * Handle HIL interrupts.
153 static irqreturn_t hil_interrupt(int irq, void *handle)
155 unsigned char s, c;
157 s = hil_status();
158 c = hil_read_data();
160 switch (s >> 4) {
161 case 0x5:
162 handle_status(s, c);
163 break;
164 case 0x6:
165 handle_data(s, c);
166 break;
167 case 0x4:
168 hil_dev.s = s;
169 hil_dev.c = c;
170 mb();
171 hil_dev.valid = 1;
172 break;
174 return IRQ_HANDLED;
178 * Send a command to the HIL
181 static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
183 unsigned long flags;
185 spin_lock_irqsave(&hil_dev.lock, flags);
186 while (hil_busy())
187 /* wait */;
188 hil_command(cmd);
189 while (len--) {
190 while (hil_busy())
191 /* wait */;
192 hil_write_data(*(data++));
194 spin_unlock_irqrestore(&hil_dev.lock, flags);
199 * Initialise HIL.
202 static int __init
203 hil_keyb_init(void)
205 unsigned char c;
206 unsigned int i, kbid;
207 wait_queue_head_t hil_wait;
209 if (hil_dev.dev) {
210 return -ENODEV; /* already initialized */
213 hil_dev.dev = input_allocate_device();
214 if (!hil_dev.dev)
215 return -ENOMEM;
216 hil_dev.dev->private = &hil_dev;
218 #if defined(CONFIG_HP300)
219 if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
220 return -ENODEV;
222 request_region(HILBASE+HIL_DATA, 2, "hil");
223 #endif
225 request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
227 /* Turn on interrupts */
228 hil_do(HIL_INTON, NULL, 0);
230 /* Look for keyboards */
231 hil_dev.valid = 0; /* clear any pending data */
232 hil_do(HIL_READKBDSADR, NULL, 0);
234 init_waitqueue_head(&hil_wait);
235 wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
236 if (!hil_dev.valid) {
237 printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
240 c = hil_dev.c;
241 hil_dev.valid = 0;
242 if (c == 0) {
243 kbid = -1;
244 printk(KERN_WARNING "HIL: no keyboard present.\n");
245 } else {
246 kbid = ffz(~c);
247 /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
250 /* set it to raw mode */
251 c = 0;
252 hil_do(HIL_WRITEKBDSADR, &c, 1);
254 for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
255 if (hphilkeyb_keycode[i] != KEY_RESERVED)
256 set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
258 hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
259 hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
260 hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
261 hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]);
262 hil_dev.dev->keycode = hphilkeyb_keycode;
263 hil_dev.dev->name = "HIL keyboard";
264 hil_dev.dev->phys = "hpkbd/input0";
266 hil_dev.dev->id.bustype = BUS_HIL;
267 hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP;
268 hil_dev.dev->id.product = 0x0001;
269 hil_dev.dev->id.version = 0x0010;
271 input_register_device(hil_dev.dev);
272 printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
273 hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
275 return 0;
278 #if defined(CONFIG_PARISC)
279 static int __init
280 hil_init_chip(struct parisc_device *dev)
282 if (!dev->irq) {
283 printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start);
284 return -ENODEV;
287 hil_base = dev->hpa.start;
288 hil_irq = dev->irq;
289 hil_dev.dev_id = dev;
291 printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
293 return hil_keyb_init();
296 static struct parisc_device_id hil_tbl[] = {
297 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
298 { 0, }
301 MODULE_DEVICE_TABLE(parisc, hil_tbl);
303 static struct parisc_driver hil_driver = {
304 .name = "hil",
305 .id_table = hil_tbl,
306 .probe = hil_init_chip,
308 #endif /* CONFIG_PARISC */
314 static int __init hil_init(void)
316 #if defined(CONFIG_PARISC)
317 return register_parisc_driver(&hil_driver);
318 #else
319 return hil_keyb_init();
320 #endif
324 static void __exit hil_exit(void)
326 if (HIL_IRQ) {
327 disable_irq(HIL_IRQ);
328 free_irq(HIL_IRQ, hil_dev.dev_id);
331 /* Turn off interrupts */
332 hil_do(HIL_INTOFF, NULL, 0);
334 input_unregister_device(hil_dev.dev);
336 hil_dev.dev = NULL;
338 #if defined(CONFIG_PARISC)
339 unregister_parisc_driver(&hil_driver);
340 #else
341 release_region(HILBASE+HIL_DATA, 2);
342 #endif
345 module_init(hil_init);
346 module_exit(hil_exit);