linux/drivers/input/serio/apbps2.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 Aeroflex Gaisler
   3 *
   4 * This driver supports the APBPS2 PS/2 core available in the GRLIB
   5 * VHDL IP core library.
   6 *
   7 * Full documentation of the APBPS2 core can be found here:
   8 * http://www.gaisler.com/products/grlib/grip.pdf
   9 *
  10 * See "Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt" for
  11 * information on open firmware properties.
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * Contributors: Daniel Hellstrom <daniel@gaisler.com>
  19 */
  20#include <linux/platform_device.h>
  21#include <linux/of_device.h>
  22#include <linux/module.h>
  23#include <linux/serio.h>
  24#include <linux/errno.h>
  25#include <linux/interrupt.h>
  26#include <linux/of_irq.h>
  27#include <linux/device.h>
  28#include <linux/delay.h>
  29#include <linux/err.h>
  30#include <linux/slab.h>
  31#include <linux/string.h>
  32#include <linux/kernel.h>
  33#include <linux/io.h>
  34
  35struct apbps2_regs {
  36        u32 __iomem data;       /* 0x00 */
  37        u32 __iomem status;     /* 0x04 */
  38        u32 __iomem ctrl;       /* 0x08 */
  39        u32 __iomem reload;     /* 0x0c */
  40};
  41
  42#define APBPS2_STATUS_DR        (1<<0)
  43#define APBPS2_STATUS_PE        (1<<1)
  44#define APBPS2_STATUS_FE        (1<<2)
  45#define APBPS2_STATUS_KI        (1<<3)
  46#define APBPS2_STATUS_RF        (1<<4)
  47#define APBPS2_STATUS_TF        (1<<5)
  48#define APBPS2_STATUS_TCNT      (0x1f<<22)
  49#define APBPS2_STATUS_RCNT      (0x1f<<27)
  50
  51#define APBPS2_CTRL_RE          (1<<0)
  52#define APBPS2_CTRL_TE          (1<<1)
  53#define APBPS2_CTRL_RI          (1<<2)
  54#define APBPS2_CTRL_TI          (1<<3)
  55
  56struct apbps2_priv {
  57        struct serio            *io;
  58        struct apbps2_regs      *regs;
  59};
  60
  61static int apbps2_idx;
  62
  63static irqreturn_t apbps2_isr(int irq, void *dev_id)
  64{
  65        struct apbps2_priv *priv = dev_id;
  66        unsigned long status, data, rxflags;
  67        irqreturn_t ret = IRQ_NONE;
  68
  69        while ((status = ioread32be(&priv->regs->status)) & APBPS2_STATUS_DR) {
  70                data = ioread32be(&priv->regs->data);
  71                rxflags = (status & APBPS2_STATUS_PE) ? SERIO_PARITY : 0;
  72                rxflags |= (status & APBPS2_STATUS_FE) ? SERIO_FRAME : 0;
  73
  74                /* clear error bits? */
  75                if (rxflags)
  76                        iowrite32be(0, &priv->regs->status);
  77
  78                serio_interrupt(priv->io, data, rxflags);
  79
  80                ret = IRQ_HANDLED;
  81        }
  82
  83        return ret;
  84}
  85
  86static int apbps2_write(struct serio *io, unsigned char val)
  87{
  88        struct apbps2_priv *priv = io->port_data;
  89        unsigned int tleft = 10000; /* timeout in 100ms */
  90
  91        /* delay until PS/2 controller has room for more chars */
  92        while ((ioread32be(&priv->regs->status) & APBPS2_STATUS_TF) && tleft--)
  93                udelay(10);
  94
  95        if ((ioread32be(&priv->regs->status) & APBPS2_STATUS_TF) == 0) {
  96                iowrite32be(val, &priv->regs->data);
  97
  98                iowrite32be(APBPS2_CTRL_RE | APBPS2_CTRL_RI | APBPS2_CTRL_TE,
  99                                &priv->regs->ctrl);
 100                return 0;
 101        }
 102
 103        return -ETIMEDOUT;
 104}
 105
 106static int apbps2_open(struct serio *io)
 107{
 108        struct apbps2_priv *priv = io->port_data;
 109        int limit;
 110        unsigned long tmp;
 111
 112        /* clear error flags */
 113        iowrite32be(0, &priv->regs->status);
 114
 115        /* Clear old data if available (unlikely) */
 116        limit = 1024;
 117        while ((ioread32be(&priv->regs->status) & APBPS2_STATUS_DR) && --limit)
 118                tmp = ioread32be(&priv->regs->data);
 119
 120        /* Enable reciever and it's interrupt */
 121        iowrite32be(APBPS2_CTRL_RE | APBPS2_CTRL_RI, &priv->regs->ctrl);
 122
 123        return 0;
 124}
 125
 126static void apbps2_close(struct serio *io)
 127{
 128        struct apbps2_priv *priv = io->port_data;
 129
 130        /* stop interrupts at PS/2 HW level */
 131        iowrite32be(0, &priv->regs->ctrl);
 132}
 133
 134/* Initialize one APBPS2 PS/2 core */
 135static int apbps2_of_probe(struct platform_device *ofdev)
 136{
 137        struct apbps2_priv *priv;
 138        int irq, err;
 139        u32 freq_hz;
 140        struct resource *res;
 141
 142        priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL);
 143        if (!priv) {
 144                dev_err(&ofdev->dev, "memory allocation failed\n");
 145                return -ENOMEM;
 146        }
 147
 148        /* Find Device Address */
 149        res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
 150        priv->regs = devm_ioremap_resource(&ofdev->dev, res);
 151        if (IS_ERR(priv->regs))
 152                return PTR_ERR(priv->regs);
 153
 154        /* Reset hardware, disable interrupt */
 155        iowrite32be(0, &priv->regs->ctrl);
 156
 157        /* IRQ */
 158        irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
 159        err = devm_request_irq(&ofdev->dev, irq, apbps2_isr,
 160                                IRQF_SHARED, "apbps2", priv);
 161        if (err) {
 162                dev_err(&ofdev->dev, "request IRQ%d failed\n", irq);
 163                return err;
 164        }
 165
 166        /* Get core frequency */
 167        if (of_property_read_u32(ofdev->dev.of_node, "freq", &freq_hz)) {
 168                dev_err(&ofdev->dev, "unable to get core frequency\n");
 169                return -EINVAL;
 170        }
 171
 172        /* Set reload register to core freq in kHz/10 */
 173        iowrite32be(freq_hz / 10000, &priv->regs->reload);
 174
 175        priv->io = kzalloc(sizeof(struct serio), GFP_KERNEL);
 176        if (!priv->io)
 177                return -ENOMEM;
 178
 179        priv->io->id.type = SERIO_8042;
 180        priv->io->open = apbps2_open;
 181        priv->io->close = apbps2_close;
 182        priv->io->write = apbps2_write;
 183        priv->io->port_data = priv;
 184        strlcpy(priv->io->name, "APBPS2 PS/2", sizeof(priv->io->name));
 185        snprintf(priv->io->phys, sizeof(priv->io->phys),
 186                 "apbps2_%d", apbps2_idx++);
 187
 188        dev_info(&ofdev->dev, "irq = %d, base = 0x%p\n", irq, priv->regs);
 189
 190        serio_register_port(priv->io);
 191
 192        platform_set_drvdata(ofdev, priv);
 193
 194        return 0;
 195}
 196
 197static int apbps2_of_remove(struct platform_device *of_dev)
 198{
 199        struct apbps2_priv *priv = platform_get_drvdata(of_dev);
 200
 201        serio_unregister_port(priv->io);
 202
 203        return 0;
 204}
 205
 206static const struct of_device_id apbps2_of_match[] = {
 207        { .name = "GAISLER_APBPS2", },
 208        { .name = "01_060", },
 209        {}
 210};
 211
 212MODULE_DEVICE_TABLE(of, apbps2_of_match);
 213
 214static struct platform_driver apbps2_of_driver = {
 215        .driver = {
 216                .name = "grlib-apbps2",
 217                .of_match_table = apbps2_of_match,
 218        },
 219        .probe = apbps2_of_probe,
 220        .remove = apbps2_of_remove,
 221};
 222
 223module_platform_driver(apbps2_of_driver);
 224
 225MODULE_AUTHOR("Aeroflex Gaisler AB.");
 226MODULE_DESCRIPTION("GRLIB APBPS2 PS/2 serial I/O");
 227MODULE_LICENSE("GPL");
 228