1 /* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com> 5 * Author: Sundar Iyer <sundar.iyer@stericsson.com> 6 * 7 * License Terms: GNU General Public License, version 2 8 * 9 * TC35893 MFD Keypad Controller driver 10 */ 11 12 #include <linux/module.h> 13 #include <linux/interrupt.h> 14 #include <linux/input.h> 15 #include <linux/platform_device.h> 16 #include <linux/input/matrix_keypad.h> 17 #include <linux/i2c.h> 18 #include <linux/slab.h> 19 #include <linux/mfd/tc3589x.h> 20 21 /* Maximum supported keypad matrix row/columns size */ 22 #define TC3589x_MAX_KPROW 8 23 #define TC3589x_MAX_KPCOL 12 24 25 /* keypad related Constants */ 26 #define TC3589x_MAX_DEBOUNCE_SETTLE 0xFF 27 #define DEDICATED_KEY_VAL 0xFF 28 29 /* Pull up/down masks */ 30 #define TC3589x_NO_PULL_MASK 0x0 31 #define TC3589x_PULL_DOWN_MASK 0x1 32 #define TC3589x_PULL_UP_MASK 0x2 33 #define TC3589x_PULLUP_ALL_MASK 0xAA 34 #define TC3589x_IO_PULL_VAL(index, mask) ((mask)<<((index)%4)*2)) 35 36 /* Bit masks for IOCFG register */ 37 #define IOCFG_BALLCFG 0x01 38 #define IOCFG_IG 0x08 39 40 #define KP_EVCODE_COL_MASK 0x0F 41 #define KP_EVCODE_ROW_MASK 0x70 42 #define KP_RELEASE_EVT_MASK 0x80 43 44 #define KP_ROW_SHIFT 4 45 46 #define KP_NO_VALID_KEY_MASK 0x7F 47 48 /* bit masks for RESTCTRL register */ 49 #define TC3589x_KBDRST 0x2 50 #define TC3589x_IRQRST 0x10 51 #define TC3589x_RESET_ALL 0x1B 52 53 /* KBDMFS register bit mask */ 54 #define TC3589x_KBDMFS_EN 0x1 55 56 /* CLKEN register bitmask */ 57 #define KPD_CLK_EN 0x1 58 59 /* RSTINTCLR register bit mask */ 60 #define IRQ_CLEAR 0x1 61 62 /* bit masks for keyboard interrupts*/ 63 #define TC3589x_EVT_LOSS_INT 0x8 64 #define TC3589x_EVT_INT 0x4 65 #define TC3589x_KBD_LOSS_INT 0x2 66 #define TC3589x_KBD_INT 0x1 67 68 /* bit masks for keyboard interrupt clear*/ 69 #define TC3589x_EVT_INT_CLR 0x2 70 #define TC3589x_KBD_INT_CLR 0x1 71 72 /** 73 * struct tc_keypad - data structure used by keypad driver 74 * @tc3589x: pointer to tc35893 75 * @input: pointer to input device object 76 * @board: keypad platform device 77 * @krow: number of rows 78 * @kcol: number of columns 79 * @keymap: matrix scan code table for keycodes 80 * @keypad_stopped: holds keypad status 81 */ 82 struct tc_keypad { 83 struct tc3589x *tc3589x; 84 struct input_dev *input; 85 const struct tc3589x_keypad_platform_data *board; 86 unsigned int krow; 87 unsigned int kcol; 88 unsigned short *keymap; 89 bool keypad_stopped; 90 }; 91 92 static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) 93 { 94 int ret; 95 struct tc3589x *tc3589x = keypad->tc3589x; 96 const struct tc3589x_keypad_platform_data *board = keypad->board; 97 98 /* validate platform configuration */ 99 if (board->kcol > TC3589x_MAX_KPCOL || board->krow > TC3589x_MAX_KPROW) 100 return -EINVAL; 101 102 /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ 103 ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, 104 (board->krow << KP_ROW_SHIFT) | board->kcol); 105 if (ret < 0) 106 return ret; 107 108 /* configure dedicated key config, no dedicated key selected */ 109 ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL); 110 if (ret < 0) 111 return ret; 112 113 ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL); 114 if (ret < 0) 115 return ret; 116 117 /* Configure settle time */ 118 ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, 119 board->settle_time); 120 if (ret < 0) 121 return ret; 122 123 /* Configure debounce time */ 124 ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, 125 board->debounce_period); 126 if (ret < 0) 127 return ret; 128 129 /* Start of initialise keypad GPIOs */ 130 ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG); 131 if (ret < 0) 132 return ret; 133 134 /* Configure pull-up resistors for all row GPIOs */ 135 ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB, 136 TC3589x_PULLUP_ALL_MASK); 137 if (ret < 0) 138 return ret; 139 140 ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB, 141 TC3589x_PULLUP_ALL_MASK); 142 if (ret < 0) 143 return ret; 144 145 /* Configure pull-up resistors for all column GPIOs */ 146 ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB, 147 TC3589x_PULLUP_ALL_MASK); 148 if (ret < 0) 149 return ret; 150 151 ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB, 152 TC3589x_PULLUP_ALL_MASK); 153 if (ret < 0) 154 return ret; 155 156 ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB, 157 TC3589x_PULLUP_ALL_MASK); 158 159 return ret; 160 } 161 162 #define TC35893_DATA_REGS 4 163 #define TC35893_KEYCODE_FIFO_EMPTY 0x7f 164 #define TC35893_KEYCODE_FIFO_CLEAR 0xff 165 #define TC35893_KEYPAD_ROW_SHIFT 0x3 166 167 static irqreturn_t tc3589x_keypad_irq(int irq, void *dev) 168 { 169 struct tc_keypad *keypad = dev; 170 struct tc3589x *tc3589x = keypad->tc3589x; 171 u8 i, row_index, col_index, kbd_code, up; 172 u8 code; 173 174 for (i = 0; i < TC35893_DATA_REGS * 2; i++) { 175 kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO); 176 177 /* loop till fifo is empty and no more keys are pressed */ 178 if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY || 179 kbd_code == TC35893_KEYCODE_FIFO_CLEAR) 180 continue; 181 182 /* valid key is found */ 183 col_index = kbd_code & KP_EVCODE_COL_MASK; 184 row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT; 185 code = MATRIX_SCAN_CODE(row_index, col_index, 186 TC35893_KEYPAD_ROW_SHIFT); 187 up = kbd_code & KP_RELEASE_EVT_MASK; 188 189 input_event(keypad->input, EV_MSC, MSC_SCAN, code); 190 input_report_key(keypad->input, keypad->keymap[code], !up); 191 input_sync(keypad->input); 192 } 193 194 /* clear IRQ */ 195 tc3589x_set_bits(tc3589x, TC3589x_KBDIC, 196 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); 197 /* enable IRQ */ 198 tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 199 0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); 200 201 return IRQ_HANDLED; 202 } 203 204 static int tc3589x_keypad_enable(struct tc_keypad *keypad) 205 { 206 struct tc3589x *tc3589x = keypad->tc3589x; 207 int ret; 208 209 /* pull the keypad module out of reset */ 210 ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0); 211 if (ret < 0) 212 return ret; 213 214 /* configure KBDMFS */ 215 ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN); 216 if (ret < 0) 217 return ret; 218 219 /* enable the keypad clock */ 220 ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN); 221 if (ret < 0) 222 return ret; 223 224 /* clear pending IRQs */ 225 ret = tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1); 226 if (ret < 0) 227 return ret; 228 229 /* enable the IRQs */ 230 ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0, 231 TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); 232 if (ret < 0) 233 return ret; 234 235 keypad->keypad_stopped = false; 236 237 return ret; 238 } 239 240 static int tc3589x_keypad_disable(struct tc_keypad *keypad) 241 { 242 struct tc3589x *tc3589x = keypad->tc3589x; 243 int ret; 244 245 /* clear IRQ */ 246 ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC, 247 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); 248 if (ret < 0) 249 return ret; 250 251 /* disable all interrupts */ 252 ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 253 ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0); 254 if (ret < 0) 255 return ret; 256 257 /* disable the keypad module */ 258 ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0); 259 if (ret < 0) 260 return ret; 261 262 /* put the keypad module into reset */ 263 ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1); 264 265 keypad->keypad_stopped = true; 266 267 return ret; 268 } 269 270 static int tc3589x_keypad_open(struct input_dev *input) 271 { 272 int error; 273 struct tc_keypad *keypad = input_get_drvdata(input); 274 275 /* enable the keypad module */ 276 error = tc3589x_keypad_enable(keypad); 277 if (error < 0) { 278 dev_err(&input->dev, "failed to enable keypad module\n"); 279 return error; 280 } 281 282 error = tc3589x_keypad_init_key_hardware(keypad); 283 if (error < 0) { 284 dev_err(&input->dev, "failed to configure keypad module\n"); 285 return error; 286 } 287 288 return 0; 289 } 290 291 static void tc3589x_keypad_close(struct input_dev *input) 292 { 293 struct tc_keypad *keypad = input_get_drvdata(input); 294 295 /* disable the keypad module */ 296 tc3589x_keypad_disable(keypad); 297 } 298 299 #ifdef CONFIG_OF 300 static const struct tc3589x_keypad_platform_data * 301 tc3589x_keypad_of_probe(struct device *dev) 302 { 303 struct device_node *np = dev->of_node; 304 struct tc3589x_keypad_platform_data *plat; 305 u32 cols, rows; 306 u32 debounce_ms; 307 int proplen; 308 309 if (!np) 310 return ERR_PTR(-ENODEV); 311 312 plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL); 313 if (!plat) 314 return ERR_PTR(-ENOMEM); 315 316 of_property_read_u32(np, "keypad,num-columns", &cols); 317 of_property_read_u32(np, "keypad,num-rows", &rows); 318 plat->kcol = (u8) cols; 319 plat->krow = (u8) rows; 320 if (!plat->krow || !plat->kcol || 321 plat->krow > TC_KPD_ROWS || plat->kcol > TC_KPD_COLUMNS) { 322 dev_err(dev, 323 "keypad columns/rows not properly specified (%ux%u)\n", 324 plat->kcol, plat->krow); 325 return ERR_PTR(-EINVAL); 326 } 327 328 if (!of_get_property(np, "linux,keymap", &proplen)) { 329 dev_err(dev, "property linux,keymap not found\n"); 330 return ERR_PTR(-ENOENT); 331 } 332 333 plat->no_autorepeat = of_property_read_bool(np, "linux,no-autorepeat"); 334 plat->enable_wakeup = of_property_read_bool(np, "linux,wakeup"); 335 336 /* The custom delay format is ms/16 */ 337 of_property_read_u32(np, "debounce-delay-ms", &debounce_ms); 338 if (debounce_ms) 339 plat->debounce_period = debounce_ms * 16; 340 else 341 plat->debounce_period = TC_KPD_DEBOUNCE_PERIOD; 342 343 plat->settle_time = TC_KPD_SETTLE_TIME; 344 /* FIXME: should be property of the IRQ resource? */ 345 plat->irqtype = IRQF_TRIGGER_FALLING; 346 347 return plat; 348 } 349 #else 350 static inline const struct tc3589x_keypad_platform_data * 351 tc3589x_keypad_of_probe(struct device *dev) 352 { 353 return ERR_PTR(-ENODEV); 354 } 355 #endif 356 357 358 static int tc3589x_keypad_probe(struct platform_device *pdev) 359 { 360 struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); 361 struct tc_keypad *keypad; 362 struct input_dev *input; 363 const struct tc3589x_keypad_platform_data *plat; 364 int error, irq; 365 366 plat = tc3589x->pdata->keypad; 367 if (!plat) { 368 plat = tc3589x_keypad_of_probe(&pdev->dev); 369 if (IS_ERR(plat)) { 370 dev_err(&pdev->dev, "invalid keypad platform data\n"); 371 return PTR_ERR(plat); 372 } 373 } 374 375 irq = platform_get_irq(pdev, 0); 376 if (irq < 0) 377 return irq; 378 379 keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL); 380 input = input_allocate_device(); 381 if (!keypad || !input) { 382 dev_err(&pdev->dev, "failed to allocate keypad memory\n"); 383 error = -ENOMEM; 384 goto err_free_mem; 385 } 386 387 keypad->board = plat; 388 keypad->input = input; 389 keypad->tc3589x = tc3589x; 390 391 input->id.bustype = BUS_I2C; 392 input->name = pdev->name; 393 input->dev.parent = &pdev->dev; 394 395 input->open = tc3589x_keypad_open; 396 input->close = tc3589x_keypad_close; 397 398 error = matrix_keypad_build_keymap(plat->keymap_data, NULL, 399 TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, 400 NULL, input); 401 if (error) { 402 dev_err(&pdev->dev, "Failed to build keymap\n"); 403 goto err_free_mem; 404 } 405 406 keypad->keymap = input->keycode; 407 408 input_set_capability(input, EV_MSC, MSC_SCAN); 409 if (!plat->no_autorepeat) 410 __set_bit(EV_REP, input->evbit); 411 412 input_set_drvdata(input, keypad); 413 414 error = request_threaded_irq(irq, NULL, 415 tc3589x_keypad_irq, plat->irqtype, 416 "tc3589x-keypad", keypad); 417 if (error < 0) { 418 dev_err(&pdev->dev, 419 "Could not allocate irq %d,error %d\n", 420 irq, error); 421 goto err_free_mem; 422 } 423 424 error = input_register_device(input); 425 if (error) { 426 dev_err(&pdev->dev, "Could not register input device\n"); 427 goto err_free_irq; 428 } 429 430 /* let platform decide if keypad is a wakeup source or not */ 431 device_init_wakeup(&pdev->dev, plat->enable_wakeup); 432 device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup); 433 434 platform_set_drvdata(pdev, keypad); 435 436 return 0; 437 438 err_free_irq: 439 free_irq(irq, keypad); 440 err_free_mem: 441 input_free_device(input); 442 kfree(keypad); 443 return error; 444 } 445 446 static int tc3589x_keypad_remove(struct platform_device *pdev) 447 { 448 struct tc_keypad *keypad = platform_get_drvdata(pdev); 449 int irq = platform_get_irq(pdev, 0); 450 451 if (!keypad->keypad_stopped) 452 tc3589x_keypad_disable(keypad); 453 454 free_irq(irq, keypad); 455 456 input_unregister_device(keypad->input); 457 458 kfree(keypad); 459 460 return 0; 461 } 462 463 #ifdef CONFIG_PM_SLEEP 464 static int tc3589x_keypad_suspend(struct device *dev) 465 { 466 struct platform_device *pdev = to_platform_device(dev); 467 struct tc_keypad *keypad = platform_get_drvdata(pdev); 468 int irq = platform_get_irq(pdev, 0); 469 470 /* keypad is already off; we do nothing */ 471 if (keypad->keypad_stopped) 472 return 0; 473 474 /* if device is not a wakeup source, disable it for powersave */ 475 if (!device_may_wakeup(&pdev->dev)) 476 tc3589x_keypad_disable(keypad); 477 else 478 enable_irq_wake(irq); 479 480 return 0; 481 } 482 483 static int tc3589x_keypad_resume(struct device *dev) 484 { 485 struct platform_device *pdev = to_platform_device(dev); 486 struct tc_keypad *keypad = platform_get_drvdata(pdev); 487 int irq = platform_get_irq(pdev, 0); 488 489 if (!keypad->keypad_stopped) 490 return 0; 491 492 /* enable the device to resume normal operations */ 493 if (!device_may_wakeup(&pdev->dev)) 494 tc3589x_keypad_enable(keypad); 495 else 496 disable_irq_wake(irq); 497 498 return 0; 499 } 500 #endif 501 502 static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, 503 tc3589x_keypad_suspend, tc3589x_keypad_resume); 504 505 static struct platform_driver tc3589x_keypad_driver = { 506 .driver = { 507 .name = "tc3589x-keypad", 508 .pm = &tc3589x_keypad_dev_pm_ops, 509 }, 510 .probe = tc3589x_keypad_probe, 511 .remove = tc3589x_keypad_remove, 512 }; 513 module_platform_driver(tc3589x_keypad_driver); 514 515 MODULE_LICENSE("GPL v2"); 516 MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer"); 517 MODULE_DESCRIPTION("TC35893 Keypad Driver"); 518 MODULE_ALIAS("platform:tc3589x-keypad"); 519