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