LCOV - code coverage report
Current view: top level - drivers/input/serio - ambakmi.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 74 0.0 %
Date: 2014-02-18 Functions: 0 9 0.0 %
Branches: 0 20 0.0 %

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

Generated by: LCOV version 1.9