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