linux/drivers/input/keyboard/davinci_keyscan.c
<<
>>
Prefs
   1/*
   2 * DaVinci Key Scan Driver for TI platforms
   3 *
   4 * Copyright (C) 2009 Texas Instruments, Inc
   5 *
   6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
   7 *
   8 * Initial Code: Sandeep Paulraj <s-paulraj@ti.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23 */
  24#include <linux/module.h>
  25#include <linux/init.h>
  26#include <linux/interrupt.h>
  27#include <linux/types.h>
  28#include <linux/input.h>
  29#include <linux/kernel.h>
  30#include <linux/delay.h>
  31#include <linux/platform_device.h>
  32#include <linux/errno.h>
  33#include <linux/slab.h>
  34
  35#include <asm/irq.h>
  36
  37#include <mach/hardware.h>
  38#include <mach/irqs.h>
  39#include <linux/platform_data/keyscan-davinci.h>
  40
  41/* Key scan registers */
  42#define DAVINCI_KEYSCAN_KEYCTRL         0x0000
  43#define DAVINCI_KEYSCAN_INTENA          0x0004
  44#define DAVINCI_KEYSCAN_INTFLAG         0x0008
  45#define DAVINCI_KEYSCAN_INTCLR          0x000c
  46#define DAVINCI_KEYSCAN_STRBWIDTH       0x0010
  47#define DAVINCI_KEYSCAN_INTERVAL        0x0014
  48#define DAVINCI_KEYSCAN_CONTTIME        0x0018
  49#define DAVINCI_KEYSCAN_CURRENTST       0x001c
  50#define DAVINCI_KEYSCAN_PREVSTATE       0x0020
  51#define DAVINCI_KEYSCAN_EMUCTRL         0x0024
  52#define DAVINCI_KEYSCAN_IODFTCTRL       0x002c
  53
  54/* Key Control Register (KEYCTRL) */
  55#define DAVINCI_KEYSCAN_KEYEN           0x00000001
  56#define DAVINCI_KEYSCAN_PREVMODE        0x00000002
  57#define DAVINCI_KEYSCAN_CHATOFF         0x00000004
  58#define DAVINCI_KEYSCAN_AUTODET         0x00000008
  59#define DAVINCI_KEYSCAN_SCANMODE        0x00000010
  60#define DAVINCI_KEYSCAN_OUTTYPE         0x00000020
  61
  62/* Masks for the interrupts */
  63#define DAVINCI_KEYSCAN_INT_CONT        0x00000008
  64#define DAVINCI_KEYSCAN_INT_OFF         0x00000004
  65#define DAVINCI_KEYSCAN_INT_ON          0x00000002
  66#define DAVINCI_KEYSCAN_INT_CHANGE      0x00000001
  67#define DAVINCI_KEYSCAN_INT_ALL         0x0000000f
  68
  69struct davinci_ks {
  70        struct input_dev                *input;
  71        struct davinci_ks_platform_data *pdata;
  72        int                             irq;
  73        void __iomem                    *base;
  74        resource_size_t                 pbase;
  75        size_t                          base_size;
  76        unsigned short                  keymap[];
  77};
  78
  79/* Initializing the kp Module */
  80static int __init davinci_ks_initialize(struct davinci_ks *davinci_ks)
  81{
  82        struct device *dev = &davinci_ks->input->dev;
  83        struct davinci_ks_platform_data *pdata = davinci_ks->pdata;
  84        u32 matrix_ctrl;
  85
  86        /* Enable all interrupts */
  87        __raw_writel(DAVINCI_KEYSCAN_INT_ALL,
  88                     davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
  89
  90        /* Clear interrupts if any */
  91        __raw_writel(DAVINCI_KEYSCAN_INT_ALL,
  92                     davinci_ks->base + DAVINCI_KEYSCAN_INTCLR);
  93
  94        /* Setup the scan period = strobe + interval */
  95        __raw_writel(pdata->strobe,
  96                     davinci_ks->base + DAVINCI_KEYSCAN_STRBWIDTH);
  97        __raw_writel(pdata->interval,
  98                     davinci_ks->base + DAVINCI_KEYSCAN_INTERVAL);
  99        __raw_writel(0x01,
 100                     davinci_ks->base + DAVINCI_KEYSCAN_CONTTIME);
 101
 102        /* Define matrix type */
 103        switch (pdata->matrix_type) {
 104        case DAVINCI_KEYSCAN_MATRIX_4X4:
 105                matrix_ctrl = 0;
 106                break;
 107        case DAVINCI_KEYSCAN_MATRIX_5X3:
 108                matrix_ctrl = (1 << 6);
 109                break;
 110        default:
 111                dev_err(dev->parent, "wrong matrix type\n");
 112                return -EINVAL;
 113        }
 114
 115        /* Enable key scan module and set matrix type */
 116        __raw_writel(DAVINCI_KEYSCAN_AUTODET | DAVINCI_KEYSCAN_KEYEN |
 117                     matrix_ctrl, davinci_ks->base + DAVINCI_KEYSCAN_KEYCTRL);
 118
 119        return 0;
 120}
 121
 122static irqreturn_t davinci_ks_interrupt(int irq, void *dev_id)
 123{
 124        struct davinci_ks *davinci_ks = dev_id;
 125        struct device *dev = &davinci_ks->input->dev;
 126        unsigned short *keymap = davinci_ks->keymap;
 127        int keymapsize = davinci_ks->pdata->keymapsize;
 128        u32 prev_status, new_status, changed;
 129        bool release;
 130        int keycode = KEY_UNKNOWN;
 131        int i;
 132
 133        /* Disable interrupt */
 134        __raw_writel(0x0, davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
 135
 136        /* Reading previous and new status of the key scan */
 137        prev_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_PREVSTATE);
 138        new_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_CURRENTST);
 139
 140        changed = prev_status ^ new_status;
 141
 142        if (changed) {
 143                /*
 144                 * It goes through all bits in 'changed' to ensure
 145                 * that no key changes are being missed
 146                 */
 147                for (i = 0 ; i < keymapsize; i++) {
 148                        if ((changed>>i) & 0x1) {
 149                                keycode = keymap[i];
 150                                release = (new_status >> i) & 0x1;
 151                                dev_dbg(dev->parent, "key %d %s\n", keycode,
 152                                        release ? "released" : "pressed");
 153                                input_report_key(davinci_ks->input, keycode,
 154                                                 !release);
 155                                input_sync(davinci_ks->input);
 156                        }
 157                }
 158                /* Clearing interrupt */
 159                __raw_writel(DAVINCI_KEYSCAN_INT_ALL,
 160                             davinci_ks->base + DAVINCI_KEYSCAN_INTCLR);
 161        }
 162
 163        /* Enable interrupts */
 164        __raw_writel(0x1, davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
 165
 166        return IRQ_HANDLED;
 167}
 168
 169static int __init davinci_ks_probe(struct platform_device *pdev)
 170{
 171        struct davinci_ks *davinci_ks;
 172        struct input_dev *key_dev;
 173        struct resource *res, *mem;
 174        struct device *dev = &pdev->dev;
 175        struct davinci_ks_platform_data *pdata = dev_get_platdata(&pdev->dev);
 176        int error, i;
 177
 178        if (pdata->device_enable) {
 179                error = pdata->device_enable(dev);
 180                if (error < 0) {
 181                        dev_dbg(dev, "device enable function failed\n");
 182                        return error;
 183                }
 184        }
 185
 186        if (!pdata->keymap) {
 187                dev_dbg(dev, "no keymap from pdata\n");
 188                return -EINVAL;
 189        }
 190
 191        davinci_ks = kzalloc(sizeof(struct davinci_ks) +
 192                sizeof(unsigned short) * pdata->keymapsize, GFP_KERNEL);
 193        if (!davinci_ks) {
 194                dev_dbg(dev, "could not allocate memory for private data\n");
 195                return -ENOMEM;
 196        }
 197
 198        memcpy(davinci_ks->keymap, pdata->keymap,
 199                sizeof(unsigned short) * pdata->keymapsize);
 200
 201        key_dev = input_allocate_device();
 202        if (!key_dev) {
 203                dev_dbg(dev, "could not allocate input device\n");
 204                error = -ENOMEM;
 205                goto fail1;
 206        }
 207
 208        davinci_ks->input = key_dev;
 209
 210        davinci_ks->irq = platform_get_irq(pdev, 0);
 211        if (davinci_ks->irq < 0) {
 212                dev_err(dev, "no key scan irq\n");
 213                error = davinci_ks->irq;
 214                goto fail2;
 215        }
 216
 217        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 218        if (!res) {
 219                dev_err(dev, "no mem resource\n");
 220                error = -EINVAL;
 221                goto fail2;
 222        }
 223
 224        davinci_ks->pbase = res->start;
 225        davinci_ks->base_size = resource_size(res);
 226
 227        mem = request_mem_region(davinci_ks->pbase, davinci_ks->base_size,
 228                                 pdev->name);
 229        if (!mem) {
 230                dev_err(dev, "key scan registers at %08x are not free\n",
 231                        davinci_ks->pbase);
 232                error = -EBUSY;
 233                goto fail2;
 234        }
 235
 236        davinci_ks->base = ioremap(davinci_ks->pbase, davinci_ks->base_size);
 237        if (!davinci_ks->base) {
 238                dev_err(dev, "can't ioremap MEM resource.\n");
 239                error = -ENOMEM;
 240                goto fail3;
 241        }
 242
 243        /* Enable auto repeat feature of Linux input subsystem */
 244        if (pdata->rep)
 245                __set_bit(EV_REP, key_dev->evbit);
 246
 247        /* Setup input device */
 248        __set_bit(EV_KEY, key_dev->evbit);
 249
 250        /* Setup the platform data */
 251        davinci_ks->pdata = pdata;
 252
 253        for (i = 0; i < davinci_ks->pdata->keymapsize; i++)
 254                __set_bit(davinci_ks->pdata->keymap[i], key_dev->keybit);
 255
 256        key_dev->name = "davinci_keyscan";
 257        key_dev->phys = "davinci_keyscan/input0";
 258        key_dev->dev.parent = &pdev->dev;
 259        key_dev->id.bustype = BUS_HOST;
 260        key_dev->id.vendor = 0x0001;
 261        key_dev->id.product = 0x0001;
 262        key_dev->id.version = 0x0001;
 263        key_dev->keycode = davinci_ks->keymap;
 264        key_dev->keycodesize = sizeof(davinci_ks->keymap[0]);
 265        key_dev->keycodemax = davinci_ks->pdata->keymapsize;
 266
 267        error = input_register_device(davinci_ks->input);
 268        if (error < 0) {
 269                dev_err(dev, "unable to register davinci key scan device\n");
 270                goto fail4;
 271        }
 272
 273        error = request_irq(davinci_ks->irq, davinci_ks_interrupt,
 274                          0, pdev->name, davinci_ks);
 275        if (error < 0) {
 276                dev_err(dev, "unable to register davinci key scan interrupt\n");
 277                goto fail5;
 278        }
 279
 280        error = davinci_ks_initialize(davinci_ks);
 281        if (error < 0) {
 282                dev_err(dev, "unable to initialize davinci key scan device\n");
 283                goto fail6;
 284        }
 285
 286        platform_set_drvdata(pdev, davinci_ks);
 287        return 0;
 288
 289fail6:
 290        free_irq(davinci_ks->irq, davinci_ks);
 291fail5:
 292        input_unregister_device(davinci_ks->input);
 293        key_dev = NULL;
 294fail4:
 295        iounmap(davinci_ks->base);
 296fail3:
 297        release_mem_region(davinci_ks->pbase, davinci_ks->base_size);
 298fail2:
 299        input_free_device(key_dev);
 300fail1:
 301        kfree(davinci_ks);
 302
 303        return error;
 304}
 305
 306static int davinci_ks_remove(struct platform_device *pdev)
 307{
 308        struct davinci_ks *davinci_ks = platform_get_drvdata(pdev);
 309
 310        free_irq(davinci_ks->irq, davinci_ks);
 311
 312        input_unregister_device(davinci_ks->input);
 313
 314        iounmap(davinci_ks->base);
 315        release_mem_region(davinci_ks->pbase, davinci_ks->base_size);
 316
 317        kfree(davinci_ks);
 318
 319        return 0;
 320}
 321
 322static struct platform_driver davinci_ks_driver = {
 323        .driver = {
 324                .name = "davinci_keyscan",
 325        },
 326        .remove = davinci_ks_remove,
 327};
 328
 329module_platform_driver_probe(davinci_ks_driver, davinci_ks_probe);
 330
 331MODULE_AUTHOR("Miguel Aguilar");
 332MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");
 333MODULE_LICENSE("GPL");
 334