1 /* 2 * Samsung keypad driver 3 * 4 * Copyright (C) 2010 Samsung Electronics Co.Ltd 5 * Author: Joonyoung Shim <jy0922.shim@samsung.com> 6 * Author: Donghwa Lee <dh09.lee@samsung.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14 #include <linux/clk.h> 15 #include <linux/delay.h> 16 #include <linux/err.h> 17 #include <linux/init.h> 18 #include <linux/input.h> 19 #include <linux/interrupt.h> 20 #include <linux/io.h> 21 #include <linux/module.h> 22 #include <linux/platform_device.h> 23 #include <linux/slab.h> 24 #include <linux/of.h> 25 #include <linux/of_gpio.h> 26 #include <linux/sched.h> 27 #include <plat/keypad.h> 28 29 #define SAMSUNG_KEYIFCON 0x00 30 #define SAMSUNG_KEYIFSTSCLR 0x04 31 #define SAMSUNG_KEYIFCOL 0x08 32 #define SAMSUNG_KEYIFROW 0x0c 33 #define SAMSUNG_KEYIFFC 0x10 34 35 /* SAMSUNG_KEYIFCON */ 36 #define SAMSUNG_KEYIFCON_INT_F_EN (1 << 0) 37 #define SAMSUNG_KEYIFCON_INT_R_EN (1 << 1) 38 #define SAMSUNG_KEYIFCON_DF_EN (1 << 2) 39 #define SAMSUNG_KEYIFCON_FC_EN (1 << 3) 40 #define SAMSUNG_KEYIFCON_WAKEUPEN (1 << 4) 41 42 /* SAMSUNG_KEYIFSTSCLR */ 43 #define SAMSUNG_KEYIFSTSCLR_P_INT_MASK (0xff << 0) 44 #define SAMSUNG_KEYIFSTSCLR_R_INT_MASK (0xff << 8) 45 #define SAMSUNG_KEYIFSTSCLR_R_INT_OFFSET 8 46 #define S5PV210_KEYIFSTSCLR_P_INT_MASK (0x3fff << 0) 47 #define S5PV210_KEYIFSTSCLR_R_INT_MASK (0x3fff << 16) 48 #define S5PV210_KEYIFSTSCLR_R_INT_OFFSET 16 49 50 /* SAMSUNG_KEYIFCOL */ 51 #define SAMSUNG_KEYIFCOL_MASK (0xff << 0) 52 #define S5PV210_KEYIFCOLEN_MASK (0xff << 8) 53 54 /* SAMSUNG_KEYIFROW */ 55 #define SAMSUNG_KEYIFROW_MASK (0xff << 0) 56 #define S5PV210_KEYIFROW_MASK (0x3fff << 0) 57 58 /* SAMSUNG_KEYIFFC */ 59 #define SAMSUNG_KEYIFFC_MASK (0x3ff << 0) 60 61 enum samsung_keypad_type { 62 KEYPAD_TYPE_SAMSUNG, 63 KEYPAD_TYPE_S5PV210, 64 }; 65 66 struct samsung_keypad { 67 struct input_dev *input_dev; 68 struct clk *clk; 69 void __iomem *base; 70 wait_queue_head_t wait; 71 bool stopped; 72 int irq; 73 enum samsung_keypad_type type; 74 unsigned int row_shift; 75 unsigned int rows; 76 unsigned int cols; 77 unsigned int row_state[SAMSUNG_MAX_COLS]; 78 #ifdef CONFIG_OF 79 int row_gpios[SAMSUNG_MAX_ROWS]; 80 int col_gpios[SAMSUNG_MAX_COLS]; 81 #endif 82 unsigned short keycodes[]; 83 }; 84 85 static void samsung_keypad_scan(struct samsung_keypad *keypad, 86 unsigned int *row_state) 87 { 88 unsigned int col; 89 unsigned int val; 90 91 for (col = 0; col < keypad->cols; col++) { 92 if (keypad->type == KEYPAD_TYPE_S5PV210) { 93 val = S5PV210_KEYIFCOLEN_MASK; 94 val &= ~(1 << col) << 8; 95 } else { 96 val = SAMSUNG_KEYIFCOL_MASK; 97 val &= ~(1 << col); 98 } 99 100 writel(val, keypad->base + SAMSUNG_KEYIFCOL); 101 mdelay(1); 102 103 val = readl(keypad->base + SAMSUNG_KEYIFROW); 104 row_state[col] = ~val & ((1 << keypad->rows) - 1); 105 } 106 107 /* KEYIFCOL reg clear */ 108 writel(0, keypad->base + SAMSUNG_KEYIFCOL); 109 } 110 111 static bool samsung_keypad_report(struct samsung_keypad *keypad, 112 unsigned int *row_state) 113 { 114 struct input_dev *input_dev = keypad->input_dev; 115 unsigned int changed; 116 unsigned int pressed; 117 unsigned int key_down = 0; 118 unsigned int val; 119 unsigned int col, row; 120 121 for (col = 0; col < keypad->cols; col++) { 122 changed = row_state[col] ^ keypad->row_state[col]; 123 key_down |= row_state[col]; 124 if (!changed) 125 continue; 126 127 for (row = 0; row < keypad->rows; row++) { 128 if (!(changed & (1 << row))) 129 continue; 130 131 pressed = row_state[col] & (1 << row); 132 133 dev_dbg(&keypad->input_dev->dev, 134 "key %s, row: %d, col: %d\n", 135 pressed ? "pressed" : "released", row, col); 136 137 val = MATRIX_SCAN_CODE(row, col, keypad->row_shift); 138 139 input_event(input_dev, EV_MSC, MSC_SCAN, val); 140 input_report_key(input_dev, 141 keypad->keycodes[val], pressed); 142 } 143 input_sync(keypad->input_dev); 144 } 145 146 memcpy(keypad->row_state, row_state, sizeof(keypad->row_state)); 147 148 return key_down; 149 } 150 151 static irqreturn_t samsung_keypad_irq(int irq, void *dev_id) 152 { 153 struct samsung_keypad *keypad = dev_id; 154 unsigned int row_state[SAMSUNG_MAX_COLS]; 155 unsigned int val; 156 bool key_down; 157 158 do { 159 val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR); 160 /* Clear interrupt. */ 161 writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR); 162 163 samsung_keypad_scan(keypad, row_state); 164 165 key_down = samsung_keypad_report(keypad, row_state); 166 if (key_down) 167 wait_event_timeout(keypad->wait, keypad->stopped, 168 msecs_to_jiffies(50)); 169 170 } while (key_down && !keypad->stopped); 171 172 return IRQ_HANDLED; 173 } 174 175 static void samsung_keypad_start(struct samsung_keypad *keypad) 176 { 177 unsigned int val; 178 179 /* Tell IRQ thread that it may poll the device. */ 180 keypad->stopped = false; 181 182 clk_enable(keypad->clk); 183 184 /* Enable interrupt bits. */ 185 val = readl(keypad->base + SAMSUNG_KEYIFCON); 186 val |= SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN; 187 writel(val, keypad->base + SAMSUNG_KEYIFCON); 188 189 /* KEYIFCOL reg clear. */ 190 writel(0, keypad->base + SAMSUNG_KEYIFCOL); 191 } 192 193 static void samsung_keypad_stop(struct samsung_keypad *keypad) 194 { 195 unsigned int val; 196 197 /* Signal IRQ thread to stop polling and disable the handler. */ 198 keypad->stopped = true; 199 wake_up(&keypad->wait); 200 disable_irq(keypad->irq); 201 202 /* Clear interrupt. */ 203 writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR); 204 205 /* Disable interrupt bits. */ 206 val = readl(keypad->base + SAMSUNG_KEYIFCON); 207 val &= ~(SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN); 208 writel(val, keypad->base + SAMSUNG_KEYIFCON); 209 210 clk_disable(keypad->clk); 211 212 /* 213 * Now that chip should not generate interrupts we can safely 214 * re-enable the handler. 215 */ 216 enable_irq(keypad->irq); 217 } 218 219 static int samsung_keypad_open(struct input_dev *input_dev) 220 { 221 struct samsung_keypad *keypad = input_get_drvdata(input_dev); 222 223 samsung_keypad_start(keypad); 224 225 return 0; 226 } 227 228 static void samsung_keypad_close(struct input_dev *input_dev) 229 { 230 struct samsung_keypad *keypad = input_get_drvdata(input_dev); 231 232 samsung_keypad_stop(keypad); 233 } 234 235 #ifdef CONFIG_OF 236 static struct samsung_keypad_platdata *samsung_keypad_parse_dt( 237 struct device *dev) 238 { 239 struct samsung_keypad_platdata *pdata; 240 struct matrix_keymap_data *keymap_data; 241 uint32_t *keymap, num_rows = 0, num_cols = 0; 242 struct device_node *np = dev->of_node, *key_np; 243 unsigned int key_count = 0; 244 245 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 246 if (!pdata) { 247 dev_err(dev, "could not allocate memory for platform data\n"); 248 return NULL; 249 } 250 251 of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows); 252 of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols); 253 if (!num_rows || !num_cols) { 254 dev_err(dev, "number of keypad rows/columns not specified\n"); 255 return NULL; 256 } 257 pdata->rows = num_rows; 258 pdata->cols = num_cols; 259 260 keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL); 261 if (!keymap_data) { 262 dev_err(dev, "could not allocate memory for keymap data\n"); 263 return NULL; 264 } 265 pdata->keymap_data = keymap_data; 266 267 for_each_child_of_node(np, key_np) 268 key_count++; 269 270 keymap_data->keymap_size = key_count; 271 keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); 272 if (!keymap) { 273 dev_err(dev, "could not allocate memory for keymap\n"); 274 return NULL; 275 } 276 keymap_data->keymap = keymap; 277 278 for_each_child_of_node(np, key_np) { 279 u32 row, col, key_code; 280 of_property_read_u32(key_np, "keypad,row", &row); 281 of_property_read_u32(key_np, "keypad,column", &col); 282 of_property_read_u32(key_np, "linux,code", &key_code); 283 *keymap++ = KEY(row, col, key_code); 284 } 285 286 if (of_get_property(np, "linux,input-no-autorepeat", NULL)) 287 pdata->no_autorepeat = true; 288 if (of_get_property(np, "linux,input-wakeup", NULL)) 289 pdata->wakeup = true; 290 291 return pdata; 292 } 293 294 static void samsung_keypad_parse_dt_gpio(struct device *dev, 295 struct samsung_keypad *keypad) 296 { 297 struct device_node *np = dev->of_node; 298 int gpio, ret, row, col; 299 300 for (row = 0; row < keypad->rows; row++) { 301 gpio = of_get_named_gpio(np, "row-gpios", row); 302 keypad->row_gpios[row] = gpio; 303 if (!gpio_is_valid(gpio)) { 304 dev_err(dev, "keypad row[%d]: invalid gpio %d\n", 305 row, gpio); 306 continue; 307 } 308 309 ret = gpio_request(gpio, "keypad-row"); 310 if (ret) 311 dev_err(dev, "keypad row[%d] gpio request failed\n", 312 row); 313 } 314 315 for (col = 0; col < keypad->cols; col++) { 316 gpio = of_get_named_gpio(np, "col-gpios", col); 317 keypad->col_gpios[col] = gpio; 318 if (!gpio_is_valid(gpio)) { 319 dev_err(dev, "keypad column[%d]: invalid gpio %d\n", 320 col, gpio); 321 continue; 322 } 323 324 ret = gpio_request(gpio, "keypad-col"); 325 if (ret) 326 dev_err(dev, "keypad column[%d] gpio request failed\n", 327 col); 328 } 329 } 330 331 static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) 332 { 333 int cnt; 334 335 for (cnt = 0; cnt < keypad->rows; cnt++) 336 if (gpio_is_valid(keypad->row_gpios[cnt])) 337 gpio_free(keypad->row_gpios[cnt]); 338 339 for (cnt = 0; cnt < keypad->cols; cnt++) 340 if (gpio_is_valid(keypad->col_gpios[cnt])) 341 gpio_free(keypad->col_gpios[cnt]); 342 } 343 #else 344 static 345 struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) 346 { 347 return NULL; 348 } 349 350 static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) 351 { 352 } 353 #endif 354 355 static int __devinit samsung_keypad_probe(struct platform_device *pdev) 356 { 357 const struct samsung_keypad_platdata *pdata; 358 const struct matrix_keymap_data *keymap_data; 359 struct samsung_keypad *keypad; 360 struct resource *res; 361 struct input_dev *input_dev; 362 unsigned int row_shift; 363 unsigned int keymap_size; 364 int error; 365 366 if (pdev->dev.of_node) 367 pdata = samsung_keypad_parse_dt(&pdev->dev); 368 else 369 pdata = pdev->dev.platform_data; 370 if (!pdata) { 371 dev_err(&pdev->dev, "no platform data defined\n"); 372 return -EINVAL; 373 } 374 375 keymap_data = pdata->keymap_data; 376 if (!keymap_data) { 377 dev_err(&pdev->dev, "no keymap data defined\n"); 378 return -EINVAL; 379 } 380 381 if (!pdata->rows || pdata->rows > SAMSUNG_MAX_ROWS) 382 return -EINVAL; 383 384 if (!pdata->cols || pdata->cols > SAMSUNG_MAX_COLS) 385 return -EINVAL; 386 387 /* initialize the gpio */ 388 if (pdata->cfg_gpio) 389 pdata->cfg_gpio(pdata->rows, pdata->cols); 390 391 row_shift = get_count_order(pdata->cols); 392 keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]); 393 394 keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL); 395 input_dev = input_allocate_device(); 396 if (!keypad || !input_dev) { 397 error = -ENOMEM; 398 goto err_free_mem; 399 } 400 401 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 402 if (!res) { 403 error = -ENODEV; 404 goto err_free_mem; 405 } 406 407 keypad->base = ioremap(res->start, resource_size(res)); 408 if (!keypad->base) { 409 error = -EBUSY; 410 goto err_free_mem; 411 } 412 413 keypad->clk = clk_get(&pdev->dev, "keypad"); 414 if (IS_ERR(keypad->clk)) { 415 dev_err(&pdev->dev, "failed to get keypad clk\n"); 416 error = PTR_ERR(keypad->clk); 417 goto err_unmap_base; 418 } 419 420 keypad->input_dev = input_dev; 421 keypad->row_shift = row_shift; 422 keypad->rows = pdata->rows; 423 keypad->cols = pdata->cols; 424 init_waitqueue_head(&keypad->wait); 425 426 if (pdev->dev.of_node) { 427 #ifdef CONFIG_OF 428 samsung_keypad_parse_dt_gpio(&pdev->dev, keypad); 429 keypad->type = of_device_is_compatible(pdev->dev.of_node, 430 "samsung,s5pv210-keypad"); 431 #endif 432 } else { 433 keypad->type = platform_get_device_id(pdev)->driver_data; 434 } 435 436 input_dev->name = pdev->name; 437 input_dev->id.bustype = BUS_HOST; 438 input_dev->dev.parent = &pdev->dev; 439 input_set_drvdata(input_dev, keypad); 440 441 input_dev->open = samsung_keypad_open; 442 input_dev->close = samsung_keypad_close; 443 444 input_dev->evbit[0] = BIT_MASK(EV_KEY); 445 if (!pdata->no_autorepeat) 446 input_dev->evbit[0] |= BIT_MASK(EV_REP); 447 448 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 449 450 input_dev->keycode = keypad->keycodes; 451 input_dev->keycodesize = sizeof(keypad->keycodes[0]); 452 input_dev->keycodemax = pdata->rows << row_shift; 453 454 matrix_keypad_build_keymap(keymap_data, row_shift, 455 input_dev->keycode, input_dev->keybit); 456 457 keypad->irq = platform_get_irq(pdev, 0); 458 if (keypad->irq < 0) { 459 error = keypad->irq; 460 goto err_put_clk; 461 } 462 463 error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq, 464 IRQF_ONESHOT, dev_name(&pdev->dev), keypad); 465 if (error) { 466 dev_err(&pdev->dev, "failed to register keypad interrupt\n"); 467 goto err_put_clk; 468 } 469 470 error = input_register_device(keypad->input_dev); 471 if (error) 472 goto err_free_irq; 473 474 device_init_wakeup(&pdev->dev, pdata->wakeup); 475 platform_set_drvdata(pdev, keypad); 476 477 if (pdev->dev.of_node) { 478 devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap); 479 devm_kfree(&pdev->dev, (void *)pdata->keymap_data); 480 devm_kfree(&pdev->dev, (void *)pdata); 481 } 482 return 0; 483 484 err_free_irq: 485 free_irq(keypad->irq, keypad); 486 err_put_clk: 487 clk_put(keypad->clk); 488 samsung_keypad_dt_gpio_free(keypad); 489 err_unmap_base: 490 iounmap(keypad->base); 491 err_free_mem: 492 input_free_device(input_dev); 493 kfree(keypad); 494 495 return error; 496 } 497 498 static int __devexit samsung_keypad_remove(struct platform_device *pdev) 499 { 500 struct samsung_keypad *keypad = platform_get_drvdata(pdev); 501 502 device_init_wakeup(&pdev->dev, 0); 503 platform_set_drvdata(pdev, NULL); 504 505 input_unregister_device(keypad->input_dev); 506 507 /* 508 * It is safe to free IRQ after unregistering device because 509 * samsung_keypad_close will shut off interrupts. 510 */ 511 free_irq(keypad->irq, keypad); 512 513 clk_put(keypad->clk); 514 samsung_keypad_dt_gpio_free(keypad); 515 516 iounmap(keypad->base); 517 kfree(keypad); 518 519 return 0; 520 } 521 522 #ifdef CONFIG_PM 523 static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad, 524 bool enable) 525 { 526 struct device *dev = keypad->input_dev->dev.parent; 527 unsigned int val; 528 529 clk_enable(keypad->clk); 530 531 val = readl(keypad->base + SAMSUNG_KEYIFCON); 532 if (enable) { 533 val |= SAMSUNG_KEYIFCON_WAKEUPEN; 534 if (device_may_wakeup(dev)) 535 enable_irq_wake(keypad->irq); 536 } else { 537 val &= ~SAMSUNG_KEYIFCON_WAKEUPEN; 538 if (device_may_wakeup(dev)) 539 disable_irq_wake(keypad->irq); 540 } 541 writel(val, keypad->base + SAMSUNG_KEYIFCON); 542 543 clk_disable(keypad->clk); 544 } 545 546 static int samsung_keypad_suspend(struct device *dev) 547 { 548 struct platform_device *pdev = to_platform_device(dev); 549 struct samsung_keypad *keypad = platform_get_drvdata(pdev); 550 struct input_dev *input_dev = keypad->input_dev; 551 552 mutex_lock(&input_dev->mutex); 553 554 if (input_dev->users) 555 samsung_keypad_stop(keypad); 556 557 samsung_keypad_toggle_wakeup(keypad, true); 558 559 mutex_unlock(&input_dev->mutex); 560 561 return 0; 562 } 563 564 static int samsung_keypad_resume(struct device *dev) 565 { 566 struct platform_device *pdev = to_platform_device(dev); 567 struct samsung_keypad *keypad = platform_get_drvdata(pdev); 568 struct input_dev *input_dev = keypad->input_dev; 569 570 mutex_lock(&input_dev->mutex); 571 572 samsung_keypad_toggle_wakeup(keypad, false); 573 574 if (input_dev->users) 575 samsung_keypad_start(keypad); 576 577 mutex_unlock(&input_dev->mutex); 578 579 return 0; 580 } 581 582 static const struct dev_pm_ops samsung_keypad_pm_ops = { 583 .suspend = samsung_keypad_suspend, 584 .resume = samsung_keypad_resume, 585 }; 586 #endif 587 588 #ifdef CONFIG_OF 589 static const struct of_device_id samsung_keypad_dt_match[] = { 590 { .compatible = "samsung,s3c6410-keypad" }, 591 { .compatible = "samsung,s5pv210-keypad" }, 592 {}, 593 }; 594 MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match); 595 #else 596 #define samsung_keypad_dt_match NULL 597 #endif 598 599 static struct platform_device_id samsung_keypad_driver_ids[] = { 600 { 601 .name = "samsung-keypad", 602 .driver_data = KEYPAD_TYPE_SAMSUNG, 603 }, { 604 .name = "s5pv210-keypad", 605 .driver_data = KEYPAD_TYPE_S5PV210, 606 }, 607 { }, 608 }; 609 MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids); 610 611 static struct platform_driver samsung_keypad_driver = { 612 .probe = samsung_keypad_probe, 613 .remove = __devexit_p(samsung_keypad_remove), 614 .driver = { 615 .name = "samsung-keypad", 616 .owner = THIS_MODULE, 617 .of_match_table = samsung_keypad_dt_match, 618 #ifdef CONFIG_PM 619 .pm = &samsung_keypad_pm_ops, 620 #endif 621 }, 622 .id_table = samsung_keypad_driver_ids, 623 }; 624 625 static int __init samsung_keypad_init(void) 626 { 627 return platform_driver_register(&samsung_keypad_driver); 628 } 629 module_init(samsung_keypad_init); 630 631 static void __exit samsung_keypad_exit(void) 632 { 633 platform_driver_unregister(&samsung_keypad_driver); 634 } 635 module_exit(samsung_keypad_exit); 636 637 MODULE_DESCRIPTION("Samsung keypad driver"); 638 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 639 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>"); 640 MODULE_LICENSE("GPL"); 641 MODULE_ALIAS("platform:samsung-keypad"); 642