root/drivers/input/serio/maceps2.c

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

DEFINITIONS

This source file includes following definitions.
  1. maceps2_write
  2. maceps2_interrupt
  3. maceps2_open
  4. maceps2_close
  5. maceps2_allocate_port
  6. maceps2_probe
  7. maceps2_remove
  8. maceps2_init
  9. maceps2_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * SGI O2 MACE PS2 controller driver for linux
   4  *
   5  * Copyright (C) 2002 Vivien Chappelier
   6  */
   7 #include <linux/module.h>
   8 #include <linux/init.h>
   9 #include <linux/serio.h>
  10 #include <linux/errno.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/ioport.h>
  13 #include <linux/delay.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/slab.h>
  16 #include <linux/spinlock.h>
  17 #include <linux/err.h>
  18 
  19 #include <asm/io.h>
  20 #include <asm/irq.h>
  21 #include <asm/ip32/mace.h>
  22 #include <asm/ip32/ip32_ints.h>
  23 
  24 MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org");
  25 MODULE_DESCRIPTION("SGI O2 MACE PS2 controller driver");
  26 MODULE_LICENSE("GPL");
  27 
  28 #define MACE_PS2_TIMEOUT 10000 /* in 50us unit */
  29 
  30 #define PS2_STATUS_CLOCK_SIGNAL  BIT(0) /* external clock signal */
  31 #define PS2_STATUS_CLOCK_INHIBIT BIT(1) /* clken output signal */
  32 #define PS2_STATUS_TX_INPROGRESS BIT(2) /* transmission in progress */
  33 #define PS2_STATUS_TX_EMPTY      BIT(3) /* empty transmit buffer */
  34 #define PS2_STATUS_RX_FULL       BIT(4) /* full receive buffer */
  35 #define PS2_STATUS_RX_INPROGRESS BIT(5) /* reception in progress */
  36 #define PS2_STATUS_ERROR_PARITY  BIT(6) /* parity error */
  37 #define PS2_STATUS_ERROR_FRAMING BIT(7) /* framing error */
  38 
  39 #define PS2_CONTROL_TX_CLOCK_DISABLE BIT(0) /* inhibit clock signal after TX */
  40 #define PS2_CONTROL_TX_ENABLE        BIT(1) /* transmit enable */
  41 #define PS2_CONTROL_TX_INT_ENABLE    BIT(2) /* enable transmit interrupt */
  42 #define PS2_CONTROL_RX_INT_ENABLE    BIT(3) /* enable receive interrupt */
  43 #define PS2_CONTROL_RX_CLOCK_ENABLE  BIT(4) /* pause reception if set to 0 */
  44 #define PS2_CONTROL_RESET            BIT(5) /* reset */
  45 
  46 struct maceps2_data {
  47         struct mace_ps2port *port;
  48         int irq;
  49 };
  50 
  51 static struct maceps2_data port_data[2];
  52 static struct serio *maceps2_port[2];
  53 static struct platform_device *maceps2_device;
  54 
  55 static int maceps2_write(struct serio *dev, unsigned char val)
  56 {
  57         struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
  58         unsigned int timeout = MACE_PS2_TIMEOUT;
  59 
  60         do {
  61                 if (port->status & PS2_STATUS_TX_EMPTY) {
  62                         port->tx = val;
  63                         return 0;
  64                 }
  65                 udelay(50);
  66         } while (timeout--);
  67 
  68         return -1;
  69 }
  70 
  71 static irqreturn_t maceps2_interrupt(int irq, void *dev_id)
  72 {
  73         struct serio *dev = dev_id;
  74         struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
  75         unsigned long byte;
  76 
  77         if (port->status & PS2_STATUS_RX_FULL) {
  78                 byte = port->rx;
  79                 serio_interrupt(dev, byte & 0xff, 0);
  80         }
  81 
  82         return IRQ_HANDLED;
  83 }
  84 
  85 static int maceps2_open(struct serio *dev)
  86 {
  87         struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
  88 
  89         if (request_irq(data->irq, maceps2_interrupt, 0, "PS2 port", dev)) {
  90                 printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
  91                 return -EBUSY;
  92         }
  93 
  94         /* Reset port */
  95         data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
  96         udelay(100);
  97 
  98         /* Enable interrupts */
  99         data->port->control = PS2_CONTROL_RX_CLOCK_ENABLE |
 100                               PS2_CONTROL_TX_ENABLE |
 101                               PS2_CONTROL_RX_INT_ENABLE;
 102 
 103         return 0;
 104 }
 105 
 106 static void maceps2_close(struct serio *dev)
 107 {
 108         struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 109 
 110         data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
 111         udelay(100);
 112         free_irq(data->irq, dev);
 113 }
 114 
 115 
 116 static struct serio *maceps2_allocate_port(int idx)
 117 {
 118         struct serio *serio;
 119 
 120         serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 121         if (serio) {
 122                 serio->id.type          = SERIO_8042;
 123                 serio->write            = maceps2_write;
 124                 serio->open             = maceps2_open;
 125                 serio->close            = maceps2_close;
 126                 snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
 127                 snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
 128                 serio->port_data        = &port_data[idx];
 129                 serio->dev.parent       = &maceps2_device->dev;
 130         }
 131 
 132         return serio;
 133 }
 134 
 135 static int maceps2_probe(struct platform_device *dev)
 136 {
 137         maceps2_port[0] = maceps2_allocate_port(0);
 138         maceps2_port[1] = maceps2_allocate_port(1);
 139         if (!maceps2_port[0] || !maceps2_port[1]) {
 140                 kfree(maceps2_port[0]);
 141                 kfree(maceps2_port[1]);
 142                 return -ENOMEM;
 143         }
 144 
 145         serio_register_port(maceps2_port[0]);
 146         serio_register_port(maceps2_port[1]);
 147 
 148         return 0;
 149 }
 150 
 151 static int maceps2_remove(struct platform_device *dev)
 152 {
 153         serio_unregister_port(maceps2_port[0]);
 154         serio_unregister_port(maceps2_port[1]);
 155 
 156         return 0;
 157 }
 158 
 159 static struct platform_driver maceps2_driver = {
 160         .driver         = {
 161                 .name   = "maceps2",
 162         },
 163         .probe          = maceps2_probe,
 164         .remove         = maceps2_remove,
 165 };
 166 
 167 static int __init maceps2_init(void)
 168 {
 169         int error;
 170 
 171         error = platform_driver_register(&maceps2_driver);
 172         if (error)
 173                 return error;
 174 
 175         maceps2_device = platform_device_alloc("maceps2", -1);
 176         if (!maceps2_device) {
 177                 error = -ENOMEM;
 178                 goto err_unregister_driver;
 179         }
 180 
 181         port_data[0].port = &mace->perif.ps2.keyb;
 182         port_data[0].irq  = MACEISA_KEYB_IRQ;
 183         port_data[1].port = &mace->perif.ps2.mouse;
 184         port_data[1].irq  = MACEISA_MOUSE_IRQ;
 185 
 186         error = platform_device_add(maceps2_device);
 187         if (error)
 188                 goto err_free_device;
 189 
 190         return 0;
 191 
 192  err_free_device:
 193         platform_device_put(maceps2_device);
 194  err_unregister_driver:
 195         platform_driver_unregister(&maceps2_driver);
 196         return error;
 197 }
 198 
 199 static void __exit maceps2_exit(void)
 200 {
 201         platform_device_unregister(maceps2_device);
 202         platform_driver_unregister(&maceps2_driver);
 203 }
 204 
 205 module_init(maceps2_init);
 206 module_exit(maceps2_exit);

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