Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * SGI O2 MACE PS2 controller driver for linux
0004  *
0005  * Copyright (C) 2002 Vivien Chappelier
0006  */
0007 #include <linux/module.h>
0008 #include <linux/init.h>
0009 #include <linux/serio.h>
0010 #include <linux/errno.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/ioport.h>
0013 #include <linux/delay.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/err.h>
0018 
0019 #include <asm/io.h>
0020 #include <asm/irq.h>
0021 #include <asm/ip32/mace.h>
0022 #include <asm/ip32/ip32_ints.h>
0023 
0024 MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org");
0025 MODULE_DESCRIPTION("SGI O2 MACE PS2 controller driver");
0026 MODULE_LICENSE("GPL");
0027 
0028 #define MACE_PS2_TIMEOUT 10000 /* in 50us unit */
0029 
0030 #define PS2_STATUS_CLOCK_SIGNAL  BIT(0) /* external clock signal */
0031 #define PS2_STATUS_CLOCK_INHIBIT BIT(1) /* clken output signal */
0032 #define PS2_STATUS_TX_INPROGRESS BIT(2) /* transmission in progress */
0033 #define PS2_STATUS_TX_EMPTY      BIT(3) /* empty transmit buffer */
0034 #define PS2_STATUS_RX_FULL       BIT(4) /* full receive buffer */
0035 #define PS2_STATUS_RX_INPROGRESS BIT(5) /* reception in progress */
0036 #define PS2_STATUS_ERROR_PARITY  BIT(6) /* parity error */
0037 #define PS2_STATUS_ERROR_FRAMING BIT(7) /* framing error */
0038 
0039 #define PS2_CONTROL_TX_CLOCK_DISABLE BIT(0) /* inhibit clock signal after TX */
0040 #define PS2_CONTROL_TX_ENABLE        BIT(1) /* transmit enable */
0041 #define PS2_CONTROL_TX_INT_ENABLE    BIT(2) /* enable transmit interrupt */
0042 #define PS2_CONTROL_RX_INT_ENABLE    BIT(3) /* enable receive interrupt */
0043 #define PS2_CONTROL_RX_CLOCK_ENABLE  BIT(4) /* pause reception if set to 0 */
0044 #define PS2_CONTROL_RESET            BIT(5) /* reset */
0045 
0046 struct maceps2_data {
0047     struct mace_ps2port *port;
0048     int irq;
0049 };
0050 
0051 static struct maceps2_data port_data[2];
0052 static struct serio *maceps2_port[2];
0053 static struct platform_device *maceps2_device;
0054 
0055 static int maceps2_write(struct serio *dev, unsigned char val)
0056 {
0057     struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
0058     unsigned int timeout = MACE_PS2_TIMEOUT;
0059 
0060     do {
0061         if (port->status & PS2_STATUS_TX_EMPTY) {
0062             port->tx = val;
0063             return 0;
0064         }
0065         udelay(50);
0066     } while (timeout--);
0067 
0068     return -1;
0069 }
0070 
0071 static irqreturn_t maceps2_interrupt(int irq, void *dev_id)
0072 {
0073     struct serio *dev = dev_id;
0074     struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
0075     unsigned long byte;
0076 
0077     if (port->status & PS2_STATUS_RX_FULL) {
0078         byte = port->rx;
0079         serio_interrupt(dev, byte & 0xff, 0);
0080         }
0081 
0082     return IRQ_HANDLED;
0083 }
0084 
0085 static int maceps2_open(struct serio *dev)
0086 {
0087     struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
0088 
0089     if (request_irq(data->irq, maceps2_interrupt, 0, "PS2 port", dev)) {
0090         printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
0091         return -EBUSY;
0092     }
0093 
0094     /* Reset port */
0095     data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
0096     udelay(100);
0097 
0098         /* Enable interrupts */
0099     data->port->control = PS2_CONTROL_RX_CLOCK_ENABLE |
0100                   PS2_CONTROL_TX_ENABLE |
0101                   PS2_CONTROL_RX_INT_ENABLE;
0102 
0103     return 0;
0104 }
0105 
0106 static void maceps2_close(struct serio *dev)
0107 {
0108     struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
0109 
0110     data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
0111     udelay(100);
0112     free_irq(data->irq, dev);
0113 }
0114 
0115 
0116 static struct serio *maceps2_allocate_port(int idx)
0117 {
0118     struct serio *serio;
0119 
0120     serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
0121     if (serio) {
0122         serio->id.type      = SERIO_8042;
0123         serio->write        = maceps2_write;
0124         serio->open     = maceps2_open;
0125         serio->close        = maceps2_close;
0126         snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
0127         snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
0128         serio->port_data    = &port_data[idx];
0129         serio->dev.parent   = &maceps2_device->dev;
0130     }
0131 
0132     return serio;
0133 }
0134 
0135 static int maceps2_probe(struct platform_device *dev)
0136 {
0137     maceps2_port[0] = maceps2_allocate_port(0);
0138     maceps2_port[1] = maceps2_allocate_port(1);
0139     if (!maceps2_port[0] || !maceps2_port[1]) {
0140         kfree(maceps2_port[0]);
0141         kfree(maceps2_port[1]);
0142         return -ENOMEM;
0143     }
0144 
0145     serio_register_port(maceps2_port[0]);
0146     serio_register_port(maceps2_port[1]);
0147 
0148     return 0;
0149 }
0150 
0151 static int maceps2_remove(struct platform_device *dev)
0152 {
0153     serio_unregister_port(maceps2_port[0]);
0154     serio_unregister_port(maceps2_port[1]);
0155 
0156     return 0;
0157 }
0158 
0159 static struct platform_driver maceps2_driver = {
0160     .driver     = {
0161         .name   = "maceps2",
0162     },
0163     .probe      = maceps2_probe,
0164     .remove     = maceps2_remove,
0165 };
0166 
0167 static int __init maceps2_init(void)
0168 {
0169     int error;
0170 
0171     error = platform_driver_register(&maceps2_driver);
0172     if (error)
0173         return error;
0174 
0175     maceps2_device = platform_device_alloc("maceps2", -1);
0176     if (!maceps2_device) {
0177         error = -ENOMEM;
0178         goto err_unregister_driver;
0179     }
0180 
0181     port_data[0].port = &mace->perif.ps2.keyb;
0182     port_data[0].irq  = MACEISA_KEYB_IRQ;
0183     port_data[1].port = &mace->perif.ps2.mouse;
0184     port_data[1].irq  = MACEISA_MOUSE_IRQ;
0185 
0186     error = platform_device_add(maceps2_device);
0187     if (error)
0188         goto err_free_device;
0189 
0190     return 0;
0191 
0192  err_free_device:
0193     platform_device_put(maceps2_device);
0194  err_unregister_driver:
0195     platform_driver_unregister(&maceps2_driver);
0196     return error;
0197 }
0198 
0199 static void __exit maceps2_exit(void)
0200 {
0201     platform_device_unregister(maceps2_device);
0202     platform_driver_unregister(&maceps2_driver);
0203 }
0204 
0205 module_init(maceps2_init);
0206 module_exit(maceps2_exit);