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/sched.h> 25 #include <plat/keypad.h> 26 27 #define SAMSUNG_KEYIFCON 0x00 28 #define SAMSUNG_KEYIFSTSCLR 0x04 29 #define SAMSUNG_KEYIFCOL 0x08 30 #define SAMSUNG_KEYIFROW 0x0c 31 #define SAMSUNG_KEYIFFC 0x10 32 33 /* SAMSUNG_KEYIFCON */ 34 #define SAMSUNG_KEYIFCON_INT_F_EN (1 << 0) 35 #define SAMSUNG_KEYIFCON_INT_R_EN (1 << 1) 36 #define SAMSUNG_KEYIFCON_DF_EN (1 << 2) 37 #define SAMSUNG_KEYIFCON_FC_EN (1 << 3) 38 #define SAMSUNG_KEYIFCON_WAKEUPEN (1 << 4) 39 40 /* SAMSUNG_KEYIFSTSCLR */ 41 #define SAMSUNG_KEYIFSTSCLR_P_INT_MASK (0xff << 0) 42 #define SAMSUNG_KEYIFSTSCLR_R_INT_MASK (0xff << 8) 43 #define SAMSUNG_KEYIFSTSCLR_R_INT_OFFSET 8 44 #define S5PV210_KEYIFSTSCLR_P_INT_MASK (0x3fff << 0) 45 #define S5PV210_KEYIFSTSCLR_R_INT_MASK (0x3fff << 16) 46 #define S5PV210_KEYIFSTSCLR_R_INT_OFFSET 16 47 48 /* SAMSUNG_KEYIFCOL */ 49 #define SAMSUNG_KEYIFCOL_MASK (0xff << 0) 50 #define S5PV210_KEYIFCOLEN_MASK (0xff << 8) 51 52 /* SAMSUNG_KEYIFROW */ 53 #define SAMSUNG_KEYIFROW_MASK (0xff << 0) 54 #define S5PV210_KEYIFROW_MASK (0x3fff << 0) 55 56 /* SAMSUNG_KEYIFFC */ 57 #define SAMSUNG_KEYIFFC_MASK (0x3ff << 0) 58 59 enum samsung_keypad_type { 60 KEYPAD_TYPE_SAMSUNG, 61 KEYPAD_TYPE_S5PV210, 62 }; 63 64 struct samsung_keypad { 65 struct input_dev *input_dev; 66 struct clk *clk; 67 void __iomem *base; 68 wait_queue_head_t wait; 69 bool stopped; 70 int irq; 71 unsigned int row_shift; 72 unsigned int rows; 73 unsigned int cols; 74 unsigned int row_state[SAMSUNG_MAX_COLS]; 75 unsigned short keycodes[]; 76 }; 77 78 static int samsung_keypad_is_s5pv210(struct device *dev) 79 { 80 struct platform_device *pdev = to_platform_device(dev); 81 enum samsung_keypad_type type = 82 platform_get_device_id(pdev)->driver_data; 83 84 return type == KEYPAD_TYPE_S5PV210; 85 } 86 87 static void samsung_keypad_scan(struct samsung_keypad *keypad, 88 unsigned int *row_state) 89 { 90 struct device *dev = keypad->input_dev->dev.parent; 91 unsigned int col; 92 unsigned int val; 93 94 for (col = 0; col < keypad->cols; col++) { 95 if (samsung_keypad_is_s5pv210(dev)) { 96 val = S5PV210_KEYIFCOLEN_MASK; 97 val &= ~(1 << col) << 8; 98 } else { 99 val = SAMSUNG_KEYIFCOL_MASK; 100 val &= ~(1 << col); 101 } 102 103 writel(val, keypad->base + SAMSUNG_KEYIFCOL); 104 mdelay(1); 105 106 val = readl(keypad->base + SAMSUNG_KEYIFROW); 107 row_state[col] = ~val & ((1 << keypad->rows) - 1); 108 } 109 110 /* KEYIFCOL reg clear */ 111 writel(0, keypad->base + SAMSUNG_KEYIFCOL); 112 } 113 114 static bool samsung_keypad_report(struct samsung_keypad *keypad, 115 unsigned int *row_state) 116 { 117 struct input_dev *input_dev = keypad->input_dev; 118 unsigned int changed; 119 unsigned int pressed; 120 unsigned int key_down = 0; 121 unsigned int val; 122 unsigned int col, row; 123 124 for (col = 0; col < keypad->cols; col++) { 125 changed = row_state[col] ^ keypad->row_state[col]; 126 key_down |= row_state[col]; 127 if (!changed) 128 continue; 129 130 for (row = 0; row < keypad->rows; row++) { 131 if (!(changed & (1 << row))) 132 continue; 133 134 pressed = row_state[col] & (1 << row); 135 136 dev_dbg(&keypad->input_dev->dev, 137 "key %s, row: %d, col: %d\n", 138 pressed ? "pressed" : "released", row, col); 139 140 val = MATRIX_SCAN_CODE(row, col, keypad->row_shift); 141 142 input_event(input_dev, EV_MSC, MSC_SCAN, val); 143 input_report_key(input_dev, 144 keypad->keycodes[val], pressed); 145 } 146 input_sync(keypad->input_dev); 147 } 148 149 memcpy(keypad->row_state, row_state, sizeof(keypad->row_state)); 150 151 return key_down; 152 } 153 154 static irqreturn_t samsung_keypad_irq(int irq, void *dev_id) 155 { 156 struct samsung_keypad *keypad = dev_id; 157 unsigned int row_state[SAMSUNG_MAX_COLS]; 158 unsigned int val; 159 bool key_down; 160 161 do { 162 val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR); 163 /* Clear interrupt. */ 164 writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR); 165 166 samsung_keypad_scan(keypad, row_state); 167 168 key_down = samsung_keypad_report(keypad, row_state); 169 if (key_down) 170 wait_event_timeout(keypad->wait, keypad->stopped, 171 msecs_to_jiffies(50)); 172 173 } while (key_down && !keypad->stopped); 174 175 return IRQ_HANDLED; 176 } 177 178 static void samsung_keypad_start(struct samsung_keypad *keypad) 179 { 180 unsigned int val; 181 182 /* Tell IRQ thread that it may poll the device. */ 183 keypad->stopped = false; 184 185 clk_enable(keypad->clk); 186 187 /* Enable interrupt bits. */ 188 val = readl(keypad->base + SAMSUNG_KEYIFCON); 189 val |= SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN; 190 writel(val, keypad->base + SAMSUNG_KEYIFCON); 191 192 /* KEYIFCOL reg clear. */ 193 writel(0, keypad->base + SAMSUNG_KEYIFCOL); 194 } 195 196 static void samsung_keypad_stop(struct samsung_keypad *keypad) 197 { 198 unsigned int val; 199 200 /* Signal IRQ thread to stop polling and disable the handler. */ 201 keypad->stopped = true; 202 wake_up(&keypad->wait); 203 disable_irq(keypad->irq); 204 205 /* Clear interrupt. */ 206 writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR); 207 208 /* Disable interrupt bits. */ 209 val = readl(keypad->base + SAMSUNG_KEYIFCON); 210 val &= ~(SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN); 211 writel(val, keypad->base + SAMSUNG_KEYIFCON); 212 213 clk_disable(keypad->clk); 214 215 /* 216 * Now that chip should not generate interrupts we can safely 217 * re-enable the handler. 218 */ 219 enable_irq(keypad->irq); 220 } 221 222 static int samsung_keypad_open(struct input_dev *input_dev) 223 { 224 struct samsung_keypad *keypad = input_get_drvdata(input_dev); 225 226 samsung_keypad_start(keypad); 227 228 return 0; 229 } 230 231 static void samsung_keypad_close(struct input_dev *input_dev) 232 { 233 struct samsung_keypad *keypad = input_get_drvdata(input_dev); 234 235 samsung_keypad_stop(keypad); 236 } 237 238 static int __devinit samsung_keypad_probe(struct platform_device *pdev) 239 { 240 const struct samsung_keypad_platdata *pdata; 241 const struct matrix_keymap_data *keymap_data; 242 struct samsung_keypad *keypad; 243 struct resource *res; 244 struct input_dev *input_dev; 245 unsigned int row_shift; 246 unsigned int keymap_size; 247 int error; 248 249 pdata = pdev->dev.platform_data; 250 if (!pdata) { 251 dev_err(&pdev->dev, "no platform data defined\n"); 252 return -EINVAL; 253 } 254 255 keymap_data = pdata->keymap_data; 256 if (!keymap_data) { 257 dev_err(&pdev->dev, "no keymap data defined\n"); 258 return -EINVAL; 259 } 260 261 if (!pdata->rows || pdata->rows > SAMSUNG_MAX_ROWS) 262 return -EINVAL; 263 264 if (!pdata->cols || pdata->cols > SAMSUNG_MAX_COLS) 265 return -EINVAL; 266 267 /* initialize the gpio */ 268 if (pdata->cfg_gpio) 269 pdata->cfg_gpio(pdata->rows, pdata->cols); 270 271 row_shift = get_count_order(pdata->cols); 272 keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]); 273 274 keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL); 275 input_dev = input_allocate_device(); 276 if (!keypad || !input_dev) { 277 error = -ENOMEM; 278 goto err_free_mem; 279 } 280 281 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 282 if (!res) { 283 error = -ENODEV; 284 goto err_free_mem; 285 } 286 287 keypad->base = ioremap(res->start, resource_size(res)); 288 if (!keypad->base) { 289 error = -EBUSY; 290 goto err_free_mem; 291 } 292 293 keypad->clk = clk_get(&pdev->dev, "keypad"); 294 if (IS_ERR(keypad->clk)) { 295 dev_err(&pdev->dev, "failed to get keypad clk\n"); 296 error = PTR_ERR(keypad->clk); 297 goto err_unmap_base; 298 } 299 300 keypad->input_dev = input_dev; 301 keypad->row_shift = row_shift; 302 keypad->rows = pdata->rows; 303 keypad->cols = pdata->cols; 304 init_waitqueue_head(&keypad->wait); 305 306 input_dev->name = pdev->name; 307 input_dev->id.bustype = BUS_HOST; 308 input_dev->dev.parent = &pdev->dev; 309 input_set_drvdata(input_dev, keypad); 310 311 input_dev->open = samsung_keypad_open; 312 input_dev->close = samsung_keypad_close; 313 314 input_dev->evbit[0] = BIT_MASK(EV_KEY); 315 if (!pdata->no_autorepeat) 316 input_dev->evbit[0] |= BIT_MASK(EV_REP); 317 318 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 319 320 input_dev->keycode = keypad->keycodes; 321 input_dev->keycodesize = sizeof(keypad->keycodes[0]); 322 input_dev->keycodemax = pdata->rows << row_shift; 323 324 matrix_keypad_build_keymap(keymap_data, row_shift, 325 input_dev->keycode, input_dev->keybit); 326 327 keypad->irq = platform_get_irq(pdev, 0); 328 if (keypad->irq < 0) { 329 error = keypad->irq; 330 goto err_put_clk; 331 } 332 333 error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq, 334 IRQF_ONESHOT, dev_name(&pdev->dev), keypad); 335 if (error) { 336 dev_err(&pdev->dev, "failed to register keypad interrupt\n"); 337 goto err_put_clk; 338 } 339 340 error = input_register_device(keypad->input_dev); 341 if (error) 342 goto err_free_irq; 343 344 device_init_wakeup(&pdev->dev, pdata->wakeup); 345 platform_set_drvdata(pdev, keypad); 346 return 0; 347 348 err_free_irq: 349 free_irq(keypad->irq, keypad); 350 err_put_clk: 351 clk_put(keypad->clk); 352 err_unmap_base: 353 iounmap(keypad->base); 354 err_free_mem: 355 input_free_device(input_dev); 356 kfree(keypad); 357 358 return error; 359 } 360 361 static int __devexit samsung_keypad_remove(struct platform_device *pdev) 362 { 363 struct samsung_keypad *keypad = platform_get_drvdata(pdev); 364 365 device_init_wakeup(&pdev->dev, 0); 366 platform_set_drvdata(pdev, NULL); 367 368 input_unregister_device(keypad->input_dev); 369 370 /* 371 * It is safe to free IRQ after unregistering device because 372 * samsung_keypad_close will shut off interrupts. 373 */ 374 free_irq(keypad->irq, keypad); 375 376 clk_put(keypad->clk); 377 378 iounmap(keypad->base); 379 kfree(keypad); 380 381 return 0; 382 } 383 384 #ifdef CONFIG_PM 385 static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad, 386 bool enable) 387 { 388 struct device *dev = keypad->input_dev->dev.parent; 389 unsigned int val; 390 391 clk_enable(keypad->clk); 392 393 val = readl(keypad->base + SAMSUNG_KEYIFCON); 394 if (enable) { 395 val |= SAMSUNG_KEYIFCON_WAKEUPEN; 396 if (device_may_wakeup(dev)) 397 enable_irq_wake(keypad->irq); 398 } else { 399 val &= ~SAMSUNG_KEYIFCON_WAKEUPEN; 400 if (device_may_wakeup(dev)) 401 disable_irq_wake(keypad->irq); 402 } 403 writel(val, keypad->base + SAMSUNG_KEYIFCON); 404 405 clk_disable(keypad->clk); 406 } 407 408 static int samsung_keypad_suspend(struct device *dev) 409 { 410 struct platform_device *pdev = to_platform_device(dev); 411 struct samsung_keypad *keypad = platform_get_drvdata(pdev); 412 struct input_dev *input_dev = keypad->input_dev; 413 414 mutex_lock(&input_dev->mutex); 415 416 if (input_dev->users) 417 samsung_keypad_stop(keypad); 418 419 samsung_keypad_toggle_wakeup(keypad, true); 420 421 mutex_unlock(&input_dev->mutex); 422 423 return 0; 424 } 425 426 static int samsung_keypad_resume(struct device *dev) 427 { 428 struct platform_device *pdev = to_platform_device(dev); 429 struct samsung_keypad *keypad = platform_get_drvdata(pdev); 430 struct input_dev *input_dev = keypad->input_dev; 431 432 mutex_lock(&input_dev->mutex); 433 434 samsung_keypad_toggle_wakeup(keypad, false); 435 436 if (input_dev->users) 437 samsung_keypad_start(keypad); 438 439 mutex_unlock(&input_dev->mutex); 440 441 return 0; 442 } 443 444 static const struct dev_pm_ops samsung_keypad_pm_ops = { 445 .suspend = samsung_keypad_suspend, 446 .resume = samsung_keypad_resume, 447 }; 448 #endif 449 450 static struct platform_device_id samsung_keypad_driver_ids[] = { 451 { 452 .name = "samsung-keypad", 453 .driver_data = KEYPAD_TYPE_SAMSUNG, 454 }, { 455 .name = "s5pv210-keypad", 456 .driver_data = KEYPAD_TYPE_S5PV210, 457 }, 458 { }, 459 }; 460 MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids); 461 462 static struct platform_driver samsung_keypad_driver = { 463 .probe = samsung_keypad_probe, 464 .remove = __devexit_p(samsung_keypad_remove), 465 .driver = { 466 .name = "samsung-keypad", 467 .owner = THIS_MODULE, 468 #ifdef CONFIG_PM 469 .pm = &samsung_keypad_pm_ops, 470 #endif 471 }, 472 .id_table = samsung_keypad_driver_ids, 473 }; 474 475 static int __init samsung_keypad_init(void) 476 { 477 return platform_driver_register(&samsung_keypad_driver); 478 } 479 module_init(samsung_keypad_init); 480 481 static void __exit samsung_keypad_exit(void) 482 { 483 platform_driver_unregister(&samsung_keypad_driver); 484 } 485 module_exit(samsung_keypad_exit); 486 487 MODULE_DESCRIPTION("Samsung keypad driver"); 488 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 489 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>"); 490 MODULE_LICENSE("GPL"); 491 MODULE_ALIAS("platform:samsung-keypad"); 492