130ba3eadSSriramakrishnan Govindarajan /* 230ba3eadSSriramakrishnan Govindarajan * Driver for keys on TCA6416 I2C IO expander 330ba3eadSSriramakrishnan Govindarajan * 430ba3eadSSriramakrishnan Govindarajan * Copyright (C) 2010 Texas Instruments 530ba3eadSSriramakrishnan Govindarajan * 630ba3eadSSriramakrishnan Govindarajan * Author : Sriramakrishnan.A.G. <srk@ti.com> 730ba3eadSSriramakrishnan Govindarajan * 830ba3eadSSriramakrishnan Govindarajan * This program is free software; you can redistribute it and/or modify 930ba3eadSSriramakrishnan Govindarajan * it under the terms of the GNU General Public License version 2 as 1030ba3eadSSriramakrishnan Govindarajan * published by the Free Software Foundation. 1130ba3eadSSriramakrishnan Govindarajan */ 1230ba3eadSSriramakrishnan Govindarajan 1330ba3eadSSriramakrishnan Govindarajan #include <linux/types.h> 1430ba3eadSSriramakrishnan Govindarajan #include <linux/module.h> 1530ba3eadSSriramakrishnan Govindarajan #include <linux/init.h> 1630ba3eadSSriramakrishnan Govindarajan #include <linux/delay.h> 1730ba3eadSSriramakrishnan Govindarajan #include <linux/slab.h> 1830ba3eadSSriramakrishnan Govindarajan #include <linux/interrupt.h> 1930ba3eadSSriramakrishnan Govindarajan #include <linux/workqueue.h> 2030ba3eadSSriramakrishnan Govindarajan #include <linux/gpio.h> 2130ba3eadSSriramakrishnan Govindarajan #include <linux/i2c.h> 2230ba3eadSSriramakrishnan Govindarajan #include <linux/input.h> 2330ba3eadSSriramakrishnan Govindarajan #include <linux/tca6416_keypad.h> 2430ba3eadSSriramakrishnan Govindarajan 2530ba3eadSSriramakrishnan Govindarajan #define TCA6416_INPUT 0 2630ba3eadSSriramakrishnan Govindarajan #define TCA6416_OUTPUT 1 2730ba3eadSSriramakrishnan Govindarajan #define TCA6416_INVERT 2 2830ba3eadSSriramakrishnan Govindarajan #define TCA6416_DIRECTION 3 2930ba3eadSSriramakrishnan Govindarajan 3030ba3eadSSriramakrishnan Govindarajan static const struct i2c_device_id tca6416_id[] = { 3130ba3eadSSriramakrishnan Govindarajan { "tca6416-keys", 16, }, 32b8a3d6bcSTony SIM { "tca6408-keys", 8, }, 3330ba3eadSSriramakrishnan Govindarajan { } 3430ba3eadSSriramakrishnan Govindarajan }; 3530ba3eadSSriramakrishnan Govindarajan MODULE_DEVICE_TABLE(i2c, tca6416_id); 3630ba3eadSSriramakrishnan Govindarajan 3730ba3eadSSriramakrishnan Govindarajan struct tca6416_drv_data { 3830ba3eadSSriramakrishnan Govindarajan struct input_dev *input; 3930ba3eadSSriramakrishnan Govindarajan struct tca6416_button data[0]; 4030ba3eadSSriramakrishnan Govindarajan }; 4130ba3eadSSriramakrishnan Govindarajan 4230ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip { 4330ba3eadSSriramakrishnan Govindarajan uint16_t reg_output; 4430ba3eadSSriramakrishnan Govindarajan uint16_t reg_direction; 4530ba3eadSSriramakrishnan Govindarajan uint16_t reg_input; 4630ba3eadSSriramakrishnan Govindarajan 4730ba3eadSSriramakrishnan Govindarajan struct i2c_client *client; 4830ba3eadSSriramakrishnan Govindarajan struct input_dev *input; 4930ba3eadSSriramakrishnan Govindarajan struct delayed_work dwork; 50b8a3d6bcSTony SIM int io_size; 5130ba3eadSSriramakrishnan Govindarajan int irqnum; 52b8a3d6bcSTony SIM u16 pinmask; 5330ba3eadSSriramakrishnan Govindarajan bool use_polling; 5430ba3eadSSriramakrishnan Govindarajan struct tca6416_button buttons[0]; 5530ba3eadSSriramakrishnan Govindarajan }; 5630ba3eadSSriramakrishnan Govindarajan 5730ba3eadSSriramakrishnan Govindarajan static int tca6416_write_reg(struct tca6416_keypad_chip *chip, int reg, u16 val) 5830ba3eadSSriramakrishnan Govindarajan { 5930ba3eadSSriramakrishnan Govindarajan int error; 6030ba3eadSSriramakrishnan Govindarajan 61b8a3d6bcSTony SIM error = chip->io_size > 8 ? 62b8a3d6bcSTony SIM i2c_smbus_write_word_data(chip->client, reg << 1, val) : 63b8a3d6bcSTony SIM i2c_smbus_write_byte_data(chip->client, reg, val); 6430ba3eadSSriramakrishnan Govindarajan if (error < 0) { 6530ba3eadSSriramakrishnan Govindarajan dev_err(&chip->client->dev, 6630ba3eadSSriramakrishnan Govindarajan "%s failed, reg: %d, val: %d, error: %d\n", 6730ba3eadSSriramakrishnan Govindarajan __func__, reg, val, error); 6830ba3eadSSriramakrishnan Govindarajan return error; 6930ba3eadSSriramakrishnan Govindarajan } 7030ba3eadSSriramakrishnan Govindarajan 7130ba3eadSSriramakrishnan Govindarajan return 0; 7230ba3eadSSriramakrishnan Govindarajan } 7330ba3eadSSriramakrishnan Govindarajan 7430ba3eadSSriramakrishnan Govindarajan static int tca6416_read_reg(struct tca6416_keypad_chip *chip, int reg, u16 *val) 7530ba3eadSSriramakrishnan Govindarajan { 7630ba3eadSSriramakrishnan Govindarajan int retval; 7730ba3eadSSriramakrishnan Govindarajan 78b8a3d6bcSTony SIM retval = chip->io_size > 8 ? 79b8a3d6bcSTony SIM i2c_smbus_read_word_data(chip->client, reg << 1) : 80b8a3d6bcSTony SIM i2c_smbus_read_byte_data(chip->client, reg); 8130ba3eadSSriramakrishnan Govindarajan if (retval < 0) { 8230ba3eadSSriramakrishnan Govindarajan dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n", 8330ba3eadSSriramakrishnan Govindarajan __func__, reg, retval); 8430ba3eadSSriramakrishnan Govindarajan return retval; 8530ba3eadSSriramakrishnan Govindarajan } 8630ba3eadSSriramakrishnan Govindarajan 8730ba3eadSSriramakrishnan Govindarajan *val = (u16)retval; 8830ba3eadSSriramakrishnan Govindarajan return 0; 8930ba3eadSSriramakrishnan Govindarajan } 9030ba3eadSSriramakrishnan Govindarajan 9130ba3eadSSriramakrishnan Govindarajan static void tca6416_keys_scan(struct tca6416_keypad_chip *chip) 9230ba3eadSSriramakrishnan Govindarajan { 9330ba3eadSSriramakrishnan Govindarajan struct input_dev *input = chip->input; 9430ba3eadSSriramakrishnan Govindarajan u16 reg_val, val; 9530ba3eadSSriramakrishnan Govindarajan int error, i, pin_index; 9630ba3eadSSriramakrishnan Govindarajan 9730ba3eadSSriramakrishnan Govindarajan error = tca6416_read_reg(chip, TCA6416_INPUT, ®_val); 9830ba3eadSSriramakrishnan Govindarajan if (error) 9930ba3eadSSriramakrishnan Govindarajan return; 10030ba3eadSSriramakrishnan Govindarajan 10130ba3eadSSriramakrishnan Govindarajan reg_val &= chip->pinmask; 10230ba3eadSSriramakrishnan Govindarajan 10330ba3eadSSriramakrishnan Govindarajan /* Figure out which lines have changed */ 10430ba3eadSSriramakrishnan Govindarajan val = reg_val ^ chip->reg_input; 10530ba3eadSSriramakrishnan Govindarajan chip->reg_input = reg_val; 10630ba3eadSSriramakrishnan Govindarajan 10730ba3eadSSriramakrishnan Govindarajan for (i = 0, pin_index = 0; i < 16; i++) { 10830ba3eadSSriramakrishnan Govindarajan if (val & (1 << i)) { 10930ba3eadSSriramakrishnan Govindarajan struct tca6416_button *button = &chip->buttons[pin_index]; 11030ba3eadSSriramakrishnan Govindarajan unsigned int type = button->type ?: EV_KEY; 11130ba3eadSSriramakrishnan Govindarajan int state = ((reg_val & (1 << i)) ? 1 : 0) 11230ba3eadSSriramakrishnan Govindarajan ^ button->active_low; 11330ba3eadSSriramakrishnan Govindarajan 11430ba3eadSSriramakrishnan Govindarajan input_event(input, type, button->code, !!state); 11530ba3eadSSriramakrishnan Govindarajan input_sync(input); 11630ba3eadSSriramakrishnan Govindarajan } 11730ba3eadSSriramakrishnan Govindarajan 11830ba3eadSSriramakrishnan Govindarajan if (chip->pinmask & (1 << i)) 11930ba3eadSSriramakrishnan Govindarajan pin_index++; 12030ba3eadSSriramakrishnan Govindarajan } 12130ba3eadSSriramakrishnan Govindarajan } 12230ba3eadSSriramakrishnan Govindarajan 12330ba3eadSSriramakrishnan Govindarajan /* 12430ba3eadSSriramakrishnan Govindarajan * This is threaded IRQ handler and this can (and will) sleep. 12530ba3eadSSriramakrishnan Govindarajan */ 12630ba3eadSSriramakrishnan Govindarajan static irqreturn_t tca6416_keys_isr(int irq, void *dev_id) 12730ba3eadSSriramakrishnan Govindarajan { 12830ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip *chip = dev_id; 12930ba3eadSSriramakrishnan Govindarajan 13030ba3eadSSriramakrishnan Govindarajan tca6416_keys_scan(chip); 13130ba3eadSSriramakrishnan Govindarajan 13230ba3eadSSriramakrishnan Govindarajan return IRQ_HANDLED; 13330ba3eadSSriramakrishnan Govindarajan } 13430ba3eadSSriramakrishnan Govindarajan 13530ba3eadSSriramakrishnan Govindarajan static void tca6416_keys_work_func(struct work_struct *work) 13630ba3eadSSriramakrishnan Govindarajan { 13730ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip *chip = 13830ba3eadSSriramakrishnan Govindarajan container_of(work, struct tca6416_keypad_chip, dwork.work); 13930ba3eadSSriramakrishnan Govindarajan 14030ba3eadSSriramakrishnan Govindarajan tca6416_keys_scan(chip); 14130ba3eadSSriramakrishnan Govindarajan schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); 14230ba3eadSSriramakrishnan Govindarajan } 14330ba3eadSSriramakrishnan Govindarajan 14430ba3eadSSriramakrishnan Govindarajan static int tca6416_keys_open(struct input_dev *dev) 14530ba3eadSSriramakrishnan Govindarajan { 14630ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip *chip = input_get_drvdata(dev); 14730ba3eadSSriramakrishnan Govindarajan 14830ba3eadSSriramakrishnan Govindarajan /* Get initial device state in case it has switches */ 14930ba3eadSSriramakrishnan Govindarajan tca6416_keys_scan(chip); 15030ba3eadSSriramakrishnan Govindarajan 15130ba3eadSSriramakrishnan Govindarajan if (chip->use_polling) 15230ba3eadSSriramakrishnan Govindarajan schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); 15330ba3eadSSriramakrishnan Govindarajan else 15430ba3eadSSriramakrishnan Govindarajan enable_irq(chip->irqnum); 15530ba3eadSSriramakrishnan Govindarajan 15630ba3eadSSriramakrishnan Govindarajan return 0; 15730ba3eadSSriramakrishnan Govindarajan } 15830ba3eadSSriramakrishnan Govindarajan 15930ba3eadSSriramakrishnan Govindarajan static void tca6416_keys_close(struct input_dev *dev) 16030ba3eadSSriramakrishnan Govindarajan { 16130ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip *chip = input_get_drvdata(dev); 16230ba3eadSSriramakrishnan Govindarajan 16330ba3eadSSriramakrishnan Govindarajan if (chip->use_polling) 16430ba3eadSSriramakrishnan Govindarajan cancel_delayed_work_sync(&chip->dwork); 16530ba3eadSSriramakrishnan Govindarajan else 16630ba3eadSSriramakrishnan Govindarajan disable_irq(chip->irqnum); 16730ba3eadSSriramakrishnan Govindarajan } 16830ba3eadSSriramakrishnan Govindarajan 16930ba3eadSSriramakrishnan Govindarajan static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip) 17030ba3eadSSriramakrishnan Govindarajan { 17130ba3eadSSriramakrishnan Govindarajan int error; 17230ba3eadSSriramakrishnan Govindarajan 17330ba3eadSSriramakrishnan Govindarajan error = tca6416_read_reg(chip, TCA6416_OUTPUT, &chip->reg_output); 17430ba3eadSSriramakrishnan Govindarajan if (error) 17530ba3eadSSriramakrishnan Govindarajan return error; 17630ba3eadSSriramakrishnan Govindarajan 17730ba3eadSSriramakrishnan Govindarajan error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction); 17830ba3eadSSriramakrishnan Govindarajan if (error) 17930ba3eadSSriramakrishnan Govindarajan return error; 18030ba3eadSSriramakrishnan Govindarajan 18130ba3eadSSriramakrishnan Govindarajan /* ensure that keypad pins are set to input */ 18230ba3eadSSriramakrishnan Govindarajan error = tca6416_write_reg(chip, TCA6416_DIRECTION, 18330ba3eadSSriramakrishnan Govindarajan chip->reg_direction | chip->pinmask); 18430ba3eadSSriramakrishnan Govindarajan if (error) 18530ba3eadSSriramakrishnan Govindarajan return error; 18630ba3eadSSriramakrishnan Govindarajan 18730ba3eadSSriramakrishnan Govindarajan error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction); 18830ba3eadSSriramakrishnan Govindarajan if (error) 18930ba3eadSSriramakrishnan Govindarajan return error; 19030ba3eadSSriramakrishnan Govindarajan 19130ba3eadSSriramakrishnan Govindarajan error = tca6416_read_reg(chip, TCA6416_INPUT, &chip->reg_input); 19230ba3eadSSriramakrishnan Govindarajan if (error) 19330ba3eadSSriramakrishnan Govindarajan return error; 19430ba3eadSSriramakrishnan Govindarajan 19530ba3eadSSriramakrishnan Govindarajan chip->reg_input &= chip->pinmask; 19630ba3eadSSriramakrishnan Govindarajan 19730ba3eadSSriramakrishnan Govindarajan return 0; 19830ba3eadSSriramakrishnan Govindarajan } 19930ba3eadSSriramakrishnan Govindarajan 20030ba3eadSSriramakrishnan Govindarajan static int __devinit tca6416_keypad_probe(struct i2c_client *client, 20130ba3eadSSriramakrishnan Govindarajan const struct i2c_device_id *id) 20230ba3eadSSriramakrishnan Govindarajan { 20330ba3eadSSriramakrishnan Govindarajan struct tca6416_keys_platform_data *pdata; 20430ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip *chip; 20530ba3eadSSriramakrishnan Govindarajan struct input_dev *input; 20630ba3eadSSriramakrishnan Govindarajan int error; 20730ba3eadSSriramakrishnan Govindarajan int i; 20830ba3eadSSriramakrishnan Govindarajan 20930ba3eadSSriramakrishnan Govindarajan /* Check functionality */ 21030ba3eadSSriramakrishnan Govindarajan if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { 21130ba3eadSSriramakrishnan Govindarajan dev_err(&client->dev, "%s adapter not supported\n", 21230ba3eadSSriramakrishnan Govindarajan dev_driver_string(&client->adapter->dev)); 21330ba3eadSSriramakrishnan Govindarajan return -ENODEV; 21430ba3eadSSriramakrishnan Govindarajan } 21530ba3eadSSriramakrishnan Govindarajan 21630ba3eadSSriramakrishnan Govindarajan pdata = client->dev.platform_data; 21730ba3eadSSriramakrishnan Govindarajan if (!pdata) { 21830ba3eadSSriramakrishnan Govindarajan dev_dbg(&client->dev, "no platform data\n"); 21930ba3eadSSriramakrishnan Govindarajan return -EINVAL; 22030ba3eadSSriramakrishnan Govindarajan } 22130ba3eadSSriramakrishnan Govindarajan 22230ba3eadSSriramakrishnan Govindarajan chip = kzalloc(sizeof(struct tca6416_keypad_chip) + 22330ba3eadSSriramakrishnan Govindarajan pdata->nbuttons * sizeof(struct tca6416_button), 22430ba3eadSSriramakrishnan Govindarajan GFP_KERNEL); 22530ba3eadSSriramakrishnan Govindarajan input = input_allocate_device(); 22630ba3eadSSriramakrishnan Govindarajan if (!chip || !input) { 22730ba3eadSSriramakrishnan Govindarajan error = -ENOMEM; 22830ba3eadSSriramakrishnan Govindarajan goto fail1; 22930ba3eadSSriramakrishnan Govindarajan } 23030ba3eadSSriramakrishnan Govindarajan 23130ba3eadSSriramakrishnan Govindarajan chip->client = client; 23230ba3eadSSriramakrishnan Govindarajan chip->input = input; 233b8a3d6bcSTony SIM chip->io_size = id->driver_data; 23430ba3eadSSriramakrishnan Govindarajan chip->pinmask = pdata->pinmask; 23530ba3eadSSriramakrishnan Govindarajan chip->use_polling = pdata->use_polling; 23630ba3eadSSriramakrishnan Govindarajan 23730ba3eadSSriramakrishnan Govindarajan INIT_DELAYED_WORK(&chip->dwork, tca6416_keys_work_func); 23830ba3eadSSriramakrishnan Govindarajan 23930ba3eadSSriramakrishnan Govindarajan input->phys = "tca6416-keys/input0"; 24030ba3eadSSriramakrishnan Govindarajan input->name = client->name; 24130ba3eadSSriramakrishnan Govindarajan input->dev.parent = &client->dev; 24230ba3eadSSriramakrishnan Govindarajan 24330ba3eadSSriramakrishnan Govindarajan input->open = tca6416_keys_open; 24430ba3eadSSriramakrishnan Govindarajan input->close = tca6416_keys_close; 24530ba3eadSSriramakrishnan Govindarajan 24630ba3eadSSriramakrishnan Govindarajan input->id.bustype = BUS_HOST; 24730ba3eadSSriramakrishnan Govindarajan input->id.vendor = 0x0001; 24830ba3eadSSriramakrishnan Govindarajan input->id.product = 0x0001; 24930ba3eadSSriramakrishnan Govindarajan input->id.version = 0x0100; 25030ba3eadSSriramakrishnan Govindarajan 25130ba3eadSSriramakrishnan Govindarajan /* Enable auto repeat feature of Linux input subsystem */ 25230ba3eadSSriramakrishnan Govindarajan if (pdata->rep) 25330ba3eadSSriramakrishnan Govindarajan __set_bit(EV_REP, input->evbit); 25430ba3eadSSriramakrishnan Govindarajan 25530ba3eadSSriramakrishnan Govindarajan for (i = 0; i < pdata->nbuttons; i++) { 25630ba3eadSSriramakrishnan Govindarajan unsigned int type; 25730ba3eadSSriramakrishnan Govindarajan 25830ba3eadSSriramakrishnan Govindarajan chip->buttons[i] = pdata->buttons[i]; 25930ba3eadSSriramakrishnan Govindarajan type = (pdata->buttons[i].type) ?: EV_KEY; 26030ba3eadSSriramakrishnan Govindarajan input_set_capability(input, type, pdata->buttons[i].code); 26130ba3eadSSriramakrishnan Govindarajan } 26230ba3eadSSriramakrishnan Govindarajan 26330ba3eadSSriramakrishnan Govindarajan input_set_drvdata(input, chip); 26430ba3eadSSriramakrishnan Govindarajan 26530ba3eadSSriramakrishnan Govindarajan /* 26630ba3eadSSriramakrishnan Govindarajan * Initialize cached registers from their original values. 26730ba3eadSSriramakrishnan Govindarajan * we can't share this chip with another i2c master. 26830ba3eadSSriramakrishnan Govindarajan */ 26930ba3eadSSriramakrishnan Govindarajan error = tca6416_setup_registers(chip); 27030ba3eadSSriramakrishnan Govindarajan if (error) 27130ba3eadSSriramakrishnan Govindarajan goto fail1; 27230ba3eadSSriramakrishnan Govindarajan 27330ba3eadSSriramakrishnan Govindarajan if (!chip->use_polling) { 27430ba3eadSSriramakrishnan Govindarajan if (pdata->irq_is_gpio) 27530ba3eadSSriramakrishnan Govindarajan chip->irqnum = gpio_to_irq(client->irq); 27630ba3eadSSriramakrishnan Govindarajan else 27730ba3eadSSriramakrishnan Govindarajan chip->irqnum = client->irq; 27830ba3eadSSriramakrishnan Govindarajan 27930ba3eadSSriramakrishnan Govindarajan error = request_threaded_irq(chip->irqnum, NULL, 28030ba3eadSSriramakrishnan Govindarajan tca6416_keys_isr, 281*9b7e31bbSLars-Peter Clausen IRQF_TRIGGER_FALLING | 282*9b7e31bbSLars-Peter Clausen IRQF_ONESHOT, 28330ba3eadSSriramakrishnan Govindarajan "tca6416-keypad", chip); 28430ba3eadSSriramakrishnan Govindarajan if (error) { 28530ba3eadSSriramakrishnan Govindarajan dev_dbg(&client->dev, 28630ba3eadSSriramakrishnan Govindarajan "Unable to claim irq %d; error %d\n", 28730ba3eadSSriramakrishnan Govindarajan chip->irqnum, error); 28830ba3eadSSriramakrishnan Govindarajan goto fail1; 28930ba3eadSSriramakrishnan Govindarajan } 29030ba3eadSSriramakrishnan Govindarajan disable_irq(chip->irqnum); 29130ba3eadSSriramakrishnan Govindarajan } 29230ba3eadSSriramakrishnan Govindarajan 29330ba3eadSSriramakrishnan Govindarajan error = input_register_device(input); 29430ba3eadSSriramakrishnan Govindarajan if (error) { 29530ba3eadSSriramakrishnan Govindarajan dev_dbg(&client->dev, 29630ba3eadSSriramakrishnan Govindarajan "Unable to register input device, error: %d\n", error); 29730ba3eadSSriramakrishnan Govindarajan goto fail2; 29830ba3eadSSriramakrishnan Govindarajan } 29930ba3eadSSriramakrishnan Govindarajan 30030ba3eadSSriramakrishnan Govindarajan i2c_set_clientdata(client, chip); 30164dcddd8SMagnus Damm device_init_wakeup(&client->dev, 1); 30230ba3eadSSriramakrishnan Govindarajan 30330ba3eadSSriramakrishnan Govindarajan return 0; 30430ba3eadSSriramakrishnan Govindarajan 30530ba3eadSSriramakrishnan Govindarajan fail2: 30630ba3eadSSriramakrishnan Govindarajan if (!chip->use_polling) { 30730ba3eadSSriramakrishnan Govindarajan free_irq(chip->irqnum, chip); 30830ba3eadSSriramakrishnan Govindarajan enable_irq(chip->irqnum); 30930ba3eadSSriramakrishnan Govindarajan } 31030ba3eadSSriramakrishnan Govindarajan fail1: 31130ba3eadSSriramakrishnan Govindarajan input_free_device(input); 31230ba3eadSSriramakrishnan Govindarajan kfree(chip); 31330ba3eadSSriramakrishnan Govindarajan return error; 31430ba3eadSSriramakrishnan Govindarajan } 31530ba3eadSSriramakrishnan Govindarajan 31630ba3eadSSriramakrishnan Govindarajan static int __devexit tca6416_keypad_remove(struct i2c_client *client) 31730ba3eadSSriramakrishnan Govindarajan { 31830ba3eadSSriramakrishnan Govindarajan struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); 31930ba3eadSSriramakrishnan Govindarajan 32030ba3eadSSriramakrishnan Govindarajan if (!chip->use_polling) { 32130ba3eadSSriramakrishnan Govindarajan free_irq(chip->irqnum, chip); 32230ba3eadSSriramakrishnan Govindarajan enable_irq(chip->irqnum); 32330ba3eadSSriramakrishnan Govindarajan } 32430ba3eadSSriramakrishnan Govindarajan 32530ba3eadSSriramakrishnan Govindarajan input_unregister_device(chip->input); 32630ba3eadSSriramakrishnan Govindarajan kfree(chip); 32730ba3eadSSriramakrishnan Govindarajan 32830ba3eadSSriramakrishnan Govindarajan return 0; 32930ba3eadSSriramakrishnan Govindarajan } 33030ba3eadSSriramakrishnan Govindarajan 33164dcddd8SMagnus Damm #ifdef CONFIG_PM_SLEEP 33264dcddd8SMagnus Damm static int tca6416_keypad_suspend(struct device *dev) 33364dcddd8SMagnus Damm { 33464dcddd8SMagnus Damm struct i2c_client *client = to_i2c_client(dev); 33564dcddd8SMagnus Damm struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); 33664dcddd8SMagnus Damm 33764dcddd8SMagnus Damm if (device_may_wakeup(dev)) 33864dcddd8SMagnus Damm enable_irq_wake(chip->irqnum); 33964dcddd8SMagnus Damm 34064dcddd8SMagnus Damm return 0; 34164dcddd8SMagnus Damm } 34264dcddd8SMagnus Damm 34364dcddd8SMagnus Damm static int tca6416_keypad_resume(struct device *dev) 34464dcddd8SMagnus Damm { 34564dcddd8SMagnus Damm struct i2c_client *client = to_i2c_client(dev); 34664dcddd8SMagnus Damm struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); 34764dcddd8SMagnus Damm 34864dcddd8SMagnus Damm if (device_may_wakeup(dev)) 34964dcddd8SMagnus Damm disable_irq_wake(chip->irqnum); 35064dcddd8SMagnus Damm 35164dcddd8SMagnus Damm return 0; 35264dcddd8SMagnus Damm } 35364dcddd8SMagnus Damm #endif 35464dcddd8SMagnus Damm 35564dcddd8SMagnus Damm static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops, 35664dcddd8SMagnus Damm tca6416_keypad_suspend, tca6416_keypad_resume); 35730ba3eadSSriramakrishnan Govindarajan 35830ba3eadSSriramakrishnan Govindarajan static struct i2c_driver tca6416_keypad_driver = { 35930ba3eadSSriramakrishnan Govindarajan .driver = { 36030ba3eadSSriramakrishnan Govindarajan .name = "tca6416-keypad", 36164dcddd8SMagnus Damm .pm = &tca6416_keypad_dev_pm_ops, 36230ba3eadSSriramakrishnan Govindarajan }, 36330ba3eadSSriramakrishnan Govindarajan .probe = tca6416_keypad_probe, 36430ba3eadSSriramakrishnan Govindarajan .remove = __devexit_p(tca6416_keypad_remove), 36530ba3eadSSriramakrishnan Govindarajan .id_table = tca6416_id, 36630ba3eadSSriramakrishnan Govindarajan }; 36730ba3eadSSriramakrishnan Govindarajan 36830ba3eadSSriramakrishnan Govindarajan static int __init tca6416_keypad_init(void) 36930ba3eadSSriramakrishnan Govindarajan { 37030ba3eadSSriramakrishnan Govindarajan return i2c_add_driver(&tca6416_keypad_driver); 37130ba3eadSSriramakrishnan Govindarajan } 37230ba3eadSSriramakrishnan Govindarajan 37330ba3eadSSriramakrishnan Govindarajan subsys_initcall(tca6416_keypad_init); 37430ba3eadSSriramakrishnan Govindarajan 37530ba3eadSSriramakrishnan Govindarajan static void __exit tca6416_keypad_exit(void) 37630ba3eadSSriramakrishnan Govindarajan { 37730ba3eadSSriramakrishnan Govindarajan i2c_del_driver(&tca6416_keypad_driver); 37830ba3eadSSriramakrishnan Govindarajan } 37930ba3eadSSriramakrishnan Govindarajan module_exit(tca6416_keypad_exit); 38030ba3eadSSriramakrishnan Govindarajan 38130ba3eadSSriramakrishnan Govindarajan MODULE_AUTHOR("Sriramakrishnan <srk@ti.com>"); 38230ba3eadSSriramakrishnan Govindarajan MODULE_DESCRIPTION("Keypad driver over tca6146 IO expander"); 38330ba3eadSSriramakrishnan Govindarajan MODULE_LICENSE("GPL"); 384