Path: blob/master/drivers/input/keyboard/adp5588-keys.c
15109 views
/*1* File: drivers/input/keyboard/adp5588_keys.c2* Description: keypad driver for ADP5588 and ADP55873* I2C QWERTY Keypad and IO Expander4* Bugs: Enter bugs at http://blackfin.uclinux.org/5*6* Copyright (C) 2008-2010 Analog Devices Inc.7* Licensed under the GPL-2 or later.8*/910#include <linux/module.h>11#include <linux/version.h>12#include <linux/init.h>13#include <linux/interrupt.h>14#include <linux/irq.h>15#include <linux/workqueue.h>16#include <linux/errno.h>17#include <linux/pm.h>18#include <linux/platform_device.h>19#include <linux/input.h>20#include <linux/i2c.h>21#include <linux/gpio.h>22#include <linux/slab.h>2324#include <linux/i2c/adp5588.h>2526/* Key Event Register xy */27#define KEY_EV_PRESSED (1 << 7)28#define KEY_EV_MASK (0x7F)2930#define KP_SEL(x) (0xFFFF >> (16 - x)) /* 2^x-1 */3132#define KEYP_MAX_EVENT 103334/*35* Early pre 4.0 Silicon required to delay readout by at least 25ms,36* since the Event Counter Register updated 25ms after the interrupt37* asserted.38*/39#define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4)4041struct adp5588_kpad {42struct i2c_client *client;43struct input_dev *input;44struct delayed_work work;45unsigned long delay;46unsigned short keycode[ADP5588_KEYMAPSIZE];47const struct adp5588_gpi_map *gpimap;48unsigned short gpimapsize;49#ifdef CONFIG_GPIOLIB50unsigned char gpiomap[ADP5588_MAXGPIO];51bool export_gpio;52struct gpio_chip gc;53struct mutex gpio_lock; /* Protect cached dir, dat_out */54u8 dat_out[3];55u8 dir[3];56#endif57};5859static int adp5588_read(struct i2c_client *client, u8 reg)60{61int ret = i2c_smbus_read_byte_data(client, reg);6263if (ret < 0)64dev_err(&client->dev, "Read Error\n");6566return ret;67}6869static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)70{71return i2c_smbus_write_byte_data(client, reg, val);72}7374#ifdef CONFIG_GPIOLIB75static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)76{77struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);78unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);79unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);8081return !!(adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank) & bit);82}8384static void adp5588_gpio_set_value(struct gpio_chip *chip,85unsigned off, int val)86{87struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);88unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);89unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);9091mutex_lock(&kpad->gpio_lock);9293if (val)94kpad->dat_out[bank] |= bit;95else96kpad->dat_out[bank] &= ~bit;9798adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,99kpad->dat_out[bank]);100101mutex_unlock(&kpad->gpio_lock);102}103104static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)105{106struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);107unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);108unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);109int ret;110111mutex_lock(&kpad->gpio_lock);112113kpad->dir[bank] &= ~bit;114ret = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]);115116mutex_unlock(&kpad->gpio_lock);117118return ret;119}120121static int adp5588_gpio_direction_output(struct gpio_chip *chip,122unsigned off, int val)123{124struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);125unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);126unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);127int ret;128129mutex_lock(&kpad->gpio_lock);130131kpad->dir[bank] |= bit;132133if (val)134kpad->dat_out[bank] |= bit;135else136kpad->dat_out[bank] &= ~bit;137138ret = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,139kpad->dat_out[bank]);140ret |= adp5588_write(kpad->client, GPIO_DIR1 + bank,141kpad->dir[bank]);142143mutex_unlock(&kpad->gpio_lock);144145return ret;146}147148static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,149const struct adp5588_kpad_platform_data *pdata)150{151bool pin_used[ADP5588_MAXGPIO];152int n_unused = 0;153int i;154155memset(pin_used, 0, sizeof(pin_used));156157for (i = 0; i < pdata->rows; i++)158pin_used[i] = true;159160for (i = 0; i < pdata->cols; i++)161pin_used[i + GPI_PIN_COL_BASE - GPI_PIN_BASE] = true;162163for (i = 0; i < kpad->gpimapsize; i++)164pin_used[kpad->gpimap[i].pin - GPI_PIN_BASE] = true;165166for (i = 0; i < ADP5588_MAXGPIO; i++)167if (!pin_used[i])168kpad->gpiomap[n_unused++] = i;169170return n_unused;171}172173static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad)174{175struct device *dev = &kpad->client->dev;176const struct adp5588_kpad_platform_data *pdata = dev->platform_data;177const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;178int i, error;179180if (!gpio_data)181return 0;182183kpad->gc.ngpio = adp5588_build_gpiomap(kpad, pdata);184if (kpad->gc.ngpio == 0) {185dev_info(dev, "No unused gpios left to export\n");186return 0;187}188189kpad->export_gpio = true;190191kpad->gc.direction_input = adp5588_gpio_direction_input;192kpad->gc.direction_output = adp5588_gpio_direction_output;193kpad->gc.get = adp5588_gpio_get_value;194kpad->gc.set = adp5588_gpio_set_value;195kpad->gc.can_sleep = 1;196197kpad->gc.base = gpio_data->gpio_start;198kpad->gc.label = kpad->client->name;199kpad->gc.owner = THIS_MODULE;200201mutex_init(&kpad->gpio_lock);202203error = gpiochip_add(&kpad->gc);204if (error) {205dev_err(dev, "gpiochip_add failed, err: %d\n", error);206return error;207}208209for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {210kpad->dat_out[i] = adp5588_read(kpad->client,211GPIO_DAT_OUT1 + i);212kpad->dir[i] = adp5588_read(kpad->client, GPIO_DIR1 + i);213}214215if (gpio_data->setup) {216error = gpio_data->setup(kpad->client,217kpad->gc.base, kpad->gc.ngpio,218gpio_data->context);219if (error)220dev_warn(dev, "setup failed, %d\n", error);221}222223return 0;224}225226static void __devexit adp5588_gpio_remove(struct adp5588_kpad *kpad)227{228struct device *dev = &kpad->client->dev;229const struct adp5588_kpad_platform_data *pdata = dev->platform_data;230const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;231int error;232233if (!kpad->export_gpio)234return;235236if (gpio_data->teardown) {237error = gpio_data->teardown(kpad->client,238kpad->gc.base, kpad->gc.ngpio,239gpio_data->context);240if (error)241dev_warn(dev, "teardown failed %d\n", error);242}243244error = gpiochip_remove(&kpad->gc);245if (error)246dev_warn(dev, "gpiochip_remove failed %d\n", error);247}248#else249static inline int adp5588_gpio_add(struct adp5588_kpad *kpad)250{251return 0;252}253254static inline void adp5588_gpio_remove(struct adp5588_kpad *kpad)255{256}257#endif258259static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)260{261int i, j;262263for (i = 0; i < ev_cnt; i++) {264int key = adp5588_read(kpad->client, Key_EVENTA + i);265int key_val = key & KEY_EV_MASK;266267if (key_val >= GPI_PIN_BASE && key_val <= GPI_PIN_END) {268for (j = 0; j < kpad->gpimapsize; j++) {269if (key_val == kpad->gpimap[j].pin) {270input_report_switch(kpad->input,271kpad->gpimap[j].sw_evt,272key & KEY_EV_PRESSED);273break;274}275}276} else {277input_report_key(kpad->input,278kpad->keycode[key_val - 1],279key & KEY_EV_PRESSED);280}281}282}283284static void adp5588_work(struct work_struct *work)285{286struct adp5588_kpad *kpad = container_of(work,287struct adp5588_kpad, work.work);288struct i2c_client *client = kpad->client;289int status, ev_cnt;290291status = adp5588_read(client, INT_STAT);292293if (status & ADP5588_OVR_FLOW_INT) /* Unlikely and should never happen */294dev_err(&client->dev, "Event Overflow Error\n");295296if (status & ADP5588_KE_INT) {297ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & ADP5588_KEC;298if (ev_cnt) {299adp5588_report_events(kpad, ev_cnt);300input_sync(kpad->input);301}302}303adp5588_write(client, INT_STAT, status); /* Status is W1C */304}305306static irqreturn_t adp5588_irq(int irq, void *handle)307{308struct adp5588_kpad *kpad = handle;309310/*311* use keventd context to read the event fifo registers312* Schedule readout at least 25ms after notification for313* REVID < 4314*/315316schedule_delayed_work(&kpad->work, kpad->delay);317318return IRQ_HANDLED;319}320321static int __devinit adp5588_setup(struct i2c_client *client)322{323const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;324const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;325int i, ret;326unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;327328ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows));329ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF);330ret |= adp5588_write(client, KP_GPIO3, KP_SEL(pdata->cols) >> 8);331332if (pdata->en_keylock) {333ret |= adp5588_write(client, UNLOCK1, pdata->unlock_key1);334ret |= adp5588_write(client, UNLOCK2, pdata->unlock_key2);335ret |= adp5588_write(client, KEY_LCK_EC_STAT, ADP5588_K_LCK_EN);336}337338for (i = 0; i < KEYP_MAX_EVENT; i++)339ret |= adp5588_read(client, Key_EVENTA);340341for (i = 0; i < pdata->gpimapsize; i++) {342unsigned short pin = pdata->gpimap[i].pin;343344if (pin <= GPI_PIN_ROW_END) {345evt_mode1 |= (1 << (pin - GPI_PIN_ROW_BASE));346} else {347evt_mode2 |= ((1 << (pin - GPI_PIN_COL_BASE)) & 0xFF);348evt_mode3 |= ((1 << (pin - GPI_PIN_COL_BASE)) >> 8);349}350}351352if (pdata->gpimapsize) {353ret |= adp5588_write(client, GPI_EM1, evt_mode1);354ret |= adp5588_write(client, GPI_EM2, evt_mode2);355ret |= adp5588_write(client, GPI_EM3, evt_mode3);356}357358if (gpio_data) {359for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {360int pull_mask = gpio_data->pullup_dis_mask;361362ret |= adp5588_write(client, GPIO_PULL1 + i,363(pull_mask >> (8 * i)) & 0xFF);364}365}366367ret |= adp5588_write(client, INT_STAT,368ADP5588_CMP2_INT | ADP5588_CMP1_INT |369ADP5588_OVR_FLOW_INT | ADP5588_K_LCK_INT |370ADP5588_GPI_INT | ADP5588_KE_INT); /* Status is W1C */371372ret |= adp5588_write(client, CFG, ADP5588_INT_CFG |373ADP5588_OVR_FLOW_IEN |374ADP5588_KE_IEN);375376if (ret < 0) {377dev_err(&client->dev, "Write Error\n");378return ret;379}380381return 0;382}383384static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)385{386int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);387int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);388int gpi_stat3 = adp5588_read(kpad->client, GPIO_DAT_STAT3);389int gpi_stat_tmp, pin_loc;390int i;391392for (i = 0; i < kpad->gpimapsize; i++) {393unsigned short pin = kpad->gpimap[i].pin;394395if (pin <= GPI_PIN_ROW_END) {396gpi_stat_tmp = gpi_stat1;397pin_loc = pin - GPI_PIN_ROW_BASE;398} else if ((pin - GPI_PIN_COL_BASE) < 8) {399gpi_stat_tmp = gpi_stat2;400pin_loc = pin - GPI_PIN_COL_BASE;401} else {402gpi_stat_tmp = gpi_stat3;403pin_loc = pin - GPI_PIN_COL_BASE - 8;404}405406if (gpi_stat_tmp < 0) {407dev_err(&kpad->client->dev,408"Can't read GPIO_DAT_STAT switch %d default to OFF\n",409pin);410gpi_stat_tmp = 0;411}412413input_report_switch(kpad->input,414kpad->gpimap[i].sw_evt,415!(gpi_stat_tmp & (1 << pin_loc)));416}417418input_sync(kpad->input);419}420421422static int __devinit adp5588_probe(struct i2c_client *client,423const struct i2c_device_id *id)424{425struct adp5588_kpad *kpad;426const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;427struct input_dev *input;428unsigned int revid;429int ret, i;430int error;431432if (!i2c_check_functionality(client->adapter,433I2C_FUNC_SMBUS_BYTE_DATA)) {434dev_err(&client->dev, "SMBUS Byte Data not Supported\n");435return -EIO;436}437438if (!pdata) {439dev_err(&client->dev, "no platform data?\n");440return -EINVAL;441}442443if (!pdata->rows || !pdata->cols || !pdata->keymap) {444dev_err(&client->dev, "no rows, cols or keymap from pdata\n");445return -EINVAL;446}447448if (pdata->keymapsize != ADP5588_KEYMAPSIZE) {449dev_err(&client->dev, "invalid keymapsize\n");450return -EINVAL;451}452453if (!pdata->gpimap && pdata->gpimapsize) {454dev_err(&client->dev, "invalid gpimap from pdata\n");455return -EINVAL;456}457458if (pdata->gpimapsize > ADP5588_GPIMAPSIZE_MAX) {459dev_err(&client->dev, "invalid gpimapsize\n");460return -EINVAL;461}462463for (i = 0; i < pdata->gpimapsize; i++) {464unsigned short pin = pdata->gpimap[i].pin;465466if (pin < GPI_PIN_BASE || pin > GPI_PIN_END) {467dev_err(&client->dev, "invalid gpi pin data\n");468return -EINVAL;469}470471if (pin <= GPI_PIN_ROW_END) {472if (pin - GPI_PIN_ROW_BASE + 1 <= pdata->rows) {473dev_err(&client->dev, "invalid gpi row data\n");474return -EINVAL;475}476} else {477if (pin - GPI_PIN_COL_BASE + 1 <= pdata->cols) {478dev_err(&client->dev, "invalid gpi col data\n");479return -EINVAL;480}481}482}483484if (!client->irq) {485dev_err(&client->dev, "no IRQ?\n");486return -EINVAL;487}488489kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);490input = input_allocate_device();491if (!kpad || !input) {492error = -ENOMEM;493goto err_free_mem;494}495496kpad->client = client;497kpad->input = input;498INIT_DELAYED_WORK(&kpad->work, adp5588_work);499500ret = adp5588_read(client, DEV_ID);501if (ret < 0) {502error = ret;503goto err_free_mem;504}505506revid = (u8) ret & ADP5588_DEVICE_ID_MASK;507if (WA_DELAYED_READOUT_REVID(revid))508kpad->delay = msecs_to_jiffies(30);509510input->name = client->name;511input->phys = "adp5588-keys/input0";512input->dev.parent = &client->dev;513514input_set_drvdata(input, kpad);515516input->id.bustype = BUS_I2C;517input->id.vendor = 0x0001;518input->id.product = 0x0001;519input->id.version = revid;520521input->keycodesize = sizeof(kpad->keycode[0]);522input->keycodemax = pdata->keymapsize;523input->keycode = kpad->keycode;524525memcpy(kpad->keycode, pdata->keymap,526pdata->keymapsize * input->keycodesize);527528kpad->gpimap = pdata->gpimap;529kpad->gpimapsize = pdata->gpimapsize;530531/* setup input device */532__set_bit(EV_KEY, input->evbit);533534if (pdata->repeat)535__set_bit(EV_REP, input->evbit);536537for (i = 0; i < input->keycodemax; i++)538__set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);539__clear_bit(KEY_RESERVED, input->keybit);540541if (kpad->gpimapsize)542__set_bit(EV_SW, input->evbit);543for (i = 0; i < kpad->gpimapsize; i++)544__set_bit(kpad->gpimap[i].sw_evt, input->swbit);545546error = input_register_device(input);547if (error) {548dev_err(&client->dev, "unable to register input device\n");549goto err_free_mem;550}551552error = request_irq(client->irq, adp5588_irq,553IRQF_TRIGGER_FALLING | IRQF_DISABLED,554client->dev.driver->name, kpad);555if (error) {556dev_err(&client->dev, "irq %d busy?\n", client->irq);557goto err_unreg_dev;558}559560error = adp5588_setup(client);561if (error)562goto err_free_irq;563564if (kpad->gpimapsize)565adp5588_report_switch_state(kpad);566567error = adp5588_gpio_add(kpad);568if (error)569goto err_free_irq;570571device_init_wakeup(&client->dev, 1);572i2c_set_clientdata(client, kpad);573574dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);575return 0;576577err_free_irq:578free_irq(client->irq, kpad);579err_unreg_dev:580input_unregister_device(input);581input = NULL;582err_free_mem:583input_free_device(input);584kfree(kpad);585586return error;587}588589static int __devexit adp5588_remove(struct i2c_client *client)590{591struct adp5588_kpad *kpad = i2c_get_clientdata(client);592593adp5588_write(client, CFG, 0);594free_irq(client->irq, kpad);595cancel_delayed_work_sync(&kpad->work);596input_unregister_device(kpad->input);597adp5588_gpio_remove(kpad);598kfree(kpad);599600return 0;601}602603#ifdef CONFIG_PM604static int adp5588_suspend(struct device *dev)605{606struct adp5588_kpad *kpad = dev_get_drvdata(dev);607struct i2c_client *client = kpad->client;608609disable_irq(client->irq);610cancel_delayed_work_sync(&kpad->work);611612if (device_may_wakeup(&client->dev))613enable_irq_wake(client->irq);614615return 0;616}617618static int adp5588_resume(struct device *dev)619{620struct adp5588_kpad *kpad = dev_get_drvdata(dev);621struct i2c_client *client = kpad->client;622623if (device_may_wakeup(&client->dev))624disable_irq_wake(client->irq);625626enable_irq(client->irq);627628return 0;629}630631static const struct dev_pm_ops adp5588_dev_pm_ops = {632.suspend = adp5588_suspend,633.resume = adp5588_resume,634};635#endif636637static const struct i2c_device_id adp5588_id[] = {638{ "adp5588-keys", 0 },639{ "adp5587-keys", 0 },640{ }641};642MODULE_DEVICE_TABLE(i2c, adp5588_id);643644static struct i2c_driver adp5588_driver = {645.driver = {646.name = KBUILD_MODNAME,647#ifdef CONFIG_PM648.pm = &adp5588_dev_pm_ops,649#endif650},651.probe = adp5588_probe,652.remove = __devexit_p(adp5588_remove),653.id_table = adp5588_id,654};655656static int __init adp5588_init(void)657{658return i2c_add_driver(&adp5588_driver);659}660module_init(adp5588_init);661662static void __exit adp5588_exit(void)663{664i2c_del_driver(&adp5588_driver);665}666module_exit(adp5588_exit);667668MODULE_LICENSE("GPL");669MODULE_AUTHOR("Michael Hennerich <[email protected]>");670MODULE_DESCRIPTION("ADP5588/87 Keypad driver");671MODULE_ALIAS("platform:adp5588-keys");672673674