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/platform_device.h>
  24#include <linux/interrupt.h>
  25#include <linux/input.h>
  26#include <linux/clk.h>
  27
  28#include <mach/hardware.h>
  29#include <mach/gpio.h>
  30#include <mach/ep93xx_keypad.h>
  31
  32/*
  33 * Keypad Interface Register offsets
  34 */
  35#define KEY_INIT                0x00    /* Key Scan Initialization register */
  36#define KEY_DIAG                0x04    /* Key Scan Diagnostic register */
  37#define KEY_REG                 0x08    /* Key Value Capture register */
  38
  39/* Key Scan Initialization Register bit defines */
  40#define KEY_INIT_DBNC_MASK      (0x00ff0000)
  41#define KEY_INIT_DBNC_SHIFT     (16)
  42#define KEY_INIT_DIS3KY         (1<<15)
  43#define KEY_INIT_DIAG           (1<<14)
  44#define KEY_INIT_BACK           (1<<13)
  45#define KEY_INIT_T2             (1<<12)
  46#define KEY_INIT_PRSCL_MASK     (0x000003ff)
  47#define KEY_INIT_PRSCL_SHIFT    (0)
  48
  49/* Key Scan Diagnostic Register bit defines */
  50#define KEY_DIAG_MASK           (0x0000003f)
  51#define KEY_DIAG_SHIFT          (0)
  52
  53/* Key Value Capture Register bit defines */
  54#define KEY_REG_K               (1<<15)
  55#define KEY_REG_INT             (1<<14)
  56#define KEY_REG_2KEYS           (1<<13)
  57#define KEY_REG_1KEY            (1<<12)
  58#define KEY_REG_KEY2_MASK       (0x00000fc0)
  59#define KEY_REG_KEY2_SHIFT      (6)
  60#define KEY_REG_KEY1_MASK       (0x0000003f)
  61#define KEY_REG_KEY1_SHIFT      (0)
  62
  63#define keypad_readl(off)       __raw_readl(keypad->mmio_base + (off))
  64#define keypad_writel(v, off)   __raw_writel((v), keypad->mmio_base + (off))
  65
  66#define MAX_MATRIX_KEY_NUM      (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
  67
  68struct ep93xx_keypad {
  69        struct ep93xx_keypad_platform_data *pdata;
  70
  71        struct clk *clk;
  72        struct input_dev *input_dev;
  73        void __iomem *mmio_base;
  74
  75        int irq;
  76        int enabled;
  77
  78        int key1;
  79        int key2;
  80
  81        unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
  82};
  83
  84static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad)
  85{
  86        struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
  87        struct input_dev *input_dev = keypad->input_dev;
  88        int i;
  89
  90        for (i = 0; i < pdata->matrix_key_map_size; i++) {
  91                unsigned int key = pdata->matrix_key_map[i];
  92                int row = (key >> 28) & 0xf;
  93                int col = (key >> 24) & 0xf;
  94                int code = key & 0xffffff;
  95
  96                keypad->matrix_keycodes[(row << 3) + col] = code;
  97                __set_bit(code, input_dev->keybit);
  98        }
  99}
 100
 101static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
 102{
 103        struct ep93xx_keypad *keypad = dev_id;
 104        struct input_dev *input_dev = keypad->input_dev;
 105        unsigned int status = keypad_readl(KEY_REG);
 106        int keycode, key1, key2;
 107
 108        keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
 109        key1 = keypad->matrix_keycodes[keycode];
 110
 111        keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
 112        key2 = keypad->matrix_keycodes[keycode];
 113
 114        if (status & KEY_REG_2KEYS) {
 115                if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
 116                        input_report_key(input_dev, keypad->key1, 0);
 117
 118                if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2)
 119                        input_report_key(input_dev, keypad->key2, 0);
 120
 121                input_report_key(input_dev, key1, 1);
 122                input_report_key(input_dev, key2, 1);
 123
 124                keypad->key1 = key1;
 125                keypad->key2 = key2;
 126
 127        } else if (status & KEY_REG_1KEY) {
 128                if (keypad->key1 && key1 != keypad->key1)
 129                        input_report_key(input_dev, keypad->key1, 0);
 130
 131                if (keypad->key2 && key1 != keypad->key2)
 132                        input_report_key(input_dev, keypad->key2, 0);
 133
 134                input_report_key(input_dev, key1, 1);
 135
 136                keypad->key1 = key1;
 137                keypad->key2 = 0;
 138
 139        } else {
 140                input_report_key(input_dev, keypad->key1, 0);
 141                input_report_key(input_dev, keypad->key2, 0);
 142
 143                keypad->key1 = keypad->key2 = 0;
 144        }
 145        input_sync(input_dev);
 146
 147        return IRQ_HANDLED;
 148}
 149
 150static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
 151{
 152        struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
 153        unsigned int val = 0;
 154
 155        clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV);
 156
 157        if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
 158                val |= KEY_INIT_DIS3KY;
 159        if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE)
 160                val |= KEY_INIT_DIAG;
 161        if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE)
 162                val |= KEY_INIT_BACK;
 163        if (pdata->flags & EP93XX_KEYPAD_TEST_MODE)
 164                val |= KEY_INIT_T2;
 165
 166        val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK);
 167
 168        val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
 169
 170        keypad_writel(val, KEY_INIT);
 171}
 172
 173static int ep93xx_keypad_open(struct input_dev *pdev)
 174{
 175        struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
 176
 177        if (!keypad->enabled) {
 178                ep93xx_keypad_config(keypad);
 179                clk_enable(keypad->clk);
 180                keypad->enabled = 1;
 181        }
 182
 183        return 0;
 184}
 185
 186static void ep93xx_keypad_close(struct input_dev *pdev)
 187{
 188        struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
 189
 190        if (keypad->enabled) {
 191                clk_disable(keypad->clk);
 192                keypad->enabled = 0;
 193        }
 194}
 195
 196
 197#ifdef CONFIG_PM
 198/*
 199 * NOTE: I don't know if this is correct, or will work on the ep93xx.
 200 *
 201 * None of the existing ep93xx drivers have power management support.
 202 * But, this is basically what the pxa27x_keypad driver does.
 203 */
 204static int ep93xx_keypad_suspend(struct platform_device *pdev,
 205                                 pm_message_t state)
 206{
 207        struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 208        struct input_dev *input_dev = keypad->input_dev;
 209
 210        mutex_lock(&input_dev->mutex);
 211
 212        if (keypad->enabled) {
 213                clk_disable(keypad->clk);
 214                keypad->enabled = 0;
 215        }
 216
 217        mutex_unlock(&input_dev->mutex);
 218
 219        if (device_may_wakeup(&pdev->dev))
 220                enable_irq_wake(keypad->irq);
 221
 222        return 0;
 223}
 224
 225static int ep93xx_keypad_resume(struct platform_device *pdev)
 226{
 227        struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 228        struct input_dev *input_dev = keypad->input_dev;
 229
 230        if (device_may_wakeup(&pdev->dev))
 231                disable_irq_wake(keypad->irq);
 232
 233        mutex_lock(&input_dev->mutex);
 234
 235        if (input_dev->users) {
 236                if (!keypad->enabled) {
 237                        ep93xx_keypad_config(keypad);
 238                        clk_enable(keypad->clk);
 239                        keypad->enabled = 1;
 240                }
 241        }
 242
 243        mutex_unlock(&input_dev->mutex);
 244
 245        return 0;
 246}
 247#else   /* !CONFIG_PM */
 248#define ep93xx_keypad_suspend   NULL
 249#define ep93xx_keypad_resume    NULL
 250#endif  /* !CONFIG_PM */
 251
 252static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
 253{
 254        struct ep93xx_keypad *keypad;
 255        struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data;
 256        struct input_dev *input_dev;
 257        struct resource *res;
 258        int irq, err, i, gpio;
 259
 260        if (!pdata ||
 261            !pdata->matrix_key_rows ||
 262            pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS ||
 263            !pdata->matrix_key_cols ||
 264            pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) {
 265                dev_err(&pdev->dev, "invalid or missing platform data\n");
 266                return -EINVAL;
 267        }
 268
 269        keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL);
 270        if (!keypad) {
 271                dev_err(&pdev->dev, "failed to allocate driver data\n");
 272                return -ENOMEM;
 273        }
 274
 275        keypad->pdata = pdata;
 276
 277        irq = platform_get_irq(pdev, 0);
 278        if (irq < 0) {
 279                dev_err(&pdev->dev, "failed to get keypad irq\n");
 280                err = -ENXIO;
 281                goto failed_free;
 282        }
 283
 284        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 285        if (!res) {
 286                dev_err(&pdev->dev, "failed to get I/O memory\n");
 287                err = -ENXIO;
 288                goto failed_free;
 289        }
 290
 291        res = request_mem_region(res->start, resource_size(res), pdev->name);
 292        if (!res) {
 293                dev_err(&pdev->dev, "failed to request I/O memory\n");
 294                err = -EBUSY;
 295                goto failed_free;
 296        }
 297
 298        keypad->mmio_base = ioremap(res->start, resource_size(res));
 299        if (keypad->mmio_base == NULL) {
 300                dev_err(&pdev->dev, "failed to remap I/O memory\n");
 301                err = -ENXIO;
 302                goto failed_free_mem;
 303        }
 304
 305        /* Request the needed GPIO's */
 306        gpio = EP93XX_GPIO_LINE_ROW0;
 307        for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) {
 308                err = gpio_request(gpio, pdev->name);
 309                if (err) {
 310                        dev_err(&pdev->dev, "failed to request gpio-%d\n",
 311                                gpio);
 312                        goto failed_free_rows;
 313                }
 314        }
 315
 316        gpio = EP93XX_GPIO_LINE_COL0;
 317        for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) {
 318                err = gpio_request(gpio, pdev->name);
 319                if (err) {
 320                        dev_err(&pdev->dev, "failed to request gpio-%d\n",
 321                                gpio);
 322                        goto failed_free_cols;
 323                }
 324        }
 325
 326        keypad->clk = clk_get(&pdev->dev, "key_clk");
 327        if (IS_ERR(keypad->clk)) {
 328                dev_err(&pdev->dev, "failed to get keypad clock\n");
 329                err = PTR_ERR(keypad->clk);
 330                goto failed_free_io;
 331        }
 332
 333        /* Create and register the input driver */
 334        input_dev = input_allocate_device();
 335        if (!input_dev) {
 336                dev_err(&pdev->dev, "failed to allocate input device\n");
 337                err = -ENOMEM;
 338                goto failed_put_clk;
 339        }
 340
 341        keypad->input_dev = input_dev;
 342
 343        input_dev->name = pdev->name;
 344        input_dev->id.bustype = BUS_HOST;
 345        input_dev->open = ep93xx_keypad_open;
 346        input_dev->close = ep93xx_keypad_close;
 347        input_dev->dev.parent = &pdev->dev;
 348        input_dev->keycode = keypad->matrix_keycodes;
 349        input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]);
 350        input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes);
 351
 352        input_set_drvdata(input_dev, keypad);
 353
 354        input_dev->evbit[0] = BIT_MASK(EV_KEY);
 355        if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
 356                input_dev->evbit[0] |= BIT_MASK(EV_REP);
 357
 358        ep93xx_keypad_build_keycode(keypad);
 359        platform_set_drvdata(pdev, keypad);
 360
 361        err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED,
 362                                pdev->name, keypad);
 363        if (err) {
 364                dev_err(&pdev->dev, "failed to request IRQ\n");
 365                goto failed_free_dev;
 366        }
 367
 368        keypad->irq = irq;
 369
 370        /* Register the input device */
 371        err = input_register_device(input_dev);
 372        if (err) {
 373                dev_err(&pdev->dev, "failed to register input device\n");
 374                goto failed_free_irq;
 375        }
 376
 377        device_init_wakeup(&pdev->dev, 1);
 378
 379        return 0;
 380
 381failed_free_irq:
 382        free_irq(irq, pdev);
 383        platform_set_drvdata(pdev, NULL);
 384failed_free_dev:
 385        input_free_device(input_dev);
 386failed_put_clk:
 387        clk_put(keypad->clk);
 388failed_free_io:
 389        i = keypad->pdata->matrix_key_cols - 1;
 390        gpio = EP93XX_GPIO_LINE_COL0 + i;
 391failed_free_cols:
 392        for ( ; i >= 0; i--, gpio--)
 393                gpio_free(gpio);
 394        i = keypad->pdata->matrix_key_rows - 1;
 395        gpio = EP93XX_GPIO_LINE_ROW0 + i;
 396failed_free_rows:
 397        for ( ; i >= 0; i--, gpio--)
 398                gpio_free(gpio);
 399        iounmap(keypad->mmio_base);
 400failed_free_mem:
 401        release_mem_region(res->start, resource_size(res));
 402failed_free:
 403        kfree(keypad);
 404        return err;
 405}
 406
 407static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
 408{
 409        struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 410        struct resource *res;
 411        int i, gpio;
 412
 413        free_irq(keypad->irq, pdev);
 414
 415        platform_set_drvdata(pdev, NULL);
 416
 417        if (keypad->enabled)
 418                clk_disable(keypad->clk);
 419        clk_put(keypad->clk);
 420
 421        input_unregister_device(keypad->input_dev);
 422
 423        i = keypad->pdata->matrix_key_cols - 1;
 424        gpio = EP93XX_GPIO_LINE_COL0 + i;
 425        for ( ; i >= 0; i--, gpio--)
 426                gpio_free(gpio);
 427
 428        i = keypad->pdata->matrix_key_rows - 1;
 429        gpio = EP93XX_GPIO_LINE_ROW0 + i;
 430        for ( ; i >= 0; i--, gpio--)
 431                gpio_free(gpio);
 432
 433        iounmap(keypad->mmio_base);
 434
 435        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 436        release_mem_region(res->start, resource_size(res));
 437
 438        kfree(keypad);
 439
 440        return 0;
 441}
 442
 443static struct platform_driver ep93xx_keypad_driver = {
 444        .driver         = {
 445                .name   = "ep93xx-keypad",
 446                .owner  = THIS_MODULE,
 447        },
 448        .probe          = ep93xx_keypad_probe,
 449        .remove         = __devexit_p(ep93xx_keypad_remove),
 450        .suspend        = ep93xx_keypad_suspend,
 451        .resume         = ep93xx_keypad_resume,
 452};
 453
 454static int __init ep93xx_keypad_init(void)
 455{
 456        return platform_driver_register(&ep93xx_keypad_driver);
 457}
 458
 459static void __exit ep93xx_keypad_exit(void)
 460{
 461        platform_driver_unregister(&ep93xx_keypad_driver);
 462}
 463
 464module_init(ep93xx_keypad_init);
 465module_exit(ep93xx_keypad_exit);
 466
 467MODULE_LICENSE("GPL");
 468MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 469MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
 470MODULE_ALIAS("platform:ep93xx-keypad");
 471