root/drivers/input/keyboard/hilkbd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. poll_finished
  2. handle_status
  3. handle_data
  4. hil_interrupt
  5. hil_do
  6. hil_keyb_init
  7. hil_keyb_exit
  8. hil_probe_chip
  9. hil_remove_chip
  10. hil_init
  11. hil_exit
  12. hil_init
  13. hil_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  linux/drivers/hil/hilkbd.c
   4  *
   5  *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
   6  *  Copyright (C) 1999 Matthew Wilcox <willy@infradead.org>
   7  *  Copyright (C) 1999-2007 Helge Deller <deller@gmx.de>
   8  *
   9  *  Very basic HP Human Interface Loop (HIL) driver.
  10  *  This driver handles the keyboard on HP300 (m68k) and on some
  11  *  HP700 (parisc) series machines.
  12  */
  13 
  14 #include <linux/pci_ids.h>
  15 #include <linux/ioport.h>
  16 #include <linux/module.h>
  17 #include <linux/errno.h>
  18 #include <linux/input.h>
  19 #include <linux/init.h>
  20 #include <linux/interrupt.h>
  21 #include <linux/hil.h>
  22 #include <linux/io.h>
  23 #include <linux/sched.h>
  24 #include <linux/spinlock.h>
  25 #include <asm/irq.h>
  26 #ifdef CONFIG_HP300
  27 #include <asm/hwtest.h>
  28 #endif
  29 
  30 
  31 MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
  32 MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
  33 MODULE_LICENSE("GPL v2");
  34 
  35 
  36 #if defined(CONFIG_PARISC)
  37 
  38  #include <asm/io.h>
  39  #include <asm/hardware.h>
  40  #include <asm/parisc-device.h>
  41  static unsigned long hil_base; /* HPA for the HIL device */
  42  static unsigned int hil_irq;
  43  #define HILBASE                hil_base /* HPPA (parisc) port address */
  44  #define HIL_DATA               0x800
  45  #define HIL_CMD                0x801
  46  #define HIL_IRQ                hil_irq
  47  #define hil_readb(p)           gsc_readb(p)
  48  #define hil_writeb(v,p)        gsc_writeb((v),(p))
  49 
  50 #elif defined(CONFIG_HP300)
  51 
  52  #define HILBASE                0xf0428000UL /* HP300 (m68k) port address */
  53  #define HIL_DATA               0x1
  54  #define HIL_CMD                0x3
  55  #define HIL_IRQ                2
  56  #define hil_readb(p)           readb((const volatile void __iomem *)(p))
  57  #define hil_writeb(v, p)       writeb((v), (volatile void __iomem *)(p))
  58 
  59 #else
  60 #error "HIL is not supported on this platform"
  61 #endif
  62 
  63 
  64 
  65 /* HIL helper functions */
  66 
  67 #define hil_busy()              (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
  68 #define hil_data_available()    (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
  69 #define hil_status()            (hil_readb(HILBASE + HIL_CMD))
  70 #define hil_command(x)          do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
  71 #define hil_read_data()         (hil_readb(HILBASE + HIL_DATA))
  72 #define hil_write_data(x)       do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
  73 
  74 /* HIL constants */
  75 
  76 #define HIL_BUSY                0x02
  77 #define HIL_DATA_RDY            0x01
  78 
  79 #define HIL_SETARD              0xA0            /* set auto-repeat delay */
  80 #define HIL_SETARR              0xA2            /* set auto-repeat rate */
  81 #define HIL_SETTONE             0xA3            /* set tone generator */
  82 #define HIL_CNMT                0xB2            /* clear nmi */
  83 #define HIL_INTON               0x5C            /* Turn on interrupts. */
  84 #define HIL_INTOFF              0x5D            /* Turn off interrupts. */
  85 
  86 #define HIL_READKBDSADR         0xF9
  87 #define HIL_WRITEKBDSADR        0xE9
  88 
  89 static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
  90         { HIL_KEYCODES_SET1 };
  91 
  92 /* HIL structure */
  93 static struct {
  94         struct input_dev *dev;
  95 
  96         unsigned int curdev;
  97 
  98         unsigned char s;
  99         unsigned char c;
 100         int valid;
 101 
 102         unsigned char data[16];
 103         unsigned int ptr;
 104         spinlock_t lock;
 105 
 106         void *dev_id;   /* native bus device */
 107 } hil_dev;
 108 
 109 
 110 static void poll_finished(void)
 111 {
 112         int down;
 113         int key;
 114         unsigned char scode;
 115 
 116         switch (hil_dev.data[0]) {
 117         case 0x40:
 118                 down = (hil_dev.data[1] & 1) == 0;
 119                 scode = hil_dev.data[1] >> 1;
 120                 key = hphilkeyb_keycode[scode];
 121                 input_report_key(hil_dev.dev, key, down);
 122                 break;
 123         }
 124         hil_dev.curdev = 0;
 125 }
 126 
 127 
 128 static inline void handle_status(unsigned char s, unsigned char c)
 129 {
 130         if (c & 0x8) {
 131                 /* End of block */
 132                 if (c & 0x10)
 133                         poll_finished();
 134         } else {
 135                 if (c & 0x10) {
 136                         if (hil_dev.curdev)
 137                                 poll_finished();  /* just in case */
 138                         hil_dev.curdev = c & 7;
 139                         hil_dev.ptr = 0;
 140                 }
 141         }
 142 }
 143 
 144 
 145 static inline void handle_data(unsigned char s, unsigned char c)
 146 {
 147         if (hil_dev.curdev) {
 148                 hil_dev.data[hil_dev.ptr++] = c;
 149                 hil_dev.ptr &= 15;
 150         }
 151 }
 152 
 153 
 154 /* handle HIL interrupts */
 155 static irqreturn_t hil_interrupt(int irq, void *handle)
 156 {
 157         unsigned char s, c;
 158 
 159         s = hil_status();
 160         c = hil_read_data();
 161 
 162         switch (s >> 4) {
 163         case 0x5:
 164                 handle_status(s, c);
 165                 break;
 166         case 0x6:
 167                 handle_data(s, c);
 168                 break;
 169         case 0x4:
 170                 hil_dev.s = s;
 171                 hil_dev.c = c;
 172                 mb();
 173                 hil_dev.valid = 1;
 174                 break;
 175         }
 176         return IRQ_HANDLED;
 177 }
 178 
 179 
 180 /* send a command to the HIL */
 181 static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
 182 {
 183         unsigned long flags;
 184 
 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++));
 193         }
 194         spin_unlock_irqrestore(&hil_dev.lock, flags);
 195 }
 196 
 197 
 198 /* initialize HIL */
 199 static int hil_keyb_init(void)
 200 {
 201         unsigned char c;
 202         unsigned int i, kbid;
 203         wait_queue_head_t hil_wait;
 204         int err;
 205 
 206         if (hil_dev.dev)
 207                 return -ENODEV; /* already initialized */
 208 
 209         init_waitqueue_head(&hil_wait);
 210         spin_lock_init(&hil_dev.lock);
 211 
 212         hil_dev.dev = input_allocate_device();
 213         if (!hil_dev.dev)
 214                 return -ENOMEM;
 215 
 216         err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
 217         if (err) {
 218                 printk(KERN_ERR "HIL: Can't get IRQ\n");
 219                 goto err1;
 220         }
 221 
 222         /* Turn on interrupts */
 223         hil_do(HIL_INTON, NULL, 0);
 224 
 225         /* Look for keyboards */
 226         hil_dev.valid = 0;      /* clear any pending data */
 227         hil_do(HIL_READKBDSADR, NULL, 0);
 228 
 229         wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3 * HZ);
 230         if (!hil_dev.valid)
 231                 printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n");
 232 
 233         c = hil_dev.c;
 234         hil_dev.valid = 0;
 235         if (c == 0) {
 236                 kbid = -1;
 237                 printk(KERN_WARNING "HIL: no keyboard present\n");
 238         } else {
 239                 kbid = ffz(~c);
 240                 printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid);
 241         }
 242 
 243         /* set it to raw mode */
 244         c = 0;
 245         hil_do(HIL_WRITEKBDSADR, &c, 1);
 246 
 247         for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
 248                 if (hphilkeyb_keycode[i] != KEY_RESERVED)
 249                         __set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
 250 
 251         hil_dev.dev->evbit[0]   = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 252         hil_dev.dev->ledbit[0]  = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
 253                 BIT_MASK(LED_SCROLLL);
 254         hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
 255         hil_dev.dev->keycodesize= sizeof(hphilkeyb_keycode[0]);
 256         hil_dev.dev->keycode    = hphilkeyb_keycode;
 257         hil_dev.dev->name       = "HIL keyboard";
 258         hil_dev.dev->phys       = "hpkbd/input0";
 259 
 260         hil_dev.dev->id.bustype = BUS_HIL;
 261         hil_dev.dev->id.vendor  = PCI_VENDOR_ID_HP;
 262         hil_dev.dev->id.product = 0x0001;
 263         hil_dev.dev->id.version = 0x0010;
 264 
 265         err = input_register_device(hil_dev.dev);
 266         if (err) {
 267                 printk(KERN_ERR "HIL: Can't register device\n");
 268                 goto err2;
 269         }
 270 
 271         printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
 272                hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
 273 
 274         return 0;
 275 
 276 err2:
 277         hil_do(HIL_INTOFF, NULL, 0);
 278         free_irq(HIL_IRQ, hil_dev.dev_id);
 279 err1:
 280         input_free_device(hil_dev.dev);
 281         hil_dev.dev = NULL;
 282         return err;
 283 }
 284 
 285 static void hil_keyb_exit(void)
 286 {
 287         if (HIL_IRQ)
 288                 free_irq(HIL_IRQ, hil_dev.dev_id);
 289 
 290         /* Turn off interrupts */
 291         hil_do(HIL_INTOFF, NULL, 0);
 292 
 293         input_unregister_device(hil_dev.dev);
 294         hil_dev.dev = NULL;
 295 }
 296 
 297 #if defined(CONFIG_PARISC)
 298 static int __init hil_probe_chip(struct parisc_device *dev)
 299 {
 300         /* Only allow one HIL keyboard */
 301         if (hil_dev.dev)
 302                 return -ENODEV;
 303 
 304         if (!dev->irq) {
 305                 printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%p\n",
 306                         (void *)dev->hpa.start);
 307                 return -ENODEV;
 308         }
 309 
 310         hil_base = dev->hpa.start;
 311         hil_irq  = dev->irq;
 312         hil_dev.dev_id = dev;
 313 
 314         printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
 315 
 316         return hil_keyb_init();
 317 }
 318 
 319 static int __exit hil_remove_chip(struct parisc_device *dev)
 320 {
 321         hil_keyb_exit();
 322 
 323         return 0;
 324 }
 325 
 326 static const struct parisc_device_id hil_tbl[] __initconst = {
 327         { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
 328         { 0, }
 329 };
 330 
 331 #if 0
 332 /* Disabled to avoid conflicts with the HP SDC HIL drivers */
 333 MODULE_DEVICE_TABLE(parisc, hil_tbl);
 334 #endif
 335 
 336 static struct parisc_driver hil_driver __refdata = {
 337         .name           = "hil",
 338         .id_table       = hil_tbl,
 339         .probe          = hil_probe_chip,
 340         .remove         = __exit_p(hil_remove_chip),
 341 };
 342 
 343 static int __init hil_init(void)
 344 {
 345         return register_parisc_driver(&hil_driver);
 346 }
 347 
 348 static void __exit hil_exit(void)
 349 {
 350         unregister_parisc_driver(&hil_driver);
 351 }
 352 
 353 #else /* !CONFIG_PARISC */
 354 
 355 static int __init hil_init(void)
 356 {
 357         int error;
 358 
 359         /* Only allow one HIL keyboard */
 360         if (hil_dev.dev)
 361                 return -EBUSY;
 362 
 363         if (!MACH_IS_HP300)
 364                 return -ENODEV;
 365 
 366         if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
 367                 printk(KERN_ERR "HIL: hardware register was not found\n");
 368                 return -ENODEV;
 369         }
 370 
 371         if (!request_region(HILBASE + HIL_DATA, 2, "hil")) {
 372                 printk(KERN_ERR "HIL: IOPORT region already used\n");
 373                 return -EIO;
 374         }
 375 
 376         error = hil_keyb_init();
 377         if (error) {
 378                 release_region(HILBASE + HIL_DATA, 2);
 379                 return error;
 380         }
 381 
 382         return 0;
 383 }
 384 
 385 static void __exit hil_exit(void)
 386 {
 387         hil_keyb_exit();
 388         release_region(HILBASE + HIL_DATA, 2);
 389 }
 390 
 391 #endif /* CONFIG_PARISC */
 392 
 393 module_init(hil_init);
 394 module_exit(hil_exit);

/* [<][>][^][v][top][bottom][index][help] */