cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

apbps2.c (5563B)


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