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 static int tc3589x_keypad_probe(struct platform_device *pdev) 300 { 301 struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); 302 struct tc_keypad *keypad; 303 struct input_dev *input; 304 const struct tc3589x_keypad_platform_data *plat; 305 int error, irq; 306 307 plat = tc3589x->pdata->keypad; 308 if (!plat) { 309 dev_err(&pdev->dev, "invalid keypad platform data\n"); 310 return -EINVAL; 311 } 312 313 irq = platform_get_irq(pdev, 0); 314 if (irq < 0) 315 return irq; 316 317 keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL); 318 input = input_allocate_device(); 319 if (!keypad || !input) { 320 dev_err(&pdev->dev, "failed to allocate keypad memory\n"); 321 error = -ENOMEM; 322 goto err_free_mem; 323 } 324 325 keypad->board = plat; 326 keypad->input = input; 327 keypad->tc3589x = tc3589x; 328 329 input->id.bustype = BUS_I2C; 330 input->name = pdev->name; 331 input->dev.parent = &pdev->dev; 332 333 input->open = tc3589x_keypad_open; 334 input->close = tc3589x_keypad_close; 335 336 error = matrix_keypad_build_keymap(plat->keymap_data, NULL, 337 TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, 338 NULL, input); 339 if (error) { 340 dev_err(&pdev->dev, "Failed to build keymap\n"); 341 goto err_free_mem; 342 } 343 344 keypad->keymap = input->keycode; 345 346 input_set_capability(input, EV_MSC, MSC_SCAN); 347 if (!plat->no_autorepeat) 348 __set_bit(EV_REP, input->evbit); 349 350 input_set_drvdata(input, keypad); 351 352 error = request_threaded_irq(irq, NULL, 353 tc3589x_keypad_irq, plat->irqtype, 354 "tc3589x-keypad", keypad); 355 if (error < 0) { 356 dev_err(&pdev->dev, 357 "Could not allocate irq %d,error %d\n", 358 irq, error); 359 goto err_free_mem; 360 } 361 362 error = input_register_device(input); 363 if (error) { 364 dev_err(&pdev->dev, "Could not register input device\n"); 365 goto err_free_irq; 366 } 367 368 /* let platform decide if keypad is a wakeup source or not */ 369 device_init_wakeup(&pdev->dev, plat->enable_wakeup); 370 device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup); 371 372 platform_set_drvdata(pdev, keypad); 373 374 return 0; 375 376 err_free_irq: 377 free_irq(irq, keypad); 378 err_free_mem: 379 input_free_device(input); 380 kfree(keypad); 381 return error; 382 } 383 384 static int tc3589x_keypad_remove(struct platform_device *pdev) 385 { 386 struct tc_keypad *keypad = platform_get_drvdata(pdev); 387 int irq = platform_get_irq(pdev, 0); 388 389 if (!keypad->keypad_stopped) 390 tc3589x_keypad_disable(keypad); 391 392 free_irq(irq, keypad); 393 394 input_unregister_device(keypad->input); 395 396 kfree(keypad); 397 398 return 0; 399 } 400 401 #ifdef CONFIG_PM_SLEEP 402 static int tc3589x_keypad_suspend(struct device *dev) 403 { 404 struct platform_device *pdev = to_platform_device(dev); 405 struct tc_keypad *keypad = platform_get_drvdata(pdev); 406 int irq = platform_get_irq(pdev, 0); 407 408 /* keypad is already off; we do nothing */ 409 if (keypad->keypad_stopped) 410 return 0; 411 412 /* if device is not a wakeup source, disable it for powersave */ 413 if (!device_may_wakeup(&pdev->dev)) 414 tc3589x_keypad_disable(keypad); 415 else 416 enable_irq_wake(irq); 417 418 return 0; 419 } 420 421 static int tc3589x_keypad_resume(struct device *dev) 422 { 423 struct platform_device *pdev = to_platform_device(dev); 424 struct tc_keypad *keypad = platform_get_drvdata(pdev); 425 int irq = platform_get_irq(pdev, 0); 426 427 if (!keypad->keypad_stopped) 428 return 0; 429 430 /* enable the device to resume normal operations */ 431 if (!device_may_wakeup(&pdev->dev)) 432 tc3589x_keypad_enable(keypad); 433 else 434 disable_irq_wake(irq); 435 436 return 0; 437 } 438 #endif 439 440 static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, 441 tc3589x_keypad_suspend, tc3589x_keypad_resume); 442 443 static struct platform_driver tc3589x_keypad_driver = { 444 .driver = { 445 .name = "tc3589x-keypad", 446 .owner = THIS_MODULE, 447 .pm = &tc3589x_keypad_dev_pm_ops, 448 }, 449 .probe = tc3589x_keypad_probe, 450 .remove = tc3589x_keypad_remove, 451 }; 452 module_platform_driver(tc3589x_keypad_driver); 453 454 MODULE_LICENSE("GPL v2"); 455 MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer"); 456 MODULE_DESCRIPTION("TC35893 Keypad Driver"); 457 MODULE_ALIAS("platform:tc3589x-keypad"); 458