Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0004  *
0005  * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com>
0006  */
0007 
0008 #include <linux/err.h>
0009 #include <linux/module.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/input.h>
0012 #include <linux/serio.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/of.h>
0015 #include <linux/io.h>
0016 #include <linux/kernel.h>
0017 #include <linux/slab.h>
0018 
0019 #define ARC_PS2_PORTS                   2
0020 
0021 #define ARC_ARC_PS2_ID                  0x0001f609
0022 
0023 #define STAT_TIMEOUT                    128
0024 
0025 #define PS2_STAT_RX_FRM_ERR             (1)
0026 #define PS2_STAT_RX_BUF_OVER            (1 << 1)
0027 #define PS2_STAT_RX_INT_EN              (1 << 2)
0028 #define PS2_STAT_RX_VAL                 (1 << 3)
0029 #define PS2_STAT_TX_ISNOT_FUL           (1 << 4)
0030 #define PS2_STAT_TX_INT_EN              (1 << 5)
0031 
0032 struct arc_ps2_port {
0033     void __iomem *data_addr;
0034     void __iomem *status_addr;
0035     struct serio *io;
0036 };
0037 
0038 struct arc_ps2_data {
0039     struct arc_ps2_port port[ARC_PS2_PORTS];
0040     void __iomem *addr;
0041     unsigned int frame_error;
0042     unsigned int buf_overflow;
0043     unsigned int total_int;
0044 };
0045 
0046 static void arc_ps2_check_rx(struct arc_ps2_data *arc_ps2,
0047                  struct arc_ps2_port *port)
0048 {
0049     unsigned int timeout = 1000;
0050     unsigned int flag, status;
0051     unsigned char data;
0052 
0053     do {
0054         status = ioread32(port->status_addr);
0055         if (!(status & PS2_STAT_RX_VAL))
0056             return;
0057 
0058         data = ioread32(port->data_addr) & 0xff;
0059 
0060         flag = 0;
0061         arc_ps2->total_int++;
0062         if (status & PS2_STAT_RX_FRM_ERR) {
0063             arc_ps2->frame_error++;
0064             flag |= SERIO_PARITY;
0065         } else if (status & PS2_STAT_RX_BUF_OVER) {
0066             arc_ps2->buf_overflow++;
0067             flag |= SERIO_FRAME;
0068         }
0069 
0070         serio_interrupt(port->io, data, flag);
0071     } while (--timeout);
0072 
0073     dev_err(&port->io->dev, "PS/2 hardware stuck\n");
0074 }
0075 
0076 static irqreturn_t arc_ps2_interrupt(int irq, void *dev)
0077 {
0078     struct arc_ps2_data *arc_ps2 = dev;
0079     int i;
0080 
0081     for (i = 0; i < ARC_PS2_PORTS; i++)
0082         arc_ps2_check_rx(arc_ps2, &arc_ps2->port[i]);
0083 
0084     return IRQ_HANDLED;
0085 }
0086 
0087 static int arc_ps2_write(struct serio *io, unsigned char val)
0088 {
0089     unsigned status;
0090     struct arc_ps2_port *port = io->port_data;
0091     int timeout = STAT_TIMEOUT;
0092 
0093     do {
0094         status = ioread32(port->status_addr);
0095         cpu_relax();
0096 
0097         if (status & PS2_STAT_TX_ISNOT_FUL) {
0098             iowrite32(val & 0xff, port->data_addr);
0099             return 0;
0100         }
0101 
0102     } while (--timeout);
0103 
0104     dev_err(&io->dev, "write timeout\n");
0105     return -ETIMEDOUT;
0106 }
0107 
0108 static int arc_ps2_open(struct serio *io)
0109 {
0110     struct arc_ps2_port *port = io->port_data;
0111 
0112     iowrite32(PS2_STAT_RX_INT_EN, port->status_addr);
0113 
0114     return 0;
0115 }
0116 
0117 static void arc_ps2_close(struct serio *io)
0118 {
0119     struct arc_ps2_port *port = io->port_data;
0120 
0121     iowrite32(ioread32(port->status_addr) & ~PS2_STAT_RX_INT_EN,
0122           port->status_addr);
0123 }
0124 
0125 static void __iomem *arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2,
0126                           int index, bool status)
0127 {
0128     void __iomem *addr;
0129 
0130     addr = arc_ps2->addr + 4 + 4 * index;
0131     if (status)
0132         addr += ARC_PS2_PORTS * 4;
0133 
0134     return addr;
0135 }
0136 
0137 static void arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2)
0138 {
0139     void __iomem *addr;
0140     u32 val;
0141     int i;
0142 
0143     for (i = 0; i < ARC_PS2_PORTS; i++) {
0144         addr = arc_ps2_calc_addr(arc_ps2, i, true);
0145         val = ioread32(addr);
0146         val &= ~(PS2_STAT_RX_INT_EN | PS2_STAT_TX_INT_EN);
0147         iowrite32(val, addr);
0148     }
0149 }
0150 
0151 static int arc_ps2_create_port(struct platform_device *pdev,
0152                      struct arc_ps2_data *arc_ps2,
0153                      int index)
0154 {
0155     struct arc_ps2_port *port = &arc_ps2->port[index];
0156     struct serio *io;
0157 
0158     io = kzalloc(sizeof(struct serio), GFP_KERNEL);
0159     if (!io)
0160         return -ENOMEM;
0161 
0162     io->id.type = SERIO_8042;
0163     io->write = arc_ps2_write;
0164     io->open = arc_ps2_open;
0165     io->close = arc_ps2_close;
0166     snprintf(io->name, sizeof(io->name), "ARC PS/2 port%d", index);
0167     snprintf(io->phys, sizeof(io->phys), "arc/serio%d", index);
0168     io->port_data = port;
0169 
0170     port->io = io;
0171 
0172     port->data_addr = arc_ps2_calc_addr(arc_ps2, index, false);
0173     port->status_addr = arc_ps2_calc_addr(arc_ps2, index, true);
0174 
0175     dev_dbg(&pdev->dev, "port%d is allocated (data = 0x%p, status = 0x%p)\n",
0176         index, port->data_addr, port->status_addr);
0177 
0178     serio_register_port(port->io);
0179     return 0;
0180 }
0181 
0182 static int arc_ps2_probe(struct platform_device *pdev)
0183 {
0184     struct arc_ps2_data *arc_ps2;
0185     struct resource *res;
0186     int irq;
0187     int error, id, i;
0188 
0189     irq = platform_get_irq_byname(pdev, "arc_ps2_irq");
0190     if (irq < 0)
0191         return -EINVAL;
0192 
0193     arc_ps2 = devm_kzalloc(&pdev->dev, sizeof(struct arc_ps2_data),
0194                 GFP_KERNEL);
0195     if (!arc_ps2) {
0196         dev_err(&pdev->dev, "out of memory\n");
0197         return -ENOMEM;
0198     }
0199 
0200     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0201     arc_ps2->addr = devm_ioremap_resource(&pdev->dev, res);
0202     if (IS_ERR(arc_ps2->addr))
0203         return PTR_ERR(arc_ps2->addr);
0204 
0205     dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n",
0206          irq, arc_ps2->addr, ARC_PS2_PORTS);
0207 
0208     id = ioread32(arc_ps2->addr);
0209     if (id != ARC_ARC_PS2_ID) {
0210         dev_err(&pdev->dev, "device id does not match\n");
0211         return -ENXIO;
0212     }
0213 
0214     arc_ps2_inhibit_ports(arc_ps2);
0215 
0216     error = devm_request_irq(&pdev->dev, irq, arc_ps2_interrupt,
0217                  0, "arc_ps2", arc_ps2);
0218     if (error) {
0219         dev_err(&pdev->dev, "Could not allocate IRQ\n");
0220         return error;
0221     }
0222 
0223     for (i = 0; i < ARC_PS2_PORTS; i++) {
0224         error = arc_ps2_create_port(pdev, arc_ps2, i);
0225         if (error) {
0226             while (--i >= 0)
0227                 serio_unregister_port(arc_ps2->port[i].io);
0228             return error;
0229         }
0230     }
0231 
0232     platform_set_drvdata(pdev, arc_ps2);
0233 
0234     return 0;
0235 }
0236 
0237 static int arc_ps2_remove(struct platform_device *pdev)
0238 {
0239     struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev);
0240     int i;
0241 
0242     for (i = 0; i < ARC_PS2_PORTS; i++)
0243         serio_unregister_port(arc_ps2->port[i].io);
0244 
0245     dev_dbg(&pdev->dev, "interrupt count = %i\n", arc_ps2->total_int);
0246     dev_dbg(&pdev->dev, "frame error count = %i\n", arc_ps2->frame_error);
0247     dev_dbg(&pdev->dev, "buffer overflow count = %i\n",
0248         arc_ps2->buf_overflow);
0249 
0250     return 0;
0251 }
0252 
0253 #ifdef CONFIG_OF
0254 static const struct of_device_id arc_ps2_match[] = {
0255     { .compatible = "snps,arc_ps2" },
0256     { },
0257 };
0258 MODULE_DEVICE_TABLE(of, arc_ps2_match);
0259 #endif
0260 
0261 static struct platform_driver arc_ps2_driver = {
0262     .driver = {
0263         .name       = "arc_ps2",
0264         .of_match_table = of_match_ptr(arc_ps2_match),
0265     },
0266     .probe  = arc_ps2_probe,
0267     .remove = arc_ps2_remove,
0268 };
0269 
0270 module_platform_driver(arc_ps2_driver);
0271 
0272 MODULE_LICENSE("GPL");
0273 MODULE_AUTHOR("Pavel Sokolov <psokolov@synopsys.com>");
0274 MODULE_DESCRIPTION("ARC PS/2 Driver");