OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [hil/] [hilkbd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/hil/hilkbd.c
3
 *
4
 *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5
 *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
6
 *  Copyright (C) 1999-2002 Helge Deller <deller@gmx.de>
7
 *
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.
11
 *
12
 *
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.
16
 */
17
 
18
#include <linux/pci_ids.h>
19
#include <linux/ioport.h>
20
#include <linux/module.h>
21
#include <linux/config.h>
22
#include <linux/errno.h>
23
#include <linux/input.h>
24
#include <linux/init.h>
25
#include <linux/irq.h>
26
#include <linux/hil.h>
27
 
28
 
29
MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
30
MODULE_DESCRIPTION("HIL driver (basic functionality)");
31
MODULE_LICENSE("GPL");
32
EXPORT_NO_SYMBOLS;
33
 
34
 
35
#if defined(CONFIG_PARISC)
36
 
37
 #include <asm/gsc.h>
38
 #include <asm/hardware.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))
47
 
48
#elif defined(CONFIG_HP300)
49
 
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))
56
 
57
#else
58
#error "HIL is not supported on this platform"
59
#endif
60
 
61
 
62
 
63
/* HIL helper functions */
64
 
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)
71
 
72
/* HIL constants */
73
 
74
#define HIL_BUSY                0x02
75
#define HIL_DATA_RDY            0x01
76
 
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. */
83
#define HIL_TRIGGER             0xC5            /* trigger command */
84
#define HIL_STARTCMD            0xE0            /* start loop command */
85
#define HIL_TIMEOUT             0xFE            /* timeout */
86
#define HIL_READTIME            0x13            /* Read real time register */
87
 
88
#define HIL_READBUSY            0x02            /* internal "busy" register */
89
#define HIL_READKBDLANG         0x12            /* read keyboard language code */
90
#define HIL_READKBDSADR         0xF9
91
#define HIL_WRITEKBDSADR        0xE9
92
#define HIL_READLPSTAT          0xFA
93
#define HIL_WRITELPSTAT         0xEA
94
#define HIL_READLPCTRL          0xFB
95
#define HIL_WRITELPCTRL         0xEB
96
 
97
 
98
static unsigned char hil_kbd_set1[128] = {
99
   KEY_5,               KEY_RESERVED,   KEY_RIGHTALT,   KEY_LEFTALT,
100
   KEY_RIGHTSHIFT,      KEY_LEFTSHIFT,  KEY_LEFTCTRL,   KEY_SYSRQ,
101
   KEY_KP4,             KEY_KP8,        KEY_KP5,        KEY_KP9,
102
   KEY_KP6,             KEY_KP7,        KEY_KPCOMMA,    KEY_KPENTER,
103
   KEY_KP1,             KEY_KPSLASH,    KEY_KP2,        KEY_KPPLUS,
104
   KEY_KP3,             KEY_KPASTERISK, KEY_KP0,        KEY_KPMINUS,
105
   KEY_B,               KEY_V,          KEY_C,          KEY_X,
106
   KEY_Z,               KEY_UNKNOWN,    KEY_RESERVED,   KEY_ESC,
107
   KEY_6,               KEY_F10,        KEY_3,          KEY_F11,
108
   KEY_KPDOT,           KEY_F9,         KEY_TAB /*KP*/, KEY_F12,
109
   KEY_H,               KEY_G,          KEY_F,          KEY_D,
110
   KEY_S,               KEY_A,          KEY_RESERVED,   KEY_CAPSLOCK,
111
   KEY_U,               KEY_Y,          KEY_T,          KEY_R,
112
   KEY_E,               KEY_W,          KEY_Q,          KEY_TAB,
113
   KEY_7,               KEY_6,          KEY_5,          KEY_4,
114
   KEY_3,               KEY_2,          KEY_1,          KEY_GRAVE,
115
   KEY_INTL1,           KEY_INTL2,      KEY_INTL3,      KEY_INTL4, /*Buttons*/
116
   KEY_INTL5,           KEY_INTL6,      KEY_INTL7,      KEY_INTL8,
117
   KEY_MENU,            KEY_F4,         KEY_F3,         KEY_F2,
118
   KEY_F1,              KEY_VOLUMEUP,   KEY_STOP,       KEY_SENDFILE/*Enter/Print*/,
119
   KEY_SYSRQ,           KEY_F5,         KEY_F6,         KEY_F7,
120
   KEY_F8,              KEY_VOLUMEDOWN, KEY_CUT /*CLEAR_LINE*/, KEY_REFRESH /*CLEAR_DISPLAY*/,
121
   KEY_8,               KEY_9,          KEY_0,          KEY_MINUS,
122
   KEY_EQUAL,           KEY_BACKSPACE,  KEY_INSERT/*KPINSERT_LINE*/, KEY_DELETE /*KPDELETE_LINE*/,
123
   KEY_I,               KEY_O,          KEY_P,          KEY_LEFTBRACE,
124
   KEY_RIGHTBRACE,      KEY_BACKSLASH,  KEY_INSERT,     KEY_DELETE,
125
   KEY_J,               KEY_K,          KEY_L,          KEY_SEMICOLON,
126
   KEY_APOSTROPHE,      KEY_ENTER,      KEY_HOME,       KEY_SCROLLUP,
127
   KEY_M,               KEY_COMMA,      KEY_DOT,        KEY_SLASH,
128
   KEY_RESERVED,        KEY_OPEN/*Select*/,KEY_RESERVED,KEY_SCROLLDOWN/*KPNEXT*/,
129
   KEY_N,               KEY_SPACE,      KEY_SCROLLDOWN/*Next*/, KEY_UNKNOWN,
130
   KEY_LEFT,            KEY_DOWN,       KEY_UP,         KEY_RIGHT
131
};
132
 
