1 /* 2 * OMAP4 Keypad Driver 3 * 4 * Copyright (C) 2010 Texas Instruments 5 * 6 * Author: Abraham Arce <x0066660@ti.com> 7 * Initial Code: Syed Rafiuddin <rafiuddin.syed@ti.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24 #include <linux/module.h> 25 #include <linux/interrupt.h> 26 #include <linux/platform_device.h> 27 #include <linux/errno.h> 28 #include <linux/io.h> 29 #include <linux/of.h> 30 #include <linux/input.h> 31 #include <linux/input/matrix_keypad.h> 32 #include <linux/slab.h> 33 #include <linux/pm_runtime.h> 34 35 /* OMAP4 registers */ 36 #define OMAP4_KBD_REVISION 0x00 37 #define OMAP4_KBD_SYSCONFIG 0x10 38 #define OMAP4_KBD_SYSSTATUS 0x14 39 #define OMAP4_KBD_IRQSTATUS 0x18 40 #define OMAP4_KBD_IRQENABLE 0x1C 41 #define OMAP4_KBD_WAKEUPENABLE 0x20 42 #define OMAP4_KBD_PENDING 0x24 43 #define OMAP4_KBD_CTRL 0x28 44 #define OMAP4_KBD_DEBOUNCINGTIME 0x2C 45 #define OMAP4_KBD_LONGKEYTIME 0x30 46 #define OMAP4_KBD_TIMEOUT 0x34 47 #define OMAP4_KBD_STATEMACHINE 0x38 48 #define OMAP4_KBD_ROWINPUTS 0x3C 49 #define OMAP4_KBD_COLUMNOUTPUTS 0x40 50 #define OMAP4_KBD_FULLCODE31_0 0x44 51 #define OMAP4_KBD_FULLCODE63_32 0x48 52 53 /* OMAP4 bit definitions */ 54 #define OMAP4_DEF_IRQENABLE_EVENTEN BIT(0) 55 #define OMAP4_DEF_IRQENABLE_LONGKEY BIT(1) 56 #define OMAP4_DEF_WUP_EVENT_ENA BIT(0) 57 #define OMAP4_DEF_WUP_LONG_KEY_ENA BIT(1) 58 #define OMAP4_DEF_CTRL_NOSOFTMODE BIT(1) 59 #define OMAP4_DEF_CTRL_PTV_SHIFT 2 60 61 /* OMAP4 values */ 62 #define OMAP4_VAL_IRQDISABLE 0x0 63 #define OMAP4_VAL_DEBOUNCINGTIME 0x7 64 #define OMAP4_VAL_PVT 0x7 65 66 enum { 67 KBD_REVISION_OMAP4 = 0, 68 KBD_REVISION_OMAP5, 69 }; 70 71 struct omap4_keypad { 72 struct input_dev *input; 73 74 void __iomem *base; 75 bool irq_wake_enabled; 76 unsigned int irq; 77 78 unsigned int rows; 79 unsigned int cols; 80 u32 reg_offset; 81 u32 irqreg_offset; 82 unsigned int row_shift; 83 bool no_autorepeat; 84 unsigned char key_state[8]; 85 unsigned short *keymap; 86 }; 87 88 static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset) 89 { 90 return __raw_readl(keypad_data->base + 91 keypad_data->reg_offset + offset); 92 } 93 94 static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value) 95 { 96 __raw_writel(value, 97 keypad_data->base + keypad_data->reg_offset + offset); 98 } 99 100 static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset) 101 { 102 return __raw_readl(keypad_data->base + 103 keypad_data->irqreg_offset + offset); 104 } 105 106 static void kbd_write_irqreg(struct omap4_keypad *keypad_data, 107 u32 offset, u32 value) 108 { 109 __raw_writel(value, 110 keypad_data->base + keypad_data->irqreg_offset + offset); 111 } 112 113 114 /* Interrupt handlers */ 115 static irqreturn_t omap4_keypad_irq_handler(int irq, void *dev_id) 116 { 117 struct omap4_keypad *keypad_data = dev_id; 118 119 if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)) { 120 /* Disable interrupts */ 121 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, 122 OMAP4_VAL_IRQDISABLE); 123 return IRQ_WAKE_THREAD; 124 } 125 126 return IRQ_NONE; 127 } 128 129 static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id) 130 { 131 struct omap4_keypad *keypad_data = dev_id; 132 struct input_dev *input_dev = keypad_data->input; 133 unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)]; 134 unsigned int col, row, code, changed; 135 u32 *new_state = (u32 *) key_state; 136 137 *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0); 138 *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32); 139 140 for (row = 0; row < keypad_data->rows; row++) { 141 changed = key_state[row] ^ keypad_data->key_state[row]; 142 if (!changed) 143 continue; 144 145 for (col = 0; col < keypad_data->cols; col++) { 146 if (changed & (1 << col)) { 147 code = MATRIX_SCAN_CODE(row, col, 148 keypad_data->row_shift); 149 input_event(input_dev, EV_MSC, MSC_SCAN, code); 150 input_report_key(input_dev, 151 keypad_data->keymap[code], 152 key_state[row] & (1 << col)); 153 } 154 } 155 } 156 157 input_sync(input_dev); 158 159 memcpy(keypad_data->key_state, key_state, 160 sizeof(keypad_data->key_state)); 161 162 /* clear pending interrupts */ 163 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, 164 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); 165 166 /* enable interrupts */ 167 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, 168 OMAP4_DEF_IRQENABLE_EVENTEN | 169 OMAP4_DEF_IRQENABLE_LONGKEY); 170 171 return IRQ_HANDLED; 172 } 173 174 static int omap4_keypad_open(struct input_dev *input) 175 { 176 struct omap4_keypad *keypad_data = input_get_drvdata(input); 177 178 pm_runtime_get_sync(input->dev.parent); 179 180 disable_irq(keypad_data->irq); 181 182 kbd_writel(keypad_data, OMAP4_KBD_CTRL, 183 OMAP4_DEF_CTRL_NOSOFTMODE | 184 (OMAP4_VAL_PVT << OMAP4_DEF_CTRL_PTV_SHIFT)); 185 kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME, 186 OMAP4_VAL_DEBOUNCINGTIME); 187 /* clear pending interrupts */ 188 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, 189 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); 190 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, 191 OMAP4_DEF_IRQENABLE_EVENTEN | 192 OMAP4_DEF_IRQENABLE_LONGKEY); 193 kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 194 OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA); 195 196 enable_irq(keypad_data->irq); 197 198 return 0; 199 } 200 201 static void omap4_keypad_close(struct input_dev *input) 202 { 203 struct omap4_keypad *keypad_data = input_get_drvdata(input); 204 205 disable_irq(keypad_data->irq); 206 207 /* Disable interrupts */ 208 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, 209 OMAP4_VAL_IRQDISABLE); 210 211 /* clear pending interrupts */ 212 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, 213 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); 214 215 enable_irq(keypad_data->irq); 216 217 pm_runtime_put_sync(input->dev.parent); 218 } 219 220 static int omap4_keypad_parse_dt(struct device *dev, 221 struct omap4_keypad *keypad_data) 222 { 223 struct device_node *np = dev->of_node; 224 int err; 225 226 err = matrix_keypad_parse_of_params(dev, &keypad_data->rows, 227 &keypad_data->cols); 228 if (err) 229 return err; 230 231 if (of_get_property(np, "linux,input-no-autorepeat", NULL)) 232 keypad_data->no_autorepeat = true; 233 234 return 0; 235 } 236 237 static int omap4_keypad_probe(struct platform_device *pdev) 238 { 239 struct omap4_keypad *keypad_data; 240 struct input_dev *input_dev; 241 struct resource *res; 242 unsigned int max_keys; 243 int rev; 244 int irq; 245 int error; 246 247 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 248 if (!res) { 249 dev_err(&pdev->dev, "no base address specified\n"); 250 return -EINVAL; 251 } 252 253 irq = platform_get_irq(pdev, 0); 254 if (!irq) { 255 dev_err(&pdev->dev, "no keyboard irq assigned\n"); 256 return -EINVAL; 257 } 258 259 keypad_data = kzalloc(sizeof(struct omap4_keypad), GFP_KERNEL); 260 if (!keypad_data) { 261 dev_err(&pdev->dev, "keypad_data memory allocation failed\n"); 262 return -ENOMEM; 263 } 264 265 keypad_data->irq = irq; 266 267 error = omap4_keypad_parse_dt(&pdev->dev, keypad_data); 268 if (error) 269 goto err_free_keypad; 270 271 res = request_mem_region(res->start, resource_size(res), pdev->name); 272 if (!res) { 273 dev_err(&pdev->dev, "can't request mem region\n"); 274 error = -EBUSY; 275 goto err_free_keypad; 276 } 277 278 keypad_data->base = ioremap(res->start, resource_size(res)); 279 if (!keypad_data->base) { 280 dev_err(&pdev->dev, "can't ioremap mem resource\n"); 281 error = -ENOMEM; 282 goto err_release_mem; 283 } 284 285 286 /* 287 * Enable clocks for the keypad module so that we can read 288 * revision register. 289 */ 290 pm_runtime_enable(&pdev->dev); 291 error = pm_runtime_get_sync(&pdev->dev); 292 if (error) { 293 dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); 294 goto err_unmap; 295 } 296 rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION); 297 rev &= 0x03 << 30; 298 rev >>= 30; 299 switch (rev) { 300 case KBD_REVISION_OMAP4: 301 keypad_data->reg_offset = 0x00; 302 keypad_data->irqreg_offset = 0x00; 303 break; 304 case KBD_REVISION_OMAP5: 305 keypad_data->reg_offset = 0x10; 306 keypad_data->irqreg_offset = 0x0c; 307 break; 308 default: 309 dev_err(&pdev->dev, 310 "Keypad reports unsupported revision %d", rev); 311 error = -EINVAL; 312 goto err_pm_put_sync; 313 } 314 315 /* input device allocation */ 316 keypad_data->input = input_dev = input_allocate_device(); 317 if (!input_dev) { 318 error = -ENOMEM; 319 goto err_pm_put_sync; 320 } 321 322 input_dev->name = pdev->name; 323 input_dev->dev.parent = &pdev->dev; 324 input_dev->id.bustype = BUS_HOST; 325 input_dev->id.vendor = 0x0001; 326 input_dev->id.product = 0x0001; 327 input_dev->id.version = 0x0001; 328 329 input_dev->open = omap4_keypad_open; 330 input_dev->close = omap4_keypad_close; 331 332 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 333 if (!keypad_data->no_autorepeat) 334 __set_bit(EV_REP, input_dev->evbit); 335 336 input_set_drvdata(input_dev, keypad_data); 337 338 keypad_data->row_shift = get_count_order(keypad_data->cols); 339 max_keys = keypad_data->rows << keypad_data->row_shift; 340 keypad_data->keymap = kzalloc(max_keys * sizeof(keypad_data->keymap[0]), 341 GFP_KERNEL); 342 if (!keypad_data->keymap) { 343 dev_err(&pdev->dev, "Not enough memory for keymap\n"); 344 error = -ENOMEM; 345 goto err_free_input; 346 } 347 348 error = matrix_keypad_build_keymap(NULL, NULL, 349 keypad_data->rows, keypad_data->cols, 350 keypad_data->keymap, input_dev); 351 if (error) { 352 dev_err(&pdev->dev, "failed to build keymap\n"); 353 goto err_free_keymap; 354 } 355 356 error = request_threaded_irq(keypad_data->irq, omap4_keypad_irq_handler, 357 omap4_keypad_irq_thread_fn, 0, 358 "omap4-keypad", keypad_data); 359 if (error) { 360 dev_err(&pdev->dev, "failed to register interrupt\n"); 361 goto err_free_input; 362 } 363 364 device_init_wakeup(&pdev->dev, true); 365 pm_runtime_put_sync(&pdev->dev); 366 367 error = input_register_device(keypad_data->input); 368 if (error < 0) { 369 dev_err(&pdev->dev, "failed to register input device\n"); 370 goto err_pm_disable; 371 } 372 373 platform_set_drvdata(pdev, keypad_data); 374 return 0; 375 376 err_pm_disable: 377 pm_runtime_disable(&pdev->dev); 378 device_init_wakeup(&pdev->dev, false); 379 free_irq(keypad_data->irq, keypad_data); 380 err_free_keymap: 381 kfree(keypad_data->keymap); 382 err_free_input: 383 input_free_device(input_dev); 384 err_pm_put_sync: 385 pm_runtime_put_sync(&pdev->dev); 386 err_unmap: 387 iounmap(keypad_data->base); 388 err_release_mem: 389 release_mem_region(res->start, resource_size(res)); 390 err_free_keypad: 391 kfree(keypad_data); 392 return error; 393 } 394 395 static int omap4_keypad_remove(struct platform_device *pdev) 396 { 397 struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); 398 struct resource *res; 399 400 free_irq(keypad_data->irq, keypad_data); 401 402 pm_runtime_disable(&pdev->dev); 403 404 device_init_wakeup(&pdev->dev, false); 405 406 input_unregister_device(keypad_data->input); 407 408 iounmap(keypad_data->base); 409 410 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 411 release_mem_region(res->start, resource_size(res)); 412 413 kfree(keypad_data->keymap); 414 kfree(keypad_data); 415 416 return 0; 417 } 418 419 static const struct of_device_id omap_keypad_dt_match[] = { 420 { .compatible = "ti,omap4-keypad" }, 421 {}, 422 }; 423 MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); 424 425 #ifdef CONFIG_PM_SLEEP 426 static int omap4_keypad_suspend(struct device *dev) 427 { 428 struct platform_device *pdev = to_platform_device(dev); 429 struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); 430 int error; 431 432 if (device_may_wakeup(&pdev->dev)) { 433 error = enable_irq_wake(keypad_data->irq); 434 if (!error) 435 keypad_data->irq_wake_enabled = true; 436 } 437 438 return 0; 439 } 440 441 static int omap4_keypad_resume(struct device *dev) 442 { 443 struct platform_device *pdev = to_platform_device(dev); 444 struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); 445 446 if (device_may_wakeup(&pdev->dev) && keypad_data->irq_wake_enabled) { 447 disable_irq_wake(keypad_data->irq); 448 keypad_data->irq_wake_enabled = false; 449 } 450 451 return 0; 452 } 453 #endif 454 455 static SIMPLE_DEV_PM_OPS(omap4_keypad_pm_ops, 456 omap4_keypad_suspend, omap4_keypad_resume); 457 458 static struct platform_driver omap4_keypad_driver = { 459 .probe = omap4_keypad_probe, 460 .remove = omap4_keypad_remove, 461 .driver = { 462 .name = "omap4-keypad", 463 .pm = &omap4_keypad_pm_ops, 464 .of_match_table = omap_keypad_dt_match, 465 }, 466 }; 467 module_platform_driver(omap4_keypad_driver); 468 469 MODULE_AUTHOR("Texas Instruments"); 470 MODULE_DESCRIPTION("OMAP4 Keypad Driver"); 471 MODULE_LICENSE("GPL"); 472 MODULE_ALIAS("platform:omap4-keypad"); 473