Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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