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

altera_ps2.c (3673B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Altera University Program PS2 controller driver
      4 *
      5 * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
      6 *
      7 * Based on sa1111ps2.c, which is:
      8 * Copyright (C) 2002 Russell King
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/input.h>
     13#include <linux/serio.h>
     14#include <linux/interrupt.h>
     15#include <linux/platform_device.h>
     16#include <linux/io.h>
     17#include <linux/slab.h>
     18#include <linux/of.h>
     19
     20#define DRV_NAME "altera_ps2"
     21
     22struct ps2if {
     23	struct serio *io;
     24	void __iomem *base;
     25};
     26
     27/*
     28 * Read all bytes waiting in the PS2 port.  There should be
     29 * at the most one, but we loop for safety.
     30 */
     31static irqreturn_t altera_ps2_rxint(int irq, void *dev_id)
     32{
     33	struct ps2if *ps2if = dev_id;
     34	unsigned int status;
     35	irqreturn_t handled = IRQ_NONE;
     36
     37	while ((status = readl(ps2if->base)) & 0xffff0000) {
     38		serio_interrupt(ps2if->io, status & 0xff, 0);
     39		handled = IRQ_HANDLED;
     40	}
     41
     42	return handled;
     43}
     44
     45/*
     46 * Write a byte to the PS2 port.
     47 */
     48static int altera_ps2_write(struct serio *io, unsigned char val)
     49{
     50	struct ps2if *ps2if = io->port_data;
     51
     52	writel(val, ps2if->base);
     53	return 0;
     54}
     55
     56static int altera_ps2_open(struct serio *io)
     57{
     58	struct ps2if *ps2if = io->port_data;
     59
     60	/* clear fifo */
     61	while (readl(ps2if->base) & 0xffff0000)
     62		/* empty */;
     63
     64	writel(1, ps2if->base + 4); /* enable rx irq */
     65	return 0;
     66}
     67
     68static void altera_ps2_close(struct serio *io)
     69{
     70	struct ps2if *ps2if = io->port_data;
     71
     72	writel(0, ps2if->base + 4); /* disable rx irq */
     73}
     74
     75/*
     76 * Add one device to this driver.
     77 */
     78static int altera_ps2_probe(struct platform_device *pdev)
     79{
     80	struct ps2if *ps2if;
     81	struct resource *res;
     82	struct serio *serio;
     83	int error, irq;
     84
     85	ps2if = devm_kzalloc(&pdev->dev, sizeof(struct ps2if), GFP_KERNEL);
     86	if (!ps2if)
     87		return -ENOMEM;
     88
     89	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     90	ps2if->base = devm_ioremap_resource(&pdev->dev, res);
     91	if (IS_ERR(ps2if->base))
     92		return PTR_ERR(ps2if->base);
     93
     94	irq = platform_get_irq(pdev, 0);
     95	if (irq < 0)
     96		return -ENXIO;
     97
     98	error = devm_request_irq(&pdev->dev, irq, altera_ps2_rxint, 0,
     99				 pdev->name, ps2if);
    100	if (error) {
    101		dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
    102		return error;
    103	}
    104
    105	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
    106	if (!serio)
    107		return -ENOMEM;
    108
    109	serio->id.type		= SERIO_8042;
    110	serio->write		= altera_ps2_write;
    111	serio->open		= altera_ps2_open;
    112	serio->close		= altera_ps2_close;
    113	strlcpy(serio->name, dev_name(&pdev->dev), sizeof(serio->name));
    114	strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
    115	serio->port_data	= ps2if;
    116	serio->dev.parent	= &pdev->dev;
    117	ps2if->io		= serio;
    118
    119	dev_info(&pdev->dev, "base %p, irq %d\n", ps2if->base, irq);
    120
    121	serio_register_port(ps2if->io);
    122	platform_set_drvdata(pdev, ps2if);
    123
    124	return 0;
    125}
    126
    127/*
    128 * Remove one device from this driver.
    129 */
    130static int altera_ps2_remove(struct platform_device *pdev)
    131{
    132	struct ps2if *ps2if = platform_get_drvdata(pdev);
    133
    134	serio_unregister_port(ps2if->io);
    135
    136	return 0;
    137}
    138
    139#ifdef CONFIG_OF
    140static const struct of_device_id altera_ps2_match[] = {
    141	{ .compatible = "ALTR,ps2-1.0", },
    142	{ .compatible = "altr,ps2-1.0", },
    143	{},
    144};
    145MODULE_DEVICE_TABLE(of, altera_ps2_match);
    146#endif /* CONFIG_OF */
    147
    148/*
    149 * Our device driver structure
    150 */
    151static struct platform_driver altera_ps2_driver = {
    152	.probe		= altera_ps2_probe,
    153	.remove		= altera_ps2_remove,
    154	.driver	= {
    155		.name	= DRV_NAME,
    156		.of_match_table = of_match_ptr(altera_ps2_match),
    157	},
    158};
    159module_platform_driver(altera_ps2_driver);
    160
    161MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
    162MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
    163MODULE_LICENSE("GPL");
    164MODULE_ALIAS("platform:" DRV_NAME);