root/drivers/input/serio/ambakmi.c

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

DEFINITIONS

This source file includes following definitions.
  1. amba_kmi_int
  2. amba_kmi_write
  3. amba_kmi_open
  4. amba_kmi_close
  5. amba_kmi_probe
  6. amba_kmi_remove
  7. amba_kmi_resume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  linux/drivers/input/serio/ambakmi.c
   4  *
   5  *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd.
   6  *  Copyright (C) 2002 Russell King.
   7  */
   8 #include <linux/module.h>
   9 #include <linux/serio.h>
  10 #include <linux/errno.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/ioport.h>
  13 #include <linux/device.h>
  14 #include <linux/delay.h>
  15 #include <linux/slab.h>
  16 #include <linux/err.h>
  17 #include <linux/amba/bus.h>
  18 #include <linux/amba/kmi.h>
  19 #include <linux/clk.h>
  20 
  21 #include <asm/io.h>
  22 #include <asm/irq.h>
  23 
  24 #define KMI_BASE        (kmi->base)
  25 
  26 struct amba_kmi_port {
  27         struct serio            *io;
  28         struct clk              *clk;
  29         void __iomem            *base;
  30         unsigned int            irq;
  31         unsigned int            divisor;
  32         unsigned int            open;
  33 };
  34 
  35 static irqreturn_t amba_kmi_int(int irq, void *dev_id)
  36 {
  37         struct amba_kmi_port *kmi = dev_id;
  38         unsigned int status = readb(KMIIR);
  39         int handled = IRQ_NONE;
  40 
  41         while (status & KMIIR_RXINTR) {
  42                 serio_interrupt(kmi->io, readb(KMIDATA), 0);
  43                 status = readb(KMIIR);
  44                 handled = IRQ_HANDLED;
  45         }
  46 
  47         return handled;
  48 }
  49 
  50 static int amba_kmi_write(struct serio *io, unsigned char val)
  51 {
  52         struct amba_kmi_port *kmi = io->port_data;
  53         unsigned int timeleft = 10000; /* timeout in 100ms */
  54 
  55         while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft)
  56                 udelay(10);
  57 
  58         if (timeleft)
  59                 writeb(val, KMIDATA);
  60 
  61         return timeleft ? 0 : SERIO_TIMEOUT;
  62 }
  63 
  64 static int amba_kmi_open(struct serio *io)
  65 {
  66         struct amba_kmi_port *kmi = io->port_data;
  67         unsigned int divisor;
  68         int ret;
  69 
  70         ret = clk_prepare_enable(kmi->clk);
  71         if (ret)
  72                 goto out;
  73 
  74         divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
  75         writeb(divisor, KMICLKDIV);
  76         writeb(KMICR_EN, KMICR);
  77 
  78         ret = request_irq(kmi->irq, amba_kmi_int, IRQF_SHARED, "kmi-pl050",
  79                           kmi);
  80         if (ret) {
  81                 printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
  82                 writeb(0, KMICR);
  83                 goto clk_disable;
  84         }
  85 
  86         writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
  87 
  88         return 0;
  89 
  90  clk_disable:
  91         clk_disable_unprepare(kmi->clk);
  92  out:
  93         return ret;
  94 }
  95 
  96 static void amba_kmi_close(struct serio *io)
  97 {
  98         struct amba_kmi_port *kmi = io->port_data;
  99 
 100         writeb(0, KMICR);
 101 
 102         free_irq(kmi->irq, kmi);
 103         clk_disable_unprepare(kmi->clk);
 104 }
 105 
 106 static int amba_kmi_probe(struct amba_device *dev,
 107         const struct amba_id *id)
 108 {
 109         struct amba_kmi_port *kmi;
 110         struct serio *io;
 111         int ret;
 112 
 113         ret = amba_request_regions(dev, NULL);
 114         if (ret)
 115                 return ret;
 116 
 117         kmi = kzalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
 118         io = kzalloc(sizeof(struct serio), GFP_KERNEL);
 119         if (!kmi || !io) {
 120                 ret = -ENOMEM;
 121                 goto out;
 122         }
 123 
 124 
 125         io->id.type     = SERIO_8042;
 126         io->write       = amba_kmi_write;
 127         io->open        = amba_kmi_open;
 128         io->close       = amba_kmi_close;
 129         strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name));
 130         strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys));
 131         io->port_data   = kmi;
 132         io->dev.parent  = &dev->dev;
 133 
 134         kmi->io         = io;
 135         kmi->base       = ioremap(dev->res.start, resource_size(&dev->res));
 136         if (!kmi->base) {
 137                 ret = -ENOMEM;
 138                 goto out;
 139         }
 140 
 141         kmi->clk = clk_get(&dev->dev, "KMIREFCLK");
 142         if (IS_ERR(kmi->clk)) {
 143                 ret = PTR_ERR(kmi->clk);
 144                 goto unmap;
 145         }
 146 
 147         kmi->irq = dev->irq[0];
 148         amba_set_drvdata(dev, kmi);
 149 
 150         serio_register_port(kmi->io);
 151         return 0;
 152 
 153  unmap:
 154         iounmap(kmi->base);
 155  out:
 156         kfree(kmi);
 157         kfree(io);
 158         amba_release_regions(dev);
 159         return ret;
 160 }
 161 
 162 static int amba_kmi_remove(struct amba_device *dev)
 163 {
 164         struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 165 
 166         serio_unregister_port(kmi->io);
 167         clk_put(kmi->clk);
 168         iounmap(kmi->base);
 169         kfree(kmi);
 170         amba_release_regions(dev);
 171         return 0;
 172 }
 173 
 174 static int __maybe_unused amba_kmi_resume(struct device *dev)
 175 {
 176         struct amba_kmi_port *kmi = dev_get_drvdata(dev);
 177 
 178         /* kick the serio layer to rescan this port */
 179         serio_reconnect(kmi->io);
 180 
 181         return 0;
 182 }
 183 
 184 static SIMPLE_DEV_PM_OPS(amba_kmi_dev_pm_ops, NULL, amba_kmi_resume);
 185 
 186 static const struct amba_id amba_kmi_idtable[] = {
 187         {
 188                 .id     = 0x00041050,
 189                 .mask   = 0x000fffff,
 190         },
 191         { 0, 0 }
 192 };
 193 
 194 MODULE_DEVICE_TABLE(amba, amba_kmi_idtable);
 195 
 196 static struct amba_driver ambakmi_driver = {
 197         .drv            = {
 198                 .name   = "kmi-pl050",
 199                 .owner  = THIS_MODULE,
 200                 .pm     = &amba_kmi_dev_pm_ops,
 201         },
 202         .id_table       = amba_kmi_idtable,
 203         .probe          = amba_kmi_probe,
 204         .remove         = amba_kmi_remove,
 205 };
 206 
 207 module_amba_driver(ambakmi_driver);
 208 
 209 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 210 MODULE_DESCRIPTION("AMBA KMI controller driver");
 211 MODULE_LICENSE("GPL");

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