linux/drivers/input/serio/arc_ps2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   4 *
   5 * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com>
   6 */
   7
   8#include <linux/err.h>
   9#include <linux/module.h>
  10#include <linux/interrupt.h>
  11#include <linux/input.h>
  12#include <linux/serio.h>
  13#include <linux/platform_device.h>
  14#include <linux/of.h>
  15#include <linux/io.h>
  16#include <linux/kernel.h>
  17#include <linux/slab.h>
  18
  19#define ARC_PS2_PORTS                   2
  20
  21#define ARC_ARC_PS2_ID                  0x0001f609
  22
  23#define STAT_TIMEOUT                    128
  24
  25#define PS2_STAT_RX_FRM_ERR             (1)
  26#define PS2_STAT_RX_BUF_OVER            (1 << 1)
  27#define PS2_STAT_RX_INT_EN              (1 << 2)
  28#define PS2_STAT_RX_VAL                 (1 << 3)
  29#define PS2_STAT_TX_ISNOT_FUL           (1 << 4)
  30#define PS2_STAT_TX_INT_EN              (1 << 5)
  31
  32struct arc_ps2_port {
  33        void __iomem *data_addr;
  34        void __iomem *status_addr;
  35        struct serio *io;
  36};
  37
  38struct arc_ps2_data {
  39        struct arc_ps2_port port[ARC_PS2_PORTS];
  40        void __iomem *addr;
  41        unsigned int frame_error;
  42        unsigned int buf_overflow;
  43        unsigned int total_int;
  44};
  45
  46static void arc_ps2_check_rx(struct arc_ps2_data *arc_ps2,
  47                             struct arc_ps2_port *port)
  48{
  49        unsigned int timeout = 1000;
  50        unsigned int flag, status;
  51        unsigned char data;
  52
  53        do {
  54                status = ioread32(port->status_addr);
  55                if (!(status & PS2_STAT_RX_VAL))
  56                        return;
  57
  58                data = ioread32(port->data_addr) & 0xff;
  59
  60                flag = 0;
  61                arc_ps2->total_int++;
  62                if (status & PS2_STAT_RX_FRM_ERR) {
  63                        arc_ps2->frame_error++;
  64                        flag |= SERIO_PARITY;
  65                } else if (status & PS2_STAT_RX_BUF_OVER) {
  66                        arc_ps2->buf_overflow++;
  67                        flag |= SERIO_FRAME;
  68                }
  69
  70                serio_interrupt(port->io, data, flag);
  71        } while (--timeout);
  72
  73        dev_err(&port->io->dev, "PS/2 hardware stuck\n");
  74}
  75
  76static irqreturn_t arc_ps2_interrupt(int irq, void *dev)
  77{
  78        struct arc_ps2_data *arc_ps2 = dev;
  79        int i;
  80
  81        for (i = 0; i < ARC_PS2_PORTS; i++)
  82                arc_ps2_check_rx(arc_ps2, &arc_ps2->port[i]);
  83
  84        return IRQ_HANDLED;
  85}
  86
  87static int arc_ps2_write(struct serio *io, unsigned char val)
  88{
  89        unsigned status;
  90        struct arc_ps2_port *port = io->port_data;
  91        int timeout = STAT_TIMEOUT;
  92
  93        do {
  94                status = ioread32(port->status_addr);
  95                cpu_relax();
  96
  97                if (status & PS2_STAT_TX_ISNOT_FUL) {
  98                        iowrite32(val & 0xff, port->data_addr);
  99                        return 0;
 100                }
 101
 102        } while (--timeout);
 103
 104        dev_err(&io->dev, "write timeout\n");
 105        return -ETIMEDOUT;
 106}
 107
 108static int arc_ps2_open(struct serio *io)
 109{
 110        struct arc_ps2_port *port = io->port_data;
 111
 112        iowrite32(PS2_STAT_RX_INT_EN, port->status_addr);
 113
 114        return 0;
 115}
 116
 117static void arc_ps2_close(struct serio *io)
 118{
 119        struct arc_ps2_port *port = io->port_data;
 120
 121        iowrite32(ioread32(port->status_addr) & ~PS2_STAT_RX_INT_EN,
 122                  port->status_addr);
 123}
 124
 125static void __iomem *arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2,
 126                                                  int index, bool status)
 127{
 128        void __iomem *addr;
 129
 130        addr = arc_ps2->addr + 4 + 4 * index;
 131        if (status)
 132                addr += ARC_PS2_PORTS * 4;
 133
 134        return addr;
 135}
 136
 137static void arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2)
 138{
 139        void __iomem *addr;
 140        u32 val;
 141        int i;
 142
 143        for (i = 0; i < ARC_PS2_PORTS; i++) {
 144                addr = arc_ps2_calc_addr(arc_ps2, i, true);
 145                val = ioread32(addr);
 146                val &= ~(PS2_STAT_RX_INT_EN | PS2_STAT_TX_INT_EN);
 147                iowrite32(val, addr);
 148        }
 149}
 150
 151static int arc_ps2_create_port(struct platform_device *pdev,
 152                                         struct arc_ps2_data *arc_ps2,
 153                                         int index)
 154{
 155        struct arc_ps2_port *port = &arc_ps2->port[index];
 156        struct serio *io;
 157
 158        io = kzalloc(sizeof(struct serio), GFP_KERNEL);
 159        if (!io)
 160                return -ENOMEM;
 161
 162        io->id.type = SERIO_8042;
 163        io->write = arc_ps2_write;
 164        io->open = arc_ps2_open;
 165        io->close = arc_ps2_close;
 166        snprintf(io->name, sizeof(io->name), "ARC PS/2 port%d", index);
 167        snprintf(io->phys, sizeof(io->phys), "arc/serio%d", index);
 168        io->port_data = port;
 169
 170        port->io = io;
 171
 172        port->data_addr = arc_ps2_calc_addr(arc_ps2, index, false);
 173        port->status_addr = arc_ps2_calc_addr(arc_ps2, index, true);
 174
 175        dev_dbg(&pdev->dev, "port%d is allocated (data = 0x%p, status = 0x%p)\n",
 176                index, port->data_addr, port->status_addr);
 177
 178        serio_register_port(port->io);
 179        return 0;
 180}
 181
 182static int arc_ps2_probe(struct platform_device *pdev)
 183{
 184        struct arc_ps2_data *arc_ps2;
 185        struct resource *res;
 186        int irq;
 187        int error, id, i;
 188
 189        irq = platform_get_irq_byname(pdev, "arc_ps2_irq");
 190        if (irq < 0)
 191                return -EINVAL;
 192
 193        arc_ps2 = devm_kzalloc(&pdev->dev, sizeof(struct arc_ps2_data),
 194                                GFP_KERNEL);
 195        if (!arc_ps2) {
 196                dev_err(&pdev->dev, "out of memory\n");
 197                return -ENOMEM;
 198        }
 199
 200        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 201        arc_ps2->addr = devm_ioremap_resource(&pdev->dev, res);
 202        if (IS_ERR(arc_ps2->addr))
 203                return PTR_ERR(arc_ps2->addr);
 204
 205        dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n",
 206                 irq, arc_ps2->addr, ARC_PS2_PORTS);
 207
 208        id = ioread32(arc_ps2->addr);
 209        if (id != ARC_ARC_PS2_ID) {
 210                dev_err(&pdev->dev, "device id does not match\n");
 211                return -ENXIO;
 212        }
 213
 214        arc_ps2_inhibit_ports(arc_ps2);
 215
 216        error = devm_request_irq(&pdev->dev, irq, arc_ps2_interrupt,
 217                                 0, "arc_ps2", arc_ps2);
 218        if (error) {
 219                dev_err(&pdev->dev, "Could not allocate IRQ\n");
 220                return error;
 221        }
 222
 223        for (i = 0; i < ARC_PS2_PORTS; i++) {
 224                error = arc_ps2_create_port(pdev, arc_ps2, i);
 225                if (error) {
 226                        while (--i >= 0)
 227                                serio_unregister_port(arc_ps2->port[i].io);
 228                        return error;
 229                }
 230        }
 231
 232        platform_set_drvdata(pdev, arc_ps2);
 233
 234        return 0;
 235}
 236
 237static int arc_ps2_remove(struct platform_device *pdev)
 238{
 239        struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev);
 240        int i;
 241
 242        for (i = 0; i < ARC_PS2_PORTS; i++)
 243                serio_unregister_port(arc_ps2->port[i].io);
 244
 245        dev_dbg(&pdev->dev, "interrupt count = %i\n", arc_ps2->total_int);
 246        dev_dbg(&pdev->dev, "frame error count = %i\n", arc_ps2->frame_error);
 247        dev_dbg(&pdev->dev, "buffer overflow count = %i\n",
 248                arc_ps2->buf_overflow);
 249
 250        return 0;
 251}
 252
 253#ifdef CONFIG_OF
 254static const struct of_device_id arc_ps2_match[] = {
 255        { .compatible = "snps,arc_ps2" },
 256        { },
 257};
 258MODULE_DEVICE_TABLE(of, arc_ps2_match);
 259#endif
 260
 261static struct platform_driver arc_ps2_driver = {
 262        .driver = {
 263                .name           = "arc_ps2",
 264                .of_match_table = of_match_ptr(arc_ps2_match),
 265        },
 266        .probe  = arc_ps2_probe,
 267        .remove = arc_ps2_remove,
 268};
 269
 270module_platform_driver(arc_ps2_driver);
 271
 272MODULE_LICENSE("GPL");
 273MODULE_AUTHOR("Pavel Sokolov <psokolov@synopsys.com>");
 274MODULE_DESCRIPTION("ARC PS/2 Driver");
 275