root/drivers/input/serio/altera_ps2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. altera_ps2_rxint
  2. altera_ps2_write
  3. altera_ps2_open
  4. altera_ps2_close
  5. altera_ps2_probe
  6. altera_ps2_remove

   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 
  22 struct 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  */
  31 static 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  */
  48 static 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 
  56 static 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 
  68 static 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  */
  78 static 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  */
 130 static 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
 140 static const struct of_device_id altera_ps2_match[] = {
 141         { .compatible = "ALTR,ps2-1.0", },
 142         { .compatible = "altr,ps2-1.0", },
 143         {},
 144 };
 145 MODULE_DEVICE_TABLE(of, altera_ps2_match);
 146 #endif /* CONFIG_OF */
 147 
 148 /*
 149  * Our device driver structure
 150  */
 151 static 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 };
 159 module_platform_driver(altera_ps2_driver);
 160 
 161 MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
 162 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
 163 MODULE_LICENSE("GPL");
 164 MODULE_ALIAS("platform:" DRV_NAME);

/* [<][>][^][v][top][bottom][index][help] */