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