133
 
134
/* HIL structure */
135
static struct {
136
        struct input_dev dev;
137
 
138
        unsigned int curdev;
139
 
140
        unsigned char s;
141
        unsigned char c;
142
        int valid;
143
 
144
        unsigned char data[16];
145
        unsigned int ptr;
146
 
147
        void *dev_id;   /* native bus device */
148
} hil_dev;
149
 
150
 
151
static void poll_finished(void)
152
{
153
        int down;
154
        int key;
155
        unsigned char scode;
156
 
157
        switch (hil_dev.data[0]) {
158
        case 0x40:
159
                down = (hil_dev.data[1] & 1) == 0;
160
                scode = hil_dev.data[1] >> 1;
161
                key = hil_kbd_set1[scode & 0x7f];
162
                input_report_key(&hil_dev.dev, key, down);
163
                break;
164
        }
165
        hil_dev.curdev = 0;
166
}
167
 
168
static inline void handle_status(unsigned char s, unsigned char c)
169
{
170
        if (c & 0x8) {
171
                /* End of block */
172
                if (c & 0x10)
173
                        poll_finished();
174
        } else {
175
                if (c & 0x10) {
176
                        if (hil_dev.curdev)
177
                                poll_finished();  /* just in case */
178
                        hil_dev.curdev = c & 7;
179
                        hil_dev.ptr = 0;
180
                }
181
        }
182
}
183
 
184
static inline void handle_data(unsigned char s, unsigned char c)
185
{
186
        if (hil_dev.curdev) {
187
                hil_dev.data[hil_dev.ptr++] = c;
188
                hil_dev.ptr &= 15;
189
        }
190
}
191
 
192
 
193
/*
194
 * Handle HIL interrupts.
195
 */
196
static void hil_interrupt(int irq, void *handle, struct pt_regs *regs)
197
{
198
        unsigned char s, c;
199
 
200
        s = hil_status();
201
        c = hil_read_data();
202
 
203
        switch (s >> 4) {
204
        case 0x5:
205
                handle_status(s, c);
206
                break;
207
        case 0x6:
208
                handle_data(s, c);
209
                break;
210
        case 0x4:
211
                hil_dev.s = s;
212
                hil_dev.c = c;
213
                mb();
214
                hil_dev.valid = 1;
215
                break;
216
        }
217
}
218
 
219
/*
220
 * Send a command to the HIL
221
 */
222
 
223
static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
224
{
225
        unsigned long flags;
226
 
227
        save_flags(flags);
228
        cli();
229
        while (hil_busy())
230
                /* wait */;
231
        hil_command(cmd);
232
        while (len--) {
233
                while (hil_busy())
234
                        /* wait */;
235
                hil_write_data(*(data++));
236
        }
237
        restore_flags(flags);
238
}
239
 
240
 
241
/*
242
 * Initialise HIL.
243
 */
244
 
