linux/drivers/input/keyboard/ep93xx_keypad.c
<<
>>
Prefs
   1/*
   2 * Driver for the Cirrus EP93xx matrix keypad controller.
   3 *
   4 * Copyright (c) 2008 H Hartley Sweeten <hsweeten@visionengravers.com>
   5 *
   6 * Based on the pxa27x matrix keypad controller by Rodolfo Giometti.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 * NOTE:
  13 *
  14 * The 3-key reset is triggered by pressing the 3 keys in
  15 * Row 0, Columns 2, 4, and 7 at the same time.  This action can
  16 * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag.
  17 *
  18 * Normal operation for the matrix does not autorepeat the key press.
  19 * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT
  20 * flag.
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/platform_device.h>
  25#include <linux/interrupt.h>
  26#include <linux/clk.h>
  27#include <linux/io.h>
  28#include <linux/input/matrix_keypad.h>
  29#include <linux/slab.h>
  30
  31#include <mach/hardware.h>
  32#include <linux/platform_data/keypad-ep93xx.h>
  33
  34/*
  35 * Keypad Interface Register offsets
  36 */
  37#define KEY_INIT                0x00    /* Key Scan Initialization register */
  38#define KEY_DIAG                0x04    /* Key Scan Diagnostic register */
  39#define KEY_REG                 0x08    /* Key Value Capture register */
  40
  41/* Key Scan Initialization Register bit defines */
  42#define KEY_INIT_DBNC_MASK      (0x00ff0000)
  43#define KEY_INIT_DBNC_SHIFT     (16)
  44#define KEY_INIT_DIS3KY         (1<<15)
  45#define KEY_INIT_DIAG           (1<<14)
  46#define KEY_INIT_BACK           (1<<13)
  47#define KEY_INIT_T2             (1<<12)
  48#define KEY_INIT_PRSCL_MASK     (0x000003ff)
  49#define KEY_INIT_PRSCL_SHIFT    (0)
  50
  51/* Key Scan Diagnostic Register bit defines */
  52#define KEY_DIAG_MASK           (0x0000003f)
  53#define KEY_DIAG_SHIFT          (0)
  54
  55/* Key Value Capture Register bit defines */
  56#define KEY_REG_K               (1<<15)
  57#define KEY_REG_INT             (1<<14)
  58#define KEY_REG_2KEYS           (1<<13)
  59#define KEY_REG_1KEY            (1<<12)
  60#define KEY_REG_KEY2_MASK       (0x00000fc0)
  61#define KEY_REG_KEY2_SHIFT      (6)
  62#define KEY_REG_KEY1_MASK       (0x0000003f)
  63#define KEY_REG_KEY1_SHIFT      (0)
  64
  65#define EP93XX_MATRIX_SIZE      (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
  66
  67struct ep93xx_keypad {
  68        struct ep93xx_keypad_platform_data *pdata;
  69        struct input_dev *input_dev;
  70        struct clk *clk;
  71
  72        void __iomem *mmio_base;
  73
  74        unsigned short keycodes[EP93XX_MATRIX_SIZE];
  75
  76        int key1;
  77        int key2;
  78
  79        int irq;
  80
  81        bool enabled;
  82};
  83
  84static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
  85{
  86        struct ep93xx_keypad *keypad = dev_id;
  87        struct input_dev *input_dev = keypad->input_dev;
  88        unsigned int status;
  89        int keycode, key1, key2;
  90
  91        status = __raw_readl(keypad->mmio_base + KEY_REG);
  92
  93        keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
  94        key1 = keypad->keycodes[keycode];
  95
  96        keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
  97        key2 = keypad->keycodes[keycode];
  98
  99        if (status & KEY_REG_2KEYS) {
 100                if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
 101                        input_report_key(input_dev, keypad->key1, 0);
 102
 103                if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2)
 104                        input_report_key(input_dev, keypad->key2, 0);
 105
 106                input_report_key(input_dev, key1, 1);
 107                input_report_key(input_dev, key2, 1);
 108
 109                keypad->key1 = key1;
 110                keypad->key2 = key2;
 111
 112        } else if (status & KEY_REG_1KEY) {
 113                if (keypad->key1 && key1 != keypad->key1)
 114                        input_report_key(input_dev, keypad->key1, 0);
 115
 116                if (keypad->key2 && key1 != keypad->key2)
 117                        input_report_key(input_dev, keypad->key2, 0);
 118
 119                input_report_key(input_dev, key1, 1);
 120
 121                keypad->key1 = key1;
 122                keypad->key2 = 0;
 123
 124        } else {
 125                input_report_key(input_dev, keypad->key1, 0);
 126                input_report_key(input_dev, keypad->key2, 0);
 127
 128                keypad->key1 = keypad->key2 = 0;
 129        }
 130        input_sync(input_dev);
 131
 132        return IRQ_HANDLED;
 133}
 134
 135static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
 136{
 137        struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
 138        unsigned int val = 0;
 139
 140        if (pdata->flags & EP93XX_KEYPAD_KDIV)
 141                clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4);
 142        else
 143                clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16);
 144
 145        if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
 146                val |= KEY_INIT_DIS3KY;
 147        if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE)
 148                val |= KEY_INIT_DIAG;
 149        if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE)
 150                val |= KEY_INIT_BACK;
 151        if (pdata->flags & EP93XX_KEYPAD_TEST_MODE)
 152                val |= KEY_INIT_T2;
 153
 154        val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK);
 155
 156        val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
 157
 158        __raw_writel(val, keypad->mmio_base + KEY_INIT);
 159}
 160
 161static int ep93xx_keypad_open(struct input_dev *pdev)
 162{
 163        struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
 164
 165        if (!keypad->enabled) {
 166                ep93xx_keypad_config(keypad);
 167                clk_enable(keypad->clk);
 168                keypad->enabled = true;
 169        }
 170
 171        return 0;
 172}
 173
 174static void ep93xx_keypad_close(struct input_dev *pdev)
 175{
 176        struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
 177
 178        if (keypad->enabled) {
 179                clk_disable(keypad->clk);
 180                keypad->enabled = false;
 181        }
 182}
 183
 184
 185#ifdef CONFIG_PM_SLEEP
 186static int ep93xx_keypad_suspend(struct device *dev)
 187{
 188        struct platform_device *pdev = to_platform_device(dev);
 189        struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 190        struct input_dev *input_dev = keypad->input_dev;
 191
 192        mutex_lock(&input_dev->mutex);
 193
 194        if (keypad->enabled) {
 195                clk_disable(keypad->clk);
 196                keypad->enabled = false;
 197        }
 198
 199        mutex_unlock(&input_dev->mutex);
 200
 201        if (device_may_wakeup(&pdev->dev))
 202                enable_irq_wake(keypad->irq);
 203
 204        return 0;
 205}
 206
 207static int ep93xx_keypad_resume(struct device *dev)
 208{
 209        struct platform_device *pdev = to_platform_device(dev);
 210        struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 211        struct input_dev *input_dev = keypad->input_dev;
 212
 213        if (device_may_wakeup(&pdev->dev))
 214                disable_irq_wake(keypad->irq);
 215
 216        mutex_lock(&input_dev->mutex);
 217
 218        if (input_dev->users) {
 219                if (!keypad->enabled) {
 220                        ep93xx_keypad_config(keypad);
 221                        clk_enable(keypad->clk);
 222                        keypad->enabled = true;
 223                }
 224        }
 225
 226        mutex_unlock(&input_dev->mutex);
 227
 228        return 0;
 229}
 230#endif
 231
 232static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
 233                         ep93xx_keypad_suspend, ep93xx_keypad_resume);
 234
 235static int ep93xx_keypad_probe(struct platform_device *pdev)
 236{
 237        struct ep93xx_keypad *keypad;
 238        const struct matrix_keymap_data *keymap_data;
 239        struct input_dev *input_dev;
 240        struct resource *res;
 241        int err;
 242
 243        keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL);
 244        if (!keypad)
 245                return -ENOMEM;
 246
 247        keypad->pdata = dev_get_platdata(&pdev->dev);
 248        if (!keypad->pdata) {
 249                err = -EINVAL;
 250                goto failed_free;
 251        }
 252
 253        keymap_data = keypad->pdata->keymap_data;
 254        if (!keymap_data) {
 255                err = -EINVAL;
 256                goto failed_free;
 257        }
 258
 259        keypad->irq = platform_get_irq(pdev, 0);
 260        if (!keypad->irq) {
 261                err = -ENXIO;
 262                goto failed_free;
 263        }
 264
 265        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 266        if (!res) {
 267                err = -ENXIO;
 268                goto failed_free;
 269        }
 270
 271        res = request_mem_region(res->start, resource_size(res), pdev->name);
 272        if (!res) {
 273                err = -EBUSY;
 274                goto failed_free;
 275        }
 276
 277        keypad->mmio_base = ioremap(res->start, resource_size(res));
 278        if (keypad->mmio_base == NULL) {
 279                err = -ENXIO;
 280                goto failed_free_mem;
 281        }
 282
 283        err = ep93xx_keypad_acquire_gpio(pdev);
 284        if (err)
 285                goto failed_free_io;
 286
 287        keypad->clk = clk_get(&pdev->dev, NULL);
 288        if (IS_ERR(keypad->clk)) {
 289                err = PTR_ERR(keypad->clk);
 290                goto failed_free_gpio;
 291        }
 292
 293        input_dev = input_allocate_device();
 294        if (!input_dev) {
 295                err = -ENOMEM;
 296                goto failed_put_clk;
 297        }
 298
 299        keypad->input_dev = input_dev;
 300
 301        input_dev->name = pdev->name;
 302        input_dev->id.bustype = BUS_HOST;
 303        input_dev->open = ep93xx_keypad_open;
 304        input_dev->close = ep93xx_keypad_close;
 305        input_dev->dev.parent = &pdev->dev;
 306
 307        err = matrix_keypad_build_keymap(keymap_data, NULL,
 308                                         EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
 309                                         keypad->keycodes, input_dev);
 310        if (err)
 311                goto failed_free_dev;
 312
 313        if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
 314                __set_bit(EV_REP, input_dev->evbit);
 315        input_set_drvdata(input_dev, keypad);
 316
 317        err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
 318                          0, pdev->name, keypad);
 319        if (err)
 320                goto failed_free_dev;
 321
 322        err = input_register_device(input_dev);
 323        if (err)
 324                goto failed_free_irq;
 325
 326        platform_set_drvdata(pdev, keypad);
 327        device_init_wakeup(&pdev->dev, 1);
 328
 329        return 0;
 330
 331failed_free_irq:
 332        free_irq(keypad->irq, keypad);
 333failed_free_dev:
 334        input_free_device(input_dev);
 335failed_put_clk:
 336        clk_put(keypad->clk);
 337failed_free_gpio:
 338        ep93xx_keypad_release_gpio(pdev);
 339failed_free_io:
 340        iounmap(keypad->mmio_base);
 341failed_free_mem:
 342        release_mem_region(res->start, resource_size(res));
 343failed_free:
 344        kfree(keypad);
 345        return err;
 346}
 347
 348static int ep93xx_keypad_remove(struct platform_device *pdev)
 349{
 350        struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 351        struct resource *res;
 352
 353        free_irq(keypad->irq, keypad);
 354
 355        if (keypad->enabled)
 356                clk_disable(keypad->clk);
 357        clk_put(keypad->clk);
 358
 359        input_unregister_device(keypad->input_dev);
 360
 361        ep93xx_keypad_release_gpio(pdev);
 362
 363        iounmap(keypad->mmio_base);
 364
 365        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 366        release_mem_region(res->start, resource_size(res));
 367
 368        kfree(keypad);
 369
 370        return 0;
 371}
 372
 373static struct platform_driver ep93xx_keypad_driver = {
 374        .driver         = {
 375                .name   = "ep93xx-keypad",
 376                .pm     = &ep93xx_keypad_pm_ops,
 377        },
 378        .probe          = ep93xx_keypad_probe,
 379        .remove         = ep93xx_keypad_remove,
 380};
 381module_platform_driver(ep93xx_keypad_driver);
 382
 383MODULE_LICENSE("GPL");
 384MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 385MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
 386MODULE_ALIAS("platform:ep93xx-keypad");
 387