| Trilok Soni | 39325b5 | 2011-05-19 10:54:04 +0530 | [diff] [blame] | 1 | /* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. | 
|  | 2 | * | 
|  | 3 | * This program is free software; you can redistribute it and/or modify | 
|  | 4 | * it under the terms of the GNU General Public License version 2 and | 
|  | 5 | * only version 2 as published by the Free Software Foundation. | 
|  | 6 | * | 
|  | 7 | * This program is distributed in the hope that it will be useful, | 
|  | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 10 | * GNU General Public License for more details. | 
|  | 11 | */ | 
|  | 12 |  | 
|  | 13 | #include <linux/module.h> | 
|  | 14 | #include <linux/platform_device.h> | 
|  | 15 | #include <linux/kernel.h> | 
|  | 16 | #include <linux/interrupt.h> | 
|  | 17 | #include <linux/slab.h> | 
|  | 18 | #include <linux/input.h> | 
|  | 19 | #include <linux/bitops.h> | 
|  | 20 | #include <linux/delay.h> | 
|  | 21 | #include <linux/mutex.h> | 
|  | 22 |  | 
|  | 23 | #include <linux/mfd/pm8xxx/core.h> | 
|  | 24 | #include <linux/mfd/pm8xxx/gpio.h> | 
|  | 25 | #include <linux/input/pmic8xxx-keypad.h> | 
|  | 26 |  | 
|  | 27 | #define PM8XXX_MAX_ROWS		18 | 
|  | 28 | #define PM8XXX_MAX_COLS		8 | 
|  | 29 | #define PM8XXX_ROW_SHIFT	3 | 
|  | 30 | #define PM8XXX_MATRIX_MAX_SIZE	(PM8XXX_MAX_ROWS * PM8XXX_MAX_COLS) | 
|  | 31 |  | 
|  | 32 | #define PM8XXX_MIN_ROWS		5 | 
|  | 33 | #define PM8XXX_MIN_COLS		5 | 
|  | 34 |  | 
|  | 35 | #define MAX_SCAN_DELAY		128 | 
|  | 36 | #define MIN_SCAN_DELAY		1 | 
|  | 37 |  | 
|  | 38 | /* in nanoseconds */ | 
|  | 39 | #define MAX_ROW_HOLD_DELAY	122000 | 
|  | 40 | #define MIN_ROW_HOLD_DELAY	30500 | 
|  | 41 |  | 
|  | 42 | #define MAX_DEBOUNCE_TIME	20 | 
|  | 43 | #define MIN_DEBOUNCE_TIME	5 | 
|  | 44 |  | 
|  | 45 | #define KEYP_CTRL			0x148 | 
|  | 46 |  | 
|  | 47 | #define KEYP_CTRL_EVNTS			BIT(0) | 
|  | 48 | #define KEYP_CTRL_EVNTS_MASK		0x3 | 
|  | 49 |  | 
|  | 50 | #define KEYP_CTRL_SCAN_COLS_SHIFT	5 | 
|  | 51 | #define KEYP_CTRL_SCAN_COLS_MIN		5 | 
|  | 52 | #define KEYP_CTRL_SCAN_COLS_BITS	0x3 | 
|  | 53 |  | 
|  | 54 | #define KEYP_CTRL_SCAN_ROWS_SHIFT	2 | 
|  | 55 | #define KEYP_CTRL_SCAN_ROWS_MIN		5 | 
|  | 56 | #define KEYP_CTRL_SCAN_ROWS_BITS	0x7 | 
|  | 57 |  | 
|  | 58 | #define KEYP_CTRL_KEYP_EN		BIT(7) | 
|  | 59 |  | 
|  | 60 | #define KEYP_SCAN			0x149 | 
|  | 61 |  | 
|  | 62 | #define KEYP_SCAN_READ_STATE		BIT(0) | 
|  | 63 | #define KEYP_SCAN_DBOUNCE_SHIFT		1 | 
|  | 64 | #define KEYP_SCAN_PAUSE_SHIFT		3 | 
|  | 65 | #define KEYP_SCAN_ROW_HOLD_SHIFT	6 | 
|  | 66 |  | 
|  | 67 | #define KEYP_TEST			0x14A | 
|  | 68 |  | 
|  | 69 | #define KEYP_TEST_CLEAR_RECENT_SCAN	BIT(6) | 
|  | 70 | #define KEYP_TEST_CLEAR_OLD_SCAN	BIT(5) | 
|  | 71 | #define KEYP_TEST_READ_RESET		BIT(4) | 
|  | 72 | #define KEYP_TEST_DTEST_EN		BIT(3) | 
|  | 73 | #define KEYP_TEST_ABORT_READ		BIT(0) | 
|  | 74 |  | 
|  | 75 | #define KEYP_TEST_DBG_SELECT_SHIFT	1 | 
|  | 76 |  | 
|  | 77 | /* bits of these registers represent | 
|  | 78 | * '0' for key press | 
|  | 79 | * '1' for key release | 
|  | 80 | */ | 
|  | 81 | #define KEYP_RECENT_DATA		0x14B | 
|  | 82 | #define KEYP_OLD_DATA			0x14C | 
|  | 83 |  | 
|  | 84 | #define KEYP_CLOCK_FREQ			32768 | 
|  | 85 |  | 
|  | 86 | /** | 
|  | 87 | * struct pmic8xxx_kp - internal keypad data structure | 
|  | 88 | * @pdata - keypad platform data pointer | 
|  | 89 | * @input - input device pointer for keypad | 
|  | 90 | * @key_sense_irq - key press/release irq number | 
|  | 91 | * @key_stuck_irq - key stuck notification irq number | 
|  | 92 | * @keycodes - array to hold the key codes | 
|  | 93 | * @dev - parent device pointer | 
|  | 94 | * @keystate - present key press/release state | 
|  | 95 | * @stuckstate - present state when key stuck irq | 
|  | 96 | * @ctrl_reg - control register value | 
|  | 97 | */ | 
|  | 98 | struct pmic8xxx_kp { | 
|  | 99 | const struct pm8xxx_keypad_platform_data *pdata; | 
|  | 100 | struct input_dev *input; | 
|  | 101 | int key_sense_irq; | 
|  | 102 | int key_stuck_irq; | 
|  | 103 |  | 
|  | 104 | unsigned short keycodes[PM8XXX_MATRIX_MAX_SIZE]; | 
|  | 105 |  | 
|  | 106 | struct device *dev; | 
|  | 107 | u16 keystate[PM8XXX_MAX_ROWS]; | 
|  | 108 | u16 stuckstate[PM8XXX_MAX_ROWS]; | 
|  | 109 |  | 
|  | 110 | u8 ctrl_reg; | 
|  | 111 | }; | 
|  | 112 |  | 
|  | 113 | static int pmic8xxx_kp_write_u8(struct pmic8xxx_kp *kp, | 
|  | 114 | u8 data, u16 reg) | 
|  | 115 | { | 
|  | 116 | int rc; | 
|  | 117 |  | 
|  | 118 | rc = pm8xxx_writeb(kp->dev->parent, reg, data); | 
|  | 119 | return rc; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | static int pmic8xxx_kp_read(struct pmic8xxx_kp *kp, | 
|  | 123 | u8 *data, u16 reg, unsigned num_bytes) | 
|  | 124 | { | 
|  | 125 | int rc; | 
|  | 126 |  | 
|  | 127 | rc = pm8xxx_read_buf(kp->dev->parent, reg, data, num_bytes); | 
|  | 128 | return rc; | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 | static int pmic8xxx_kp_read_u8(struct pmic8xxx_kp *kp, | 
|  | 132 | u8 *data, u16 reg) | 
|  | 133 | { | 
|  | 134 | int rc; | 
|  | 135 |  | 
|  | 136 | rc = pmic8xxx_kp_read(kp, data, reg, 1); | 
|  | 137 | return rc; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) | 
|  | 141 | { | 
|  | 142 | /* all keys pressed on that particular row? */ | 
|  | 143 | if (col == 0x00) | 
|  | 144 | return 1 << kp->pdata->num_cols; | 
|  | 145 | else | 
|  | 146 | return col & ((1 << kp->pdata->num_cols) - 1); | 
|  | 147 | } | 
|  | 148 |  | 
|  | 149 | /* | 
|  | 150 | * Synchronous read protocol for RevB0 onwards: | 
|  | 151 | * | 
|  | 152 | * 1. Write '1' to ReadState bit in KEYP_SCAN register | 
|  | 153 | * 2. Wait 2*32KHz clocks, so that HW can successfully enter read mode | 
|  | 154 | *    synchronously | 
|  | 155 | * 3. Read rows in old array first if events are more than one | 
|  | 156 | * 4. Read rows in recent array | 
|  | 157 | * 5. Wait 4*32KHz clocks | 
|  | 158 | * 6. Write '0' to ReadState bit of KEYP_SCAN register so that hw can | 
|  | 159 | *    synchronously exit read mode. | 
|  | 160 | */ | 
|  | 161 | static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) | 
|  | 162 | { | 
|  | 163 | int rc; | 
|  | 164 | u8 scan_val; | 
|  | 165 |  | 
|  | 166 | rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); | 
|  | 167 | if (rc < 0) { | 
|  | 168 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | 
|  | 169 | return rc; | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | scan_val |= 0x1; | 
|  | 173 |  | 
|  | 174 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | 
|  | 175 | if (rc < 0) { | 
|  | 176 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | 
|  | 177 | return rc; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | /* 2 * 32KHz clocks */ | 
|  | 181 | udelay((2 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | 
|  | 182 |  | 
|  | 183 | return rc; | 
|  | 184 | } | 
|  | 185 |  | 
|  | 186 | static int pmic8xxx_kp_read_data(struct pmic8xxx_kp *kp, u16 *state, | 
|  | 187 | u16 data_reg, int read_rows) | 
|  | 188 | { | 
|  | 189 | int rc, row; | 
|  | 190 | u8 new_data[PM8XXX_MAX_ROWS]; | 
|  | 191 |  | 
|  | 192 | rc = pmic8xxx_kp_read(kp, new_data, data_reg, read_rows); | 
|  | 193 | if (rc) | 
|  | 194 | return rc; | 
|  | 195 |  | 
|  | 196 | for (row = 0; row < kp->pdata->num_rows; row++) { | 
|  | 197 | dev_dbg(kp->dev, "new_data[%d] = %d\n", row, | 
|  | 198 | new_data[row]); | 
|  | 199 | state[row] = pmic8xxx_col_state(kp, new_data[row]); | 
|  | 200 | } | 
|  | 201 |  | 
|  | 202 | return rc; | 
|  | 203 | } | 
|  | 204 |  | 
|  | 205 | static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | 
|  | 206 | u16 *old_state) | 
|  | 207 | { | 
|  | 208 | int rc, read_rows; | 
|  | 209 | u8 scan_val; | 
|  | 210 |  | 
|  | 211 | if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) | 
|  | 212 | read_rows = PM8XXX_MIN_ROWS; | 
|  | 213 | else | 
|  | 214 | read_rows = kp->pdata->num_rows; | 
|  | 215 |  | 
|  | 216 | pmic8xxx_chk_sync_read(kp); | 
|  | 217 |  | 
|  | 218 | if (old_state) { | 
|  | 219 | rc = pmic8xxx_kp_read_data(kp, old_state, KEYP_OLD_DATA, | 
|  | 220 | read_rows); | 
|  | 221 | if (rc < 0) { | 
|  | 222 | dev_err(kp->dev, | 
|  | 223 | "Error reading KEYP_OLD_DATA, rc=%d\n", rc); | 
|  | 224 | return rc; | 
|  | 225 | } | 
|  | 226 | } | 
|  | 227 |  | 
|  | 228 | rc = pmic8xxx_kp_read_data(kp, new_state, KEYP_RECENT_DATA, | 
|  | 229 | read_rows); | 
|  | 230 | if (rc < 0) { | 
|  | 231 | dev_err(kp->dev, | 
|  | 232 | "Error reading KEYP_RECENT_DATA, rc=%d\n", rc); | 
|  | 233 | return rc; | 
|  | 234 | } | 
|  | 235 |  | 
|  | 236 | /* 4 * 32KHz clocks */ | 
|  | 237 | udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | 
|  | 238 |  | 
|  | 239 | rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); | 
|  | 240 | if (rc < 0) { | 
|  | 241 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | 
|  | 242 | return rc; | 
|  | 243 | } | 
|  | 244 |  | 
|  | 245 | scan_val &= 0xFE; | 
|  | 246 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | 
|  | 247 | if (rc < 0) | 
|  | 248 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | 
|  | 249 |  | 
|  | 250 | return rc; | 
|  | 251 | } | 
|  | 252 |  | 
|  | 253 | static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | 
|  | 254 | u16 *old_state) | 
|  | 255 | { | 
|  | 256 | int row, col, code; | 
|  | 257 |  | 
|  | 258 | for (row = 0; row < kp->pdata->num_rows; row++) { | 
|  | 259 | int bits_changed = new_state[row] ^ old_state[row]; | 
|  | 260 |  | 
|  | 261 | if (!bits_changed) | 
|  | 262 | continue; | 
|  | 263 |  | 
|  | 264 | for (col = 0; col < kp->pdata->num_cols; col++) { | 
|  | 265 | if (!(bits_changed & (1 << col))) | 
|  | 266 | continue; | 
|  | 267 |  | 
|  | 268 | dev_dbg(kp->dev, "key [%d:%d] %s\n", row, col, | 
|  | 269 | !(new_state[row] & (1 << col)) ? | 
|  | 270 | "pressed" : "released"); | 
|  | 271 |  | 
|  | 272 | code = MATRIX_SCAN_CODE(row, col, PM8XXX_ROW_SHIFT); | 
|  | 273 |  | 
|  | 274 | input_event(kp->input, EV_MSC, MSC_SCAN, code); | 
|  | 275 | input_report_key(kp->input, | 
|  | 276 | kp->keycodes[code], | 
|  | 277 | !(new_state[row] & (1 << col))); | 
|  | 278 |  | 
|  | 279 | input_sync(kp->input); | 
|  | 280 | } | 
|  | 281 | } | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) | 
|  | 285 | { | 
|  | 286 | int row, found_first = -1; | 
|  | 287 | u16 check, row_state; | 
|  | 288 |  | 
|  | 289 | check = 0; | 
|  | 290 | for (row = 0; row < kp->pdata->num_rows; row++) { | 
|  | 291 | row_state = (~new_state[row]) & | 
|  | 292 | ((1 << kp->pdata->num_cols) - 1); | 
|  | 293 |  | 
|  | 294 | if (hweight16(row_state) > 1) { | 
|  | 295 | if (found_first == -1) | 
|  | 296 | found_first = row; | 
|  | 297 | if (check & row_state) { | 
|  | 298 | dev_dbg(kp->dev, "detected ghost key on row[%d]" | 
|  | 299 | " and row[%d]\n", found_first, row); | 
|  | 300 | return true; | 
|  | 301 | } | 
|  | 302 | } | 
|  | 303 | check |= row_state; | 
|  | 304 | } | 
|  | 305 | return false; | 
|  | 306 | } | 
|  | 307 |  | 
|  | 308 | static int pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, unsigned int events) | 
|  | 309 | { | 
|  | 310 | u16 new_state[PM8XXX_MAX_ROWS]; | 
|  | 311 | u16 old_state[PM8XXX_MAX_ROWS]; | 
|  | 312 | int rc; | 
|  | 313 |  | 
|  | 314 | switch (events) { | 
|  | 315 | case 0x1: | 
|  | 316 | rc = pmic8xxx_kp_read_matrix(kp, new_state, NULL); | 
|  | 317 | if (rc < 0) | 
|  | 318 | return rc; | 
|  | 319 |  | 
|  | 320 | /* detecting ghost key is not an error */ | 
|  | 321 | if (pmic8xxx_detect_ghost_keys(kp, new_state)) | 
|  | 322 | return 0; | 
|  | 323 | __pmic8xxx_kp_scan_matrix(kp, new_state, kp->keystate); | 
|  | 324 | memcpy(kp->keystate, new_state, sizeof(new_state)); | 
|  | 325 | break; | 
|  | 326 | case 0x3: /* two events - eventcounter is gray-coded */ | 
|  | 327 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | 
|  | 328 | if (rc < 0) | 
|  | 329 | return rc; | 
|  | 330 |  | 
|  | 331 | __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); | 
|  | 332 | __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); | 
|  | 333 | memcpy(kp->keystate, new_state, sizeof(new_state)); | 
|  | 334 | break; | 
|  | 335 | case 0x2: | 
|  | 336 | dev_dbg(kp->dev, "Some key events were lost\n"); | 
|  | 337 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | 
|  | 338 | if (rc < 0) | 
|  | 339 | return rc; | 
|  | 340 | __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); | 
|  | 341 | __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); | 
|  | 342 | memcpy(kp->keystate, new_state, sizeof(new_state)); | 
|  | 343 | break; | 
|  | 344 | default: | 
|  | 345 | rc = -EINVAL; | 
|  | 346 | } | 
|  | 347 | return rc; | 
|  | 348 | } | 
|  | 349 |  | 
|  | 350 | /* | 
|  | 351 | * NOTE: We are reading recent and old data registers blindly | 
|  | 352 | * whenever key-stuck interrupt happens, because events counter doesn't | 
|  | 353 | * get updated when this interrupt happens due to key stuck doesn't get | 
|  | 354 | * considered as key state change. | 
|  | 355 | * | 
|  | 356 | * We are not using old data register contents after they are being read | 
|  | 357 | * because it might report the key which was pressed before the key being stuck | 
|  | 358 | * as stuck key because it's pressed status is stored in the old data | 
|  | 359 | * register. | 
|  | 360 | */ | 
|  | 361 | static irqreturn_t pmic8xxx_kp_stuck_irq(int irq, void *data) | 
|  | 362 | { | 
|  | 363 | u16 new_state[PM8XXX_MAX_ROWS]; | 
|  | 364 | u16 old_state[PM8XXX_MAX_ROWS]; | 
|  | 365 | int rc; | 
|  | 366 | struct pmic8xxx_kp *kp = data; | 
|  | 367 |  | 
|  | 368 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | 
|  | 369 | if (rc < 0) { | 
|  | 370 | dev_err(kp->dev, "failed to read keypad matrix\n"); | 
|  | 371 | return IRQ_HANDLED; | 
|  | 372 | } | 
|  | 373 |  | 
|  | 374 | __pmic8xxx_kp_scan_matrix(kp, new_state, kp->stuckstate); | 
|  | 375 |  | 
|  | 376 | return IRQ_HANDLED; | 
|  | 377 | } | 
|  | 378 |  | 
|  | 379 | static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) | 
|  | 380 | { | 
|  | 381 | struct pmic8xxx_kp *kp = data; | 
|  | 382 | u8 ctrl_val, events; | 
|  | 383 | int rc; | 
|  | 384 |  | 
|  | 385 | rc = pmic8xxx_kp_read(kp, &ctrl_val, KEYP_CTRL, 1); | 
|  | 386 | if (rc < 0) { | 
|  | 387 | dev_err(kp->dev, "failed to read keyp_ctrl register\n"); | 
|  | 388 | return IRQ_HANDLED; | 
|  | 389 | } | 
|  | 390 |  | 
|  | 391 | events = ctrl_val & KEYP_CTRL_EVNTS_MASK; | 
|  | 392 |  | 
|  | 393 | rc = pmic8xxx_kp_scan_matrix(kp, events); | 
|  | 394 | if (rc < 0) | 
|  | 395 | dev_err(kp->dev, "failed to scan matrix\n"); | 
|  | 396 |  | 
|  | 397 | return IRQ_HANDLED; | 
|  | 398 | } | 
|  | 399 |  | 
|  | 400 | static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | 
|  | 401 | { | 
|  | 402 | int bits, rc, cycles; | 
|  | 403 | u8 scan_val = 0, ctrl_val = 0; | 
|  | 404 | static const u8 row_bits[] = { | 
|  | 405 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, | 
|  | 406 | }; | 
|  | 407 |  | 
|  | 408 | /* Find column bits */ | 
|  | 409 | if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) | 
|  | 410 | bits = 0; | 
|  | 411 | else | 
|  | 412 | bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; | 
|  | 413 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << | 
|  | 414 | KEYP_CTRL_SCAN_COLS_SHIFT; | 
|  | 415 |  | 
|  | 416 | /* Find row bits */ | 
|  | 417 | if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) | 
|  | 418 | bits = 0; | 
|  | 419 | else | 
|  | 420 | bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; | 
|  | 421 |  | 
|  | 422 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); | 
|  | 423 |  | 
|  | 424 | rc = pmic8xxx_kp_write_u8(kp, ctrl_val, KEYP_CTRL); | 
|  | 425 | if (rc < 0) { | 
|  | 426 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | 
|  | 427 | return rc; | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | bits = (kp->pdata->debounce_ms / 5) - 1; | 
|  | 431 |  | 
|  | 432 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); | 
|  | 433 |  | 
|  | 434 | bits = fls(kp->pdata->scan_delay_ms) - 1; | 
|  | 435 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); | 
|  | 436 |  | 
|  | 437 | /* Row hold time is a multiple of 32KHz cycles. */ | 
|  | 438 | cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; | 
|  | 439 |  | 
|  | 440 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); | 
|  | 441 |  | 
|  | 442 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | 
|  | 443 | if (rc) | 
|  | 444 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | 
|  | 445 |  | 
|  | 446 | return rc; | 
|  | 447 |  | 
|  | 448 | } | 
|  | 449 |  | 
|  | 450 | static int  __devinit pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, | 
|  | 451 | struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config) | 
|  | 452 | { | 
|  | 453 | int	rc, i; | 
|  | 454 |  | 
|  | 455 | if (gpio_start < 0 || num_gpios < 0) | 
|  | 456 | return -EINVAL; | 
|  | 457 |  | 
|  | 458 | for (i = 0; i < num_gpios; i++) { | 
|  | 459 | rc = pm8xxx_gpio_config(gpio_start + i, gpio_config); | 
|  | 460 | if (rc) { | 
|  | 461 | dev_err(kp->dev, "%s: FAIL pm8xxx_gpio_config():" | 
|  | 462 | "for PM GPIO [%d] rc=%d.\n", | 
|  | 463 | __func__, gpio_start + i, rc); | 
|  | 464 | return rc; | 
|  | 465 | } | 
|  | 466 | } | 
|  | 467 |  | 
|  | 468 | return 0; | 
|  | 469 | } | 
|  | 470 |  | 
|  | 471 | static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) | 
|  | 472 | { | 
|  | 473 | int rc; | 
|  | 474 |  | 
|  | 475 | kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; | 
|  | 476 |  | 
|  | 477 | rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); | 
|  | 478 | if (rc < 0) | 
|  | 479 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | 
|  | 480 |  | 
|  | 481 | return rc; | 
|  | 482 | } | 
|  | 483 |  | 
|  | 484 | static int pmic8xxx_kp_disable(struct pmic8xxx_kp *kp) | 
|  | 485 | { | 
|  | 486 | int rc; | 
|  | 487 |  | 
|  | 488 | kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; | 
|  | 489 |  | 
|  | 490 | rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); | 
|  | 491 | if (rc < 0) | 
|  | 492 | return rc; | 
|  | 493 |  | 
|  | 494 | return rc; | 
|  | 495 | } | 
|  | 496 |  | 
|  | 497 | static int pmic8xxx_kp_open(struct input_dev *dev) | 
|  | 498 | { | 
|  | 499 | struct pmic8xxx_kp *kp = input_get_drvdata(dev); | 
|  | 500 |  | 
|  | 501 | return pmic8xxx_kp_enable(kp); | 
|  | 502 | } | 
|  | 503 |  | 
|  | 504 | static void pmic8xxx_kp_close(struct input_dev *dev) | 
|  | 505 | { | 
|  | 506 | struct pmic8xxx_kp *kp = input_get_drvdata(dev); | 
|  | 507 |  | 
|  | 508 | pmic8xxx_kp_disable(kp); | 
|  | 509 | } | 
|  | 510 |  | 
|  | 511 | /* | 
|  | 512 | * keypad controller should be initialized in the following sequence | 
|  | 513 | * only, otherwise it might get into FSM stuck state. | 
|  | 514 | * | 
|  | 515 | * - Initialize keypad control parameters, like no. of rows, columns, | 
|  | 516 | *   timing values etc., | 
|  | 517 | * - configure rows and column gpios pull up/down. | 
|  | 518 | * - set irq edge type. | 
|  | 519 | * - enable the keypad controller. | 
|  | 520 | */ | 
|  | 521 | static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) | 
|  | 522 | { | 
| Samuel Ortiz | 1d08382 | 2011-06-08 11:03:23 +0200 | [diff] [blame] | 523 | const struct pm8xxx_keypad_platform_data *pdata = | 
|  | 524 | dev_get_platdata(&pdev->dev); | 
| Trilok Soni | 39325b5 | 2011-05-19 10:54:04 +0530 | [diff] [blame] | 525 | const struct matrix_keymap_data *keymap_data; | 
|  | 526 | struct pmic8xxx_kp *kp; | 
|  | 527 | int rc; | 
|  | 528 | u8 ctrl_val; | 
|  | 529 |  | 
|  | 530 | struct pm_gpio kypd_drv = { | 
|  | 531 | .direction	= PM_GPIO_DIR_OUT, | 
|  | 532 | .output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN, | 
|  | 533 | .output_value	= 0, | 
|  | 534 | .pull		= PM_GPIO_PULL_NO, | 
|  | 535 | .vin_sel	= PM_GPIO_VIN_S3, | 
|  | 536 | .out_strength	= PM_GPIO_STRENGTH_LOW, | 
|  | 537 | .function	= PM_GPIO_FUNC_1, | 
|  | 538 | .inv_int_pol	= 1, | 
|  | 539 | }; | 
|  | 540 |  | 
|  | 541 | struct pm_gpio kypd_sns = { | 
|  | 542 | .direction	= PM_GPIO_DIR_IN, | 
|  | 543 | .pull		= PM_GPIO_PULL_UP_31P5, | 
|  | 544 | .vin_sel	= PM_GPIO_VIN_S3, | 
|  | 545 | .out_strength	= PM_GPIO_STRENGTH_NO, | 
|  | 546 | .function	= PM_GPIO_FUNC_NORMAL, | 
|  | 547 | .inv_int_pol	= 1, | 
|  | 548 | }; | 
|  | 549 |  | 
|  | 550 |  | 
|  | 551 | if (!pdata || !pdata->num_cols || !pdata->num_rows || | 
|  | 552 | pdata->num_cols > PM8XXX_MAX_COLS || | 
|  | 553 | pdata->num_rows > PM8XXX_MAX_ROWS || | 
|  | 554 | pdata->num_cols < PM8XXX_MIN_COLS) { | 
|  | 555 | dev_err(&pdev->dev, "invalid platform data\n"); | 
|  | 556 | return -EINVAL; | 
|  | 557 | } | 
|  | 558 |  | 
|  | 559 | if (!pdata->scan_delay_ms || | 
|  | 560 | pdata->scan_delay_ms > MAX_SCAN_DELAY || | 
|  | 561 | pdata->scan_delay_ms < MIN_SCAN_DELAY || | 
|  | 562 | !is_power_of_2(pdata->scan_delay_ms)) { | 
|  | 563 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | 
|  | 564 | return -EINVAL; | 
|  | 565 | } | 
|  | 566 |  | 
|  | 567 | if (!pdata->row_hold_ns || | 
|  | 568 | pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || | 
|  | 569 | pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || | 
|  | 570 | ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | 
|  | 571 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | 
|  | 572 | return -EINVAL; | 
|  | 573 | } | 
|  | 574 |  | 
|  | 575 | if (!pdata->debounce_ms || | 
|  | 576 | ((pdata->debounce_ms % 5) != 0) || | 
|  | 577 | pdata->debounce_ms > MAX_DEBOUNCE_TIME || | 
|  | 578 | pdata->debounce_ms < MIN_DEBOUNCE_TIME) { | 
|  | 579 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | 
|  | 580 | return -EINVAL; | 
|  | 581 | } | 
|  | 582 |  | 
|  | 583 | keymap_data = pdata->keymap_data; | 
|  | 584 | if (!keymap_data) { | 
|  | 585 | dev_err(&pdev->dev, "no keymap data supplied\n"); | 
|  | 586 | return -EINVAL; | 
|  | 587 | } | 
|  | 588 |  | 
|  | 589 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | 
|  | 590 | if (!kp) | 
|  | 591 | return -ENOMEM; | 
|  | 592 |  | 
|  | 593 | platform_set_drvdata(pdev, kp); | 
|  | 594 |  | 
|  | 595 | kp->pdata	= pdata; | 
|  | 596 | kp->dev		= &pdev->dev; | 
|  | 597 |  | 
|  | 598 | kp->input = input_allocate_device(); | 
|  | 599 | if (!kp->input) { | 
|  | 600 | dev_err(&pdev->dev, "unable to allocate input device\n"); | 
|  | 601 | rc = -ENOMEM; | 
|  | 602 | goto err_alloc_device; | 
|  | 603 | } | 
|  | 604 |  | 
|  | 605 | kp->key_sense_irq = platform_get_irq(pdev, 0); | 
|  | 606 | if (kp->key_sense_irq < 0) { | 
|  | 607 | dev_err(&pdev->dev, "unable to get keypad sense irq\n"); | 
|  | 608 | rc = -ENXIO; | 
|  | 609 | goto err_get_irq; | 
|  | 610 | } | 
|  | 611 |  | 
|  | 612 | kp->key_stuck_irq = platform_get_irq(pdev, 1); | 
|  | 613 | if (kp->key_stuck_irq < 0) { | 
|  | 614 | dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); | 
|  | 615 | rc = -ENXIO; | 
|  | 616 | goto err_get_irq; | 
|  | 617 | } | 
|  | 618 |  | 
|  | 619 | kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; | 
|  | 620 | kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; | 
|  | 621 |  | 
|  | 622 | kp->input->dev.parent	= &pdev->dev; | 
|  | 623 |  | 
|  | 624 | kp->input->id.bustype	= BUS_I2C; | 
|  | 625 | kp->input->id.version	= 0x0001; | 
|  | 626 | kp->input->id.product	= 0x0001; | 
|  | 627 | kp->input->id.vendor	= 0x0001; | 
|  | 628 |  | 
|  | 629 | kp->input->evbit[0]	= BIT_MASK(EV_KEY); | 
|  | 630 |  | 
|  | 631 | if (pdata->rep) | 
|  | 632 | __set_bit(EV_REP, kp->input->evbit); | 
|  | 633 |  | 
|  | 634 | kp->input->keycode	= kp->keycodes; | 
|  | 635 | kp->input->keycodemax	= PM8XXX_MATRIX_MAX_SIZE; | 
|  | 636 | kp->input->keycodesize	= sizeof(kp->keycodes); | 
|  | 637 | kp->input->open		= pmic8xxx_kp_open; | 
|  | 638 | kp->input->close	= pmic8xxx_kp_close; | 
|  | 639 |  | 
|  | 640 | matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, | 
|  | 641 | kp->input->keycode, kp->input->keybit); | 
|  | 642 |  | 
|  | 643 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); | 
|  | 644 | input_set_drvdata(kp->input, kp); | 
|  | 645 |  | 
|  | 646 | /* initialize keypad state */ | 
|  | 647 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); | 
|  | 648 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); | 
|  | 649 |  | 
|  | 650 | rc = pmic8xxx_kpd_init(kp); | 
|  | 651 | if (rc < 0) { | 
|  | 652 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); | 
|  | 653 | goto err_get_irq; | 
|  | 654 | } | 
|  | 655 |  | 
|  | 656 | rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, | 
|  | 657 | pdata->num_cols, kp, &kypd_sns); | 
|  | 658 | if (rc < 0) { | 
|  | 659 | dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); | 
|  | 660 | goto err_gpio_config; | 
|  | 661 | } | 
|  | 662 |  | 
|  | 663 | rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, | 
|  | 664 | pdata->num_rows, kp, &kypd_drv); | 
|  | 665 | if (rc < 0) { | 
|  | 666 | dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); | 
|  | 667 | goto err_gpio_config; | 
|  | 668 | } | 
|  | 669 |  | 
|  | 670 | rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, | 
|  | 671 | IRQF_TRIGGER_RISING, "pmic-keypad", kp); | 
|  | 672 | if (rc < 0) { | 
|  | 673 | dev_err(&pdev->dev, "failed to request keypad sense irq\n"); | 
|  | 674 | goto err_get_irq; | 
|  | 675 | } | 
|  | 676 |  | 
|  | 677 | rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, | 
|  | 678 | IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); | 
|  | 679 | if (rc < 0) { | 
|  | 680 | dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); | 
|  | 681 | goto err_req_stuck_irq; | 
|  | 682 | } | 
|  | 683 |  | 
|  | 684 | rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); | 
|  | 685 | if (rc < 0) { | 
|  | 686 | dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); | 
|  | 687 | goto err_pmic_reg_read; | 
|  | 688 | } | 
|  | 689 |  | 
|  | 690 | kp->ctrl_reg = ctrl_val; | 
|  | 691 |  | 
|  | 692 | rc = input_register_device(kp->input); | 
|  | 693 | if (rc < 0) { | 
|  | 694 | dev_err(&pdev->dev, "unable to register keypad input device\n"); | 
|  | 695 | goto err_pmic_reg_read; | 
|  | 696 | } | 
|  | 697 |  | 
|  | 698 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 
|  | 699 |  | 
|  | 700 | return 0; | 
|  | 701 |  | 
|  | 702 | err_pmic_reg_read: | 
| Axel Lin | edf21d9 | 2011-07-18 17:09:22 -0700 | [diff] [blame] | 703 | free_irq(kp->key_stuck_irq, kp); | 
| Trilok Soni | 39325b5 | 2011-05-19 10:54:04 +0530 | [diff] [blame] | 704 | err_req_stuck_irq: | 
| Axel Lin | edf21d9 | 2011-07-18 17:09:22 -0700 | [diff] [blame] | 705 | free_irq(kp->key_sense_irq, kp); | 
| Trilok Soni | 39325b5 | 2011-05-19 10:54:04 +0530 | [diff] [blame] | 706 | err_gpio_config: | 
|  | 707 | err_get_irq: | 
|  | 708 | input_free_device(kp->input); | 
|  | 709 | err_alloc_device: | 
|  | 710 | platform_set_drvdata(pdev, NULL); | 
|  | 711 | kfree(kp); | 
|  | 712 | return rc; | 
|  | 713 | } | 
|  | 714 |  | 
|  | 715 | static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) | 
|  | 716 | { | 
|  | 717 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | 
|  | 718 |  | 
|  | 719 | device_init_wakeup(&pdev->dev, 0); | 
| Axel Lin | edf21d9 | 2011-07-18 17:09:22 -0700 | [diff] [blame] | 720 | free_irq(kp->key_stuck_irq, kp); | 
|  | 721 | free_irq(kp->key_sense_irq, kp); | 
| Trilok Soni | 39325b5 | 2011-05-19 10:54:04 +0530 | [diff] [blame] | 722 | input_unregister_device(kp->input); | 
|  | 723 | kfree(kp); | 
|  | 724 |  | 
|  | 725 | platform_set_drvdata(pdev, NULL); | 
|  | 726 | return 0; | 
|  | 727 | } | 
|  | 728 |  | 
|  | 729 | #ifdef CONFIG_PM_SLEEP | 
|  | 730 | static int pmic8xxx_kp_suspend(struct device *dev) | 
|  | 731 | { | 
|  | 732 | struct platform_device *pdev = to_platform_device(dev); | 
|  | 733 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | 
|  | 734 | struct input_dev *input_dev = kp->input; | 
|  | 735 |  | 
|  | 736 | if (device_may_wakeup(dev)) { | 
|  | 737 | enable_irq_wake(kp->key_sense_irq); | 
|  | 738 | } else { | 
|  | 739 | mutex_lock(&input_dev->mutex); | 
|  | 740 |  | 
|  | 741 | if (input_dev->users) | 
|  | 742 | pmic8xxx_kp_disable(kp); | 
|  | 743 |  | 
|  | 744 | mutex_unlock(&input_dev->mutex); | 
|  | 745 | } | 
|  | 746 |  | 
|  | 747 | return 0; | 
|  | 748 | } | 
|  | 749 |  | 
|  | 750 | static int pmic8xxx_kp_resume(struct device *dev) | 
|  | 751 | { | 
|  | 752 | struct platform_device *pdev = to_platform_device(dev); | 
|  | 753 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | 
|  | 754 | struct input_dev *input_dev = kp->input; | 
|  | 755 |  | 
|  | 756 | if (device_may_wakeup(dev)) { | 
|  | 757 | disable_irq_wake(kp->key_sense_irq); | 
|  | 758 | } else { | 
|  | 759 | mutex_lock(&input_dev->mutex); | 
|  | 760 |  | 
|  | 761 | if (input_dev->users) | 
|  | 762 | pmic8xxx_kp_enable(kp); | 
|  | 763 |  | 
|  | 764 | mutex_unlock(&input_dev->mutex); | 
|  | 765 | } | 
|  | 766 |  | 
|  | 767 | return 0; | 
|  | 768 | } | 
|  | 769 | #endif | 
|  | 770 |  | 
|  | 771 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, | 
|  | 772 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); | 
|  | 773 |  | 
|  | 774 | static struct platform_driver pmic8xxx_kp_driver = { | 
|  | 775 | .probe		= pmic8xxx_kp_probe, | 
|  | 776 | .remove		= __devexit_p(pmic8xxx_kp_remove), | 
|  | 777 | .driver		= { | 
|  | 778 | .name = PM8XXX_KEYPAD_DEV_NAME, | 
|  | 779 | .owner = THIS_MODULE, | 
|  | 780 | .pm = &pm8xxx_kp_pm_ops, | 
|  | 781 | }, | 
|  | 782 | }; | 
| JJ Ding | 5146c84 | 2011-11-29 11:08:39 -0800 | [diff] [blame] | 783 | module_platform_driver(pmic8xxx_kp_driver); | 
| Trilok Soni | 39325b5 | 2011-05-19 10:54:04 +0530 | [diff] [blame] | 784 |  | 
|  | 785 | MODULE_LICENSE("GPL v2"); | 
|  | 786 | MODULE_DESCRIPTION("PMIC8XXX keypad driver"); | 
|  | 787 | MODULE_VERSION("1.0"); | 
|  | 788 | MODULE_ALIAS("platform:pmic8xxx_keypad"); | 
|  | 789 | MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>"); |