245
static int __init
246
hil_keyb_init(void)
247
{
248
        unsigned char c;
249
        unsigned int i, kbid, n = 0;
250
 
251
        if (hil_dev.dev.idbus) {
252
                printk("HIL: already initialized\n");
253
                return -ENODEV;
254
        }
255
 
256
#if defined(CONFIG_HP300)
257
        if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
258
                return -ENODEV;
259
 
260
        request_region(HILBASE+HIL_DATA, 2, "hil");
261
#endif
262
 
263
        request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
264
 
265
        /* Turn on interrupts */
266
        hil_do(HIL_INTON, NULL, 0);
267
 
268
        /* Look for keyboards */
269
        hil_dev.valid = 0;       /* clear any pending data */
270
        hil_do(HIL_READKBDSADR, NULL, 0);
271
        while (!hil_dev.valid) {
272
                if (n++ > 100000) {
273
                        printk(KERN_DEBUG "HIL: timed out, assuming no keyboard present.\n");
274
                        break;
275
                }
276
                mb();
277
        }
278
 
279
        c = hil_dev.c;
280
        hil_dev.valid = 0;
281
        if (c == 0) {
282
                kbid = -1;
283
                printk(KERN_WARNING "HIL: no keyboard present.\n");
284
        } else {
285
                kbid = ffz(~c);
286
                printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid);
287
        }
288
 
289
        /* set it to raw mode */
290
        c = 0;
291
        hil_do(HIL_WRITEKBDSADR, &c, 1);
292
 
293
 
294
        /* register input interface */
295
        hil_dev.dev.name        = "HIL keyboard";
296
        hil_dev.dev.idbus       = BUS_HIL;
297
        hil_dev.dev.idvendor    = PCI_VENDOR_ID_HP;
298
        hil_dev.dev.idproduct   = 0x0001;
299
        hil_dev.dev.idversion   = 0x0100;
300
 
301
        hil_dev.dev.evbit[0] |= BIT(EV_KEY);
302
        for (i = 0; i < 128; i++)
303
                set_bit(hil_kbd_set1[i], hil_dev.dev.keybit);
304
        clear_bit(0, hil_dev.dev.keybit);
305
 
306
#if 1
307
        /* XXX: HACK !!!
308
         * remove this call if hp_psaux.c/hp_keyb.c is converted
309
         * to the input layer... */
310
        register_ps2_keybfuncs();
311
#endif
312
 
313
        input_register_device(&hil_dev.dev);
314
        printk(KERN_INFO "input%d: %s on hil%d (id %d)\n",
315
                hil_dev.dev.number, hil_dev.dev.name, 0, kbid);
316
 
317
        /* HIL keyboards don't have a numlock key,
318
         * simulate a up-down sequence of numlock to
319
         * make the keypad work at expected. */
320
        input_report_key(&hil_dev.dev, KEY_NUMLOCK, 1);
321
 
322
        return 0;
323
}
324
 
325
#if defined(CONFIG_PARISC)
326
static int __init
327
hil_init_chip(struct parisc_device *dev)
328
{
329
        if (!dev->irq) {
330
                printk(KERN_WARNING "HIL: IRQ not found for HIL at 0x%lx\n", dev->hpa);
331
                return -ENODEV;
332
        }
333
 
334
        hil_base = dev->hpa;
335
        hil_irq  = dev->irq;
336
        hil_dev.dev_id = dev;
337
 
338
        printk(KERN_INFO "Found HIL at 0x%lx, IRQ %d\n", hil_base, hil_irq);
339
 
340
        return hil_keyb_init();
341
}
342
 
343
static struct parisc_device_id hil_tbl[] = {
344
        { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
345
        { 0, }
346
};
347
 
348
MODULE_DEVICE_TABLE(parisc, hil_tbl);
349
 
350
static struct parisc_driver hil_driver = {
351
        .name =         "HIL",
352
        .id_table =     hil_tbl,
353
        .probe =        hil_init_chip,
354
};
355
#endif /* CONFIG_PARISC */
356
 
357
 
358
 
359
 
360
 
361
static int __init hil_init(void)
362
{
363
#if defined(CONFIG_PARISC)
364
        return register_parisc_driver(&hil_driver);
365
#else
366
        return hil_keyb_init();
367
#endif
368
}
369
 
370
 
371
static void __exit hil_exit(void)
372
{
373
        if (HIL_IRQ) {
374
                disable_irq(HIL_IRQ);
375
                free_irq(HIL_IRQ, hil_dev.dev_id);
376
        }
377
 
378
        input_unregister_device(&hil_dev.dev);
379
 
380
#if defined(CONFIG_PARISC)
381
        unregister_parisc_driver(&hil_driver);
382
#else
383
        release_region(HILBASE+HIL_DATA, 2);
384
#endif
385
}
386
 
387
module_init(hil_init);
388
module_exit(hil_exit);
389
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.