summaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r--drivers/input/keyboard/Kconfig43
-rw-r--r--drivers/input/keyboard/Makefile2
-rw-r--r--drivers/input/keyboard/adc-keys.c36
-rw-r--r--drivers/input/keyboard/adp5589-keys.c171
-rw-r--r--drivers/input/keyboard/applespi.c30
-rw-r--r--drivers/input/keyboard/bcm-keypad.c4
-rw-r--r--drivers/input/keyboard/clps711x-keypad.c70
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c6
-rw-r--r--drivers/input/keyboard/davinci_keyscan.c1
-rw-r--r--drivers/input/keyboard/goldfish_events.c2
-rw-r--r--drivers/input/keyboard/gpio_keys.c21
-rw-r--r--drivers/input/keyboard/gpio_keys_polled.c74
-rw-r--r--drivers/input/keyboard/imx_keypad.c4
-rw-r--r--drivers/input/keyboard/imx_sc_key.c193
-rw-r--r--drivers/input/keyboard/jornada680_kbd.c37
-rw-r--r--drivers/input/keyboard/lpc32xx-keys.c4
-rw-r--r--drivers/input/keyboard/mpr121_touchkey.c72
-rw-r--r--drivers/input/keyboard/nomadik-ske-keypad.c4
-rw-r--r--drivers/input/keyboard/nspire-keypad.c4
-rw-r--r--drivers/input/keyboard/opencores-kbd.c4
-rw-r--r--drivers/input/keyboard/pmic8xxx-keypad.c8
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c4
-rw-r--r--drivers/input/keyboard/pxa930_rotary.c6
-rw-r--r--drivers/input/keyboard/sh_keysc.c6
-rw-r--r--drivers/input/keyboard/snvs_pwrkey.c52
-rw-r--r--drivers/input/keyboard/spear-keyboard.c4
-rw-r--r--drivers/input/keyboard/st-keyscan.c4
-rw-r--r--drivers/input/keyboard/tca6416-keypad.c4
-rw-r--r--drivers/input/keyboard/tegra-kbc.c4
-rw-r--r--drivers/input/keyboard/w90p910_keypad.c264
30 files changed, 537 insertions, 601 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 90e8a7f2f07c..4706ff09f0e8 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -16,7 +16,6 @@ if INPUT_KEYBOARD
config KEYBOARD_ADC
tristate "ADC Ladder Buttons"
depends on IIO
- select INPUT_POLLDEV
help
This driver implements support for buttons connected
to an ADC using a resistor ladder.
@@ -168,14 +167,14 @@ config KEYBOARD_QT1050
the module will be called qt1050
config KEYBOARD_QT1070
- tristate "Atmel AT42QT1070 Touch Sensor Chip"
- depends on I2C
- help
- Say Y here if you want to use Atmel AT42QT1070 QTouch
- Sensor chip as input device.
+ tristate "Atmel AT42QT1070 Touch Sensor Chip"
+ depends on I2C
+ help
+ Say Y here if you want to use Atmel AT42QT1070 QTouch
+ Sensor chip as input device.
- To compile this driver as a module, choose M here:
- the module will be called qt1070
+ To compile this driver as a module, choose M here:
+ the module will be called qt1070
config KEYBOARD_QT2160
tristate "Atmel AT42QT2160 Touch Sensor Chip"
@@ -191,7 +190,6 @@ config KEYBOARD_CLPS711X
tristate "CLPS711X Keypad support"
depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST)
select INPUT_MATRIXKMAP
- select INPUT_POLLDEV
help
Say Y here to enable the matrix keypad on the Cirrus Logic
CLPS711X CPUs.
@@ -250,7 +248,6 @@ config KEYBOARD_GPIO
config KEYBOARD_GPIO_POLLED
tristate "Polled GPIO buttons"
depends on GPIOLIB
- select INPUT_POLLDEV
help
This driver implements support for buttons connected
to GPIO pins that are not capable of generating interrupts.
@@ -342,7 +339,6 @@ config KEYBOARD_HIL
config KEYBOARD_HP6XX
tristate "HP Jornada 6xx keyboard"
depends on SH_HP6XX
- select INPUT_POLLDEV
help
Say Y here if you have a HP Jornada 620/660/680/690 and want to
support the built-in keyboard.
@@ -454,7 +450,7 @@ config KEYBOARD_SNVS_PWRKEY
depends on OF
help
This is the snvs powerkey driver for the Freescale i.MX application
- processors that are newer than i.MX6 SX.
+ processors.
To compile this driver as a module, choose M here; the
module will be called snvs_pwrkey.
@@ -469,6 +465,16 @@ config KEYBOARD_IMX
To compile this driver as a module, choose M here: the
module will be called imx_keypad.
+config KEYBOARD_IMX_SC_KEY
+ tristate "IMX SCU Key Driver"
+ depends on IMX_SCU
+ help
+ This is the system controller key driver for NXP i.MX SoCs with
+ system controller inside.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx_sc_key.
+
config KEYBOARD_NEWTON
tristate "Newton keyboard"
select SERIO
@@ -733,21 +739,10 @@ config KEYBOARD_XTKBD
To compile this driver as a module, choose M here: the
module will be called xtkbd.
-config KEYBOARD_W90P910
- tristate "W90P910 Matrix Keypad support"
- depends on ARCH_W90X900
- select INPUT_MATRIXKMAP
- help
- Say Y here to enable the matrix keypad on evaluation board
- based on W90P910.
-
- To compile this driver as a module, choose M here: the
- module will be called w90p910_keypad.
-
config KEYBOARD_CROS_EC
tristate "ChromeOS EC keyboard"
select INPUT_MATRIXKMAP
- depends on MFD_CROS_EC
+ depends on CROS_EC
help
Say Y here to enable the matrix keyboard used by ChromeOS devices
and implemented on the ChromeOS EC. You must enable one bus option
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 06a0af6efeae..f5b17524adf2 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o
obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o
+obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
@@ -68,4 +69,3 @@ obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
-obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c
index 9885fd56f5f9..6d5be48d1b3d 100644
--- a/drivers/input/keyboard/adc-keys.c
+++ b/drivers/input/keyboard/adc-keys.c
@@ -9,7 +9,6 @@
#include <linux/iio/consumer.h>
#include <linux/iio/types.h>
#include <linux/input.h>
-#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -30,9 +29,9 @@ struct adc_keys_state {
const struct adc_keys_button *map;
};
-static void adc_keys_poll(struct input_polled_dev *dev)
+static void adc_keys_poll(struct input_dev *input)
{
- struct adc_keys_state *st = dev->private;
+ struct adc_keys_state *st = input_get_drvdata(input);
int i, value, ret;
u32 diff, closest = 0xffffffff;
int keycode = 0;
@@ -55,12 +54,12 @@ static void adc_keys_poll(struct input_polled_dev *dev)
keycode = 0;
if (st->last_key && st->last_key != keycode)
- input_report_key(dev->input, st->last_key, 0);
+ input_report_key(input, st->last_key, 0);
if (keycode)
- input_report_key(dev->input, keycode, 1);
+ input_report_key(input, keycode, 1);
- input_sync(dev->input);
+ input_sync(input);
st->last_key = keycode;
}
@@ -108,7 +107,6 @@ static int adc_keys_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct adc_keys_state *st;
- struct input_polled_dev *poll_dev;
struct input_dev *input;
enum iio_chan_type type;
int i, value;
@@ -145,19 +143,13 @@ static int adc_keys_probe(struct platform_device *pdev)
if (error)
return error;
- poll_dev = devm_input_allocate_polled_device(dev);
- if (!poll_dev) {
+ input = devm_input_allocate_device(dev);
+ if (!input) {
dev_err(dev, "failed to allocate input device\n");
return -ENOMEM;
}
- if (!device_property_read_u32(dev, "poll-interval", &value))
- poll_dev->poll_interval = value;
-
- poll_dev->poll = adc_keys_poll;
- poll_dev->private = st;
-
- input = poll_dev->input;
+ input_set_drvdata(input, st);
input->name = pdev->name;
input->phys = "adc-keys/input0";
@@ -174,7 +166,17 @@ static int adc_keys_probe(struct platform_device *pdev)
if (device_property_read_bool(dev, "autorepeat"))
__set_bit(EV_REP, input->evbit);
- error = input_register_polled_device(poll_dev);
+
+ error = input_setup_polling(input, adc_keys_poll);
+ if (error) {
+ dev_err(dev, "Unable to set up polling: %d\n", error);
+ return error;
+ }
+
+ if (!device_property_read_u32(dev, "poll-interval", &value))
+ input_set_poll_interval(input, value);
+
+ error = input_register_device(input);
if (error) {
dev_err(dev, "Unable to register input device: %d\n", error);
return error;
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 4f96a4a99e5b..e7d58e7f0257 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
input_sync(kpad->input);
}
-static int adp5589_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
{
- struct adp5589_kpad *kpad;
+ struct i2c_client *client = kpad->client;
const struct adp5589_kpad_platform_data *pdata =
dev_get_platdata(&client->dev);
struct input_dev *input;
- unsigned int revid;
- int ret, i;
+ unsigned int i;
int error;
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_BYTE_DATA)) {
- dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
- return -EIO;
- }
-
- if (!pdata) {
- dev_err(&client->dev, "no platform data?\n");
- return -EINVAL;
- }
-
- kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
- if (!kpad)
- return -ENOMEM;
-
- switch (id->driver_data) {
- case ADP5585_02:
- kpad->support_row5 = true;
- /* fall through */
- case ADP5585_01:
- kpad->is_adp5585 = true;
- kpad->var = &const_adp5585;
- break;
- case ADP5589:
- kpad->support_row5 = true;
- kpad->var = &const_adp5589;
- break;
- }
-
if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
!pdata->keymap) {
dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
if (pdata->keymapsize != kpad->var->keymapsize) {
dev_err(&client->dev, "invalid keymapsize\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
if (!pdata->gpimap && pdata->gpimapsize) {
dev_err(&client->dev, "invalid gpimap from pdata\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
dev_err(&client->dev, "invalid gpimapsize\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
for (i = 0; i < pdata->gpimapsize; i++) {
@@ -929,41 +894,27 @@ static int adp5589_probe(struct i2c_client *client,
if (pin < kpad->var->gpi_pin_base ||
pin > kpad->var->gpi_pin_end) {
dev_err(&client->dev, "invalid gpi pin data\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
pdata->keypad_en_mask) {
dev_err(&client->dev, "invalid gpi row/col data\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
}
if (!client->irq) {
dev_err(&client->dev, "no IRQ?\n");
- error = -EINVAL;
- goto err_free_mem;
+ return -EINVAL;
}
input = input_allocate_device();
- if (!input) {
- error = -ENOMEM;
- goto err_free_mem;
- }
+ if (!input)
+ return -ENOMEM;
- kpad->client = client;
kpad->input = input;
- ret = adp5589_read(client, ADP5589_5_ID);
- if (ret < 0) {
- error = ret;
- goto err_free_input;
- }
-
- revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
-
input->name = client->name;
input->phys = "adp5589-keys/input0";
input->dev.parent = &client->dev;
@@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client,
goto err_unreg_dev;
}
+ device_init_wakeup(&client->dev, 1);
+
+ return 0;
+
+err_unreg_dev:
+ input_unregister_device(input);
+ input = NULL;
+err_free_input:
+ input_free_device(input);
+
+ return error;
+}
+
+static void adp5589_keypad_remove(struct adp5589_kpad *kpad)
+{
+ if (kpad->input) {
+ free_irq(kpad->client->irq, kpad);
+ input_unregister_device(kpad->input);
+ }
+}
+
+static int adp5589_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adp5589_kpad *kpad;
+ const struct adp5589_kpad_platform_data *pdata =
+ dev_get_platdata(&client->dev);
+ unsigned int revid;
+ int error, ret;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+ return -EIO;
+ }
+
+ if (!pdata) {
+ dev_err(&client->dev, "no platform data?\n");
+ return -EINVAL;
+ }
+
+ kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
+ if (!kpad)
+ return -ENOMEM;
+
+ kpad->client = client;
+
+ switch (id->driver_data) {
+ case ADP5585_02:
+ kpad->support_row5 = true;
+ /* fall through */
+ case ADP5585_01:
+ kpad->is_adp5585 = true;
+ kpad->var = &const_adp5585;
+ break;
+ case ADP5589:
+ kpad->support_row5 = true;
+ kpad->var = &const_adp5589;
+ break;
+ }
+
+ ret = adp5589_read(client, ADP5589_5_ID);
+ if (ret < 0) {
+ error = ret;
+ goto err_free_mem;
+ }
+
+ revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
+
+ if (pdata->keymapsize) {
+ error = adp5589_keypad_add(kpad, revid);
+ if (error)
+ goto err_free_mem;
+ }
+
error = adp5589_setup(kpad);
if (error)
- goto err_free_irq;
+ goto err_keypad_remove;
if (kpad->gpimapsize)
adp5589_report_switch_state(kpad);
error = adp5589_gpio_add(kpad);
if (error)
- goto err_free_irq;
+ goto err_keypad_remove;
- device_init_wakeup(&client->dev, 1);
i2c_set_clientdata(client, kpad);
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
return 0;
-err_free_irq:
- free_irq(client->irq, kpad);
-err_unreg_dev:
- input_unregister_device(input);
- input = NULL;
-err_free_input:
- input_free_device(input);
+err_keypad_remove:
+ adp5589_keypad_remove(kpad);
err_free_mem:
kfree(kpad);
@@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client)
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
- free_irq(client->irq, kpad);
- input_unregister_device(kpad->input);
+ adp5589_keypad_remove(kpad);
adp5589_gpio_remove(kpad);
kfree(kpad);
@@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev)
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
struct i2c_client *client = kpad->client;
+ if (!kpad->input)
+ return 0;
+
disable_irq(client->irq);
if (device_may_wakeup(&client->dev))
@@ -1077,6 +1099,9 @@ static int adp5589_resume(struct device *dev)
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
struct i2c_client *client = kpad->client;
+ if (!kpad->input)
+ return 0;
+
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c
index 584289b67fb3..d38398526965 100644
--- a/drivers/input/keyboard/applespi.c
+++ b/drivers/input/keyboard/applespi.c
@@ -1797,30 +1797,12 @@ static int applespi_probe(struct spi_device *spi)
/* set up debugfs entries for touchpad dimensions logging */
applespi->debugfs_root = debugfs_create_dir("applespi", NULL);
- if (IS_ERR(applespi->debugfs_root)) {
- if (PTR_ERR(applespi->debugfs_root) != -ENODEV)
- dev_warn(&applespi->spi->dev,
- "Error creating debugfs root entry (%ld)\n",
- PTR_ERR(applespi->debugfs_root));
- } else {
- struct dentry *ret;
-
- ret = debugfs_create_bool("enable_tp_dim", 0600,
- applespi->debugfs_root,
- &applespi->debug_tp_dim);
- if (IS_ERR(ret))
- dev_dbg(&applespi->spi->dev,
- "Error creating debugfs entry enable_tp_dim (%ld)\n",
- PTR_ERR(ret));
-
- ret = debugfs_create_file("tp_dim", 0400,
- applespi->debugfs_root, applespi,
- &applespi_tp_dim_fops);
- if (IS_ERR(ret))
- dev_dbg(&applespi->spi->dev,
- "Error creating debugfs entry tp_dim (%ld)\n",
- PTR_ERR(ret));
- }
+
+ debugfs_create_bool("enable_tp_dim", 0600, applespi->debugfs_root,
+ &applespi->debug_tp_dim);
+
+ debugfs_create_file("tp_dim", 0400, applespi->debugfs_root, applespi,
+ &applespi_tp_dim_fops);
return 0;
}
diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c
index e1cf63ee148f..2b771c3a5578 100644
--- a/drivers/input/keyboard/bcm-keypad.c
+++ b/drivers/input/keyboard/bcm-keypad.c
@@ -413,10 +413,8 @@ static int bcm_kp_probe(struct platform_device *pdev)
bcm_kp_stop(kp);
kp->irq = platform_get_irq(pdev, 0);
- if (kp->irq < 0) {
- dev_err(&pdev->dev, "no IRQ specified\n");
+ if (kp->irq < 0)
return -EINVAL;
- }
error = devm_request_threaded_irq(&pdev->dev, kp->irq,
NULL, bcm_kp_isr_thread,
diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c
index c4a5c07a4b98..019dd6ed2c29 100644
--- a/drivers/input/keyboard/clps711x-keypad.c
+++ b/drivers/input/keyboard/clps711x-keypad.c
@@ -6,7 +6,6 @@
*/
#include <linux/input.h>
-#include <linux/input-polldev.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
@@ -30,10 +29,10 @@ struct clps711x_keypad_data {
struct clps711x_gpio_data *gpio_data;
};
-static void clps711x_keypad_poll(struct input_polled_dev *dev)
+static void clps711x_keypad_poll(struct input_dev *input)
{
- const unsigned short *keycodes = dev->input->keycode;
- struct clps711x_keypad_data *priv = dev->private;
+ const unsigned short *keycodes = input->keycode;
+ struct clps711x_keypad_data *priv = input_get_drvdata(input);
bool sync = false;
int col, row;
@@ -61,14 +60,14 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev)
if (state) {
set_bit(col, data->last_state);
- input_event(dev->input, EV_MSC,
- MSC_SCAN, code);
+ input_event(input,
+ EV_MSC, MSC_SCAN, code);
} else {
clear_bit(col, data->last_state);
}
if (keycodes[code])
- input_report_key(dev->input,
+ input_report_key(input,
keycodes[code], state);
sync = true;
}
@@ -80,7 +79,7 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev)
}
if (sync)
- input_sync(dev->input);
+ input_sync(input);
}
static int clps711x_keypad_probe(struct platform_device *pdev)
@@ -88,7 +87,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
struct clps711x_keypad_data *priv;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- struct input_polled_dev *poll_dev;
+ struct input_dev *input;
u32 poll_interval;
int i, err;
@@ -125,53 +124,43 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
if (err)
return err;
- poll_dev = input_allocate_polled_device();
- if (!poll_dev)
+ input = devm_input_allocate_device(dev);
+ if (!input)
return -ENOMEM;
- poll_dev->private = priv;
- poll_dev->poll = clps711x_keypad_poll;
- poll_dev->poll_interval = poll_interval;
- poll_dev->input->name = pdev->name;
- poll_dev->input->dev.parent = dev;
- poll_dev->input->id.bustype = BUS_HOST;
- poll_dev->input->id.vendor = 0x0001;
- poll_dev->input->id.product = 0x0001;
- poll_dev->input->id.version = 0x0100;
+ input_set_drvdata(input, priv);
+
+ input->name = pdev->name;
+ input->dev.parent = dev;
+ input->id.bustype = BUS_HOST;
+ input->id.vendor = 0x0001;
+ input->id.product = 0x0001;
+ input->id.version = 0x0100;
err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count,
CLPS711X_KEYPAD_COL_COUNT,
- NULL, poll_dev->input);
+ NULL, input);
if (err)
- goto out_err;
+ return err;
- input_set_capability(poll_dev->input, EV_MSC, MSC_SCAN);
+ input_set_capability(input, EV_MSC, MSC_SCAN);
if (of_property_read_bool(np, "autorepeat"))
- __set_bit(EV_REP, poll_dev->input->evbit);
-
- platform_set_drvdata(pdev, poll_dev);
+ __set_bit(EV_REP, input->evbit);
/* Set all columns to low */
regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK,
SYSCON1_KBDSCAN(1));
- err = input_register_polled_device(poll_dev);
- if (err)
- goto out_err;
-
- return 0;
-out_err:
- input_free_polled_device(poll_dev);
- return err;
-}
+ err = input_setup_polling(input, clps711x_keypad_poll);
+ if (err)
+ return err;
-static int clps711x_keypad_remove(struct platform_device *pdev)
-{
- struct input_polled_dev *poll_dev = platform_get_drvdata(pdev);
+ input_set_poll_interval(input, poll_interval);
- input_unregister_polled_device(poll_dev);
- input_free_polled_device(poll_dev);
+ err = input_register_device(input);
+ if (err)
+ return err;
return 0;
}
@@ -188,7 +177,6 @@ static struct platform_driver clps711x_keypad_driver = {
.of_match_table = clps711x_keypad_of_match,
},
.probe = clps711x_keypad_probe,
- .remove = clps711x_keypad_remove,
};
module_platform_driver(clps711x_keypad_driver);
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 38cb6d82d8fe..2b71c5a51f90 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -22,8 +22,8 @@
#include <linux/slab.h>
#include <linux/sysrq.h>
#include <linux/input/matrix_keypad.h>
-#include <linux/mfd/cros_ec.h>
-#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_data/cros_ec_commands.h>
+#include <linux/platform_data/cros_ec_proto.h>
#include <asm/unaligned.h>
@@ -237,7 +237,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
if (queued_during_suspend && !device_may_wakeup(ckdev->dev))
return NOTIFY_OK;
- switch (ckdev->ec->event_data.event_type & EC_MKBP_EVENT_TYPE_MASK) {
+ switch (ckdev->ec->event_data.event_type) {
case EC_MKBP_EVENT_KEY_MATRIX:
pm_wakeup_event(ckdev->dev, 0);
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index 1d94928db922..f489cd585b33 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -192,7 +192,6 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
davinci_ks->irq = platform_get_irq(pdev, 0);
if (davinci_ks->irq < 0) {
- dev_err(dev, "no key scan irq\n");
error = davinci_ks->irq;
goto fail2;
}
diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c
index bc8c85a52a10..57d435fc5c73 100644
--- a/drivers/input/keyboard/goldfish_events.c
+++ b/drivers/input/keyboard/goldfish_events.c
@@ -30,7 +30,7 @@ struct event_dev {
struct input_dev *input;
int irq;
void __iomem *addr;
- char name[0];
+ char name[];
};
static irqreturn_t events_interrupt(int irq, void *dev_id)
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 03f4d152f6b7..53c9ff338dea 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -55,7 +55,7 @@ struct gpio_keys_drvdata {
struct input_dev *input;
struct mutex disable_lock;
unsigned short *keymap;
- struct gpio_button_data data[0];
+ struct gpio_button_data data[];
};
/*
@@ -351,10 +351,7 @@ static struct attribute *gpio_keys_attrs[] = {
&dev_attr_disabled_switches.attr,
NULL,
};
-
-static const struct attribute_group gpio_keys_attr_group = {
- .attrs = gpio_keys_attrs,
-};
+ATTRIBUTE_GROUPS(gpio_keys);
static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
{
@@ -497,10 +494,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
spin_lock_init(&bdata->lock);
if (child) {
- bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL,
- child,
- GPIOD_IN,
- desc);
+ bdata->gpiod = devm_fwnode_gpiod_get(dev, child,
+ NULL, GPIOD_IN, desc);
if (IS_ERR(bdata->gpiod)) {
error = PTR_ERR(bdata->gpiod);
if (error == -ENOENT) {
@@ -851,13 +846,6 @@ static int gpio_keys_probe(struct platform_device *pdev)
fwnode_handle_put(child);
- error = devm_device_add_group(dev, &gpio_keys_attr_group);
- if (error) {
- dev_err(dev, "Unable to export keys/switches, error: %d\n",
- error);
- return error;
- }
-
error = input_register_device(input);
if (error) {
dev_err(dev, "Unable to register input device, error: %d\n",
@@ -1026,6 +1014,7 @@ static struct platform_driver gpio_keys_device_driver = {
.name = "gpio-keys",
.pm = &gpio_keys_pm_ops,
.of_match_table = gpio_keys_of_match,
+ .dev_groups = gpio_keys_groups,
}
};
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 465eecfa6b3f..c3937d2fc744 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -16,7 +16,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
-#include <linux/input-polldev.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
@@ -34,20 +33,19 @@ struct gpio_keys_button_data {
};
struct gpio_keys_polled_dev {
- struct input_polled_dev *poll_dev;
+ struct input_dev *input;
struct device *dev;
const struct gpio_keys_platform_data *pdata;
unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)];
unsigned long abs_axis_seen[BITS_TO_LONGS(ABS_CNT)];
- struct gpio_keys_button_data data[0];
+ struct gpio_keys_button_data data[];
};
-static void gpio_keys_button_event(struct input_polled_dev *dev,
+static void gpio_keys_button_event(struct input_dev *input,
const struct gpio_keys_button *button,
int state)
{
- struct gpio_keys_polled_dev *bdev = dev->private;
- struct input_dev *input = dev->input;
+ struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
unsigned int type = button->type ?: EV_KEY;
if (type == EV_REL) {
@@ -66,7 +64,7 @@ static void gpio_keys_button_event(struct input_polled_dev *dev,
}
}
-static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
+static void gpio_keys_polled_check_state(struct input_dev *input,
const struct gpio_keys_button *button,
struct gpio_keys_button_data *bdata)
{
@@ -74,10 +72,10 @@ static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
state = gpiod_get_value_cansleep(bdata->gpiod);
if (state < 0) {
- dev_err(dev->input->dev.parent,
+ dev_err(input->dev.parent,
"failed to get gpio state: %d\n", state);
} else {
- gpio_keys_button_event(dev, button, state);
+ gpio_keys_button_event(input, button, state);
if (state != bdata->last_state) {
bdata->count = 0;
@@ -86,11 +84,10 @@ static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
}
}
-static void gpio_keys_polled_poll(struct input_polled_dev *dev)
+static void gpio_keys_polled_poll(struct input_dev *input)
{
- struct gpio_keys_polled_dev *bdev = dev->private;
+ struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
const struct gpio_keys_platform_data *pdata = bdev->pdata;
- struct input_dev *input = dev->input;
int i;
memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen));
@@ -101,10 +98,10 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
if (bdata->count < bdata->threshold) {
bdata->count++;
- gpio_keys_button_event(dev, &pdata->buttons[i],
+ gpio_keys_button_event(input, &pdata->buttons[i],
bdata->last_state);
} else {
- gpio_keys_polled_check_state(dev, &pdata->buttons[i],
+ gpio_keys_polled_check_state(input, &pdata->buttons[i],
bdata);
}
}
@@ -122,18 +119,20 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
input_sync(input);
}
-static void gpio_keys_polled_open(struct input_polled_dev *dev)
+static int gpio_keys_polled_open(struct input_dev *input)
{
- struct gpio_keys_polled_dev *bdev = dev->private;
+ struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
const struct gpio_keys_platform_data *pdata = bdev->pdata;
if (pdata->enable)
pdata->enable(bdev->dev);
+
+ return 0;
}
-static void gpio_keys_polled_close(struct input_polled_dev *dev)
+static void gpio_keys_polled_close(struct input_dev *input)
{
- struct gpio_keys_polled_dev *bdev = dev->private;
+ struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
const struct gpio_keys_platform_data *pdata = bdev->pdata;
if (pdata->disable)
@@ -232,7 +231,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
struct fwnode_handle *child = NULL;
const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
struct gpio_keys_polled_dev *bdev;
- struct input_polled_dev *poll_dev;
struct input_dev *input;
int error;
int i;
@@ -255,19 +253,13 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
return -ENOMEM;
}
- poll_dev = devm_input_allocate_polled_device(dev);
- if (!poll_dev) {
- dev_err(dev, "no memory for polled device\n");
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(dev, "no memory for input device\n");
return -ENOMEM;
}
- poll_dev->private = bdev;
- poll_dev->poll = gpio_keys_polled_poll;
- poll_dev->poll_interval = pdata->poll_interval;
- poll_dev->open = gpio_keys_polled_open;
- poll_dev->close = gpio_keys_polled_close;
-
- input = poll_dev->input;
+ input_set_drvdata(input, bdev);
input->name = pdata->name ?: pdev->name;
input->phys = DRV_NAME"/input0";
@@ -277,6 +269,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
input->id.product = 0x0001;
input->id.version = 0x0100;
+ input->open = gpio_keys_polled_open;
+ input->close = gpio_keys_polled_close;
+
__set_bit(EV_KEY, input->evbit);
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
@@ -300,10 +295,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
return -EINVAL;
}
- bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev,
- NULL, child,
- GPIOD_IN,
- button->desc);
+ bdata->gpiod = devm_fwnode_gpiod_get(dev, child,
+ NULL, GPIOD_IN,
+ button->desc);
if (IS_ERR(bdata->gpiod)) {
error = PTR_ERR(bdata->gpiod);
if (error != -EPROBE_DEFER)
@@ -353,11 +347,19 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
fwnode_handle_put(child);
- bdev->poll_dev = poll_dev;
+ bdev->input = input;
bdev->dev = dev;
bdev->pdata = pdata;
- error = input_register_polled_device(poll_dev);
+ error = input_setup_polling(input, gpio_keys_polled_poll);
+ if (error) {
+ dev_err(dev, "unable to set up polling, err=%d\n", error);
+ return error;
+ }
+
+ input_set_poll_interval(input, pdata->poll_interval);
+
+ error = input_register_device(input);
if (error) {
dev_err(dev, "unable to register polled device, err=%d\n",
error);
@@ -366,7 +368,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
/* report initial state of the buttons */
for (i = 0; i < pdata->nbuttons; i++)
- gpio_keys_polled_check_state(poll_dev, &pdata->buttons[i],
+ gpio_keys_polled_check_state(input, &pdata->buttons[i],
&bdev->data[i]);
input_sync(input);
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 97500a2de2d5..5a46d113e909 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -430,10 +430,8 @@ static int imx_keypad_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "no irq defined in platform data\n");
+ if (irq < 0)
return irq;
- }
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev) {
diff --git a/drivers/input/keyboard/imx_sc_key.c b/drivers/input/keyboard/imx_sc_key.c
new file mode 100644
index 000000000000..9f809aeb785c
--- /dev/null
+++ b/drivers/input/keyboard/imx_sc_key.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP.
+ */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/firmware/imx/sci.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
+#define DEBOUNCE_TIME 30
+#define REPEAT_INTERVAL 60
+
+#define SC_IRQ_BUTTON 1
+#define SC_IRQ_GROUP_WAKE 3
+
+#define IMX_SC_MISC_FUNC_GET_BUTTON_STATUS 18
+
+struct imx_key_drv_data {
+ u32 keycode;
+ bool keystate; /* true: pressed, false: released */
+ struct delayed_work check_work;
+ struct input_dev *input;
+ struct imx_sc_ipc *key_ipc_handle;
+ struct notifier_block key_notifier;
+};
+
+struct imx_sc_msg_key {
+ struct imx_sc_rpc_msg hdr;
+ u32 state;
+};
+
+static int imx_sc_key_notify(struct notifier_block *nb,
+ unsigned long event, void *group)
+{
+ struct imx_key_drv_data *priv =
+ container_of(nb,
+ struct imx_key_drv_data,
+ key_notifier);
+
+ if ((event & SC_IRQ_BUTTON) && (*(u8 *)group == SC_IRQ_GROUP_WAKE)) {
+ schedule_delayed_work(&priv->check_work,
+ msecs_to_jiffies(DEBOUNCE_TIME));
+ pm_wakeup_event(priv->input->dev.parent, 0);
+ }
+
+ return 0;
+}
+
+static void imx_sc_check_for_events(struct work_struct *work)
+{
+ struct imx_key_drv_data *priv =
+ container_of(work,
+ struct imx_key_drv_data,
+ check_work.work);
+ struct input_dev *input = priv->input;
+ struct imx_sc_msg_key msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ bool state;
+ int error;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_MISC;
+ hdr->func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS;
+ hdr->size = 1;
+
+ error = imx_scu_call_rpc(priv->key_ipc_handle, &msg, true);
+ if (error) {
+ dev_err(&input->dev, "read imx sc key failed, error %d\n", error);
+ return;
+ }
+
+ /*
+ * The response data from SCU firmware is 4 bytes,
+ * but ONLY the first byte is the key state, other
+ * 3 bytes could be some dirty data, so we should
+ * ONLY take the first byte as key state.
+ */
+ state = (bool)(msg.state & 0xff);
+
+ if (state ^ priv->keystate) {
+ priv->keystate = state;
+ input_event(input, EV_KEY, priv->keycode, state);
+ input_sync(input);
+ if (!priv->keystate)
+ pm_relax(priv->input->dev.parent);
+ }
+
+ if (state)
+ schedule_delayed_work(&priv->check_work,
+ msecs_to_jiffies(REPEAT_INTERVAL));
+}
+
+static int imx_sc_key_probe(struct platform_device *pdev)
+{
+ struct imx_key_drv_data *priv;
+ struct input_dev *input;
+ int error;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ error = imx_scu_get_handle(&priv->key_ipc_handle);
+ if (error)
+ return error;
+
+ if (device_property_read_u32(&pdev->dev, "linux,keycodes",
+ &priv->keycode)) {
+ dev_err(&pdev->dev, "missing linux,keycodes property\n");
+ return -EINVAL;
+ }
+
+ INIT_DELAYED_WORK(&priv->check_work, imx_sc_check_for_events);
+
+ input = devm_input_allocate_device(&pdev->dev);
+ if (!input) {
+ dev_err(&pdev->dev, "failed to allocate the input device\n");
+ return -ENOMEM;
+ }
+
+ input->name = pdev->name;
+ input->phys = "imx-sc-key/input0";
+ input->id.bustype = BUS_HOST;
+
+ input_set_capability(input, EV_KEY, priv->keycode);
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(&pdev->dev, "failed to register input device\n");
+ return error;
+ }
+
+ priv->input = input;
+ platform_set_drvdata(pdev, priv);
+
+ error = imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
+ true);
+ if (error) {
+ dev_err(&pdev->dev, "failed to enable scu group irq\n");
+ return error;
+ }
+
+ priv->key_notifier.notifier_call = imx_sc_key_notify;
+ error = imx_scu_irq_register_notifier(&priv->key_notifier);
+ if (error) {
+ imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
+ false);
+ dev_err(&pdev->dev, "failed to register scu notifier\n");
+ return error;
+ }
+
+ return 0;
+}
+
+static int imx_sc_key_remove(struct platform_device *pdev)
+{
+ struct imx_key_drv_data *priv = platform_get_drvdata(pdev);
+
+ imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false);
+ imx_scu_irq_unregister_notifier(&priv->key_notifier);
+ cancel_delayed_work_sync(&priv->check_work);
+
+ return 0;
+}
+
+static const struct of_device_id imx_sc_key_ids[] = {
+ { .compatible = "fsl,imx-sc-key" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_sc_key_ids);
+
+static struct platform_driver imx_sc_key_driver = {
+ .driver = {
+ .name = "imx-sc-key",
+ .of_match_table = imx_sc_key_ids,
+ },
+ .probe = imx_sc_key_probe,
+ .remove = imx_sc_key_remove,
+};
+module_platform_driver(imx_sc_key_driver);
+
+MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
+MODULE_DESCRIPTION("i.MX System Controller Key Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
index 4232aa876d2e..7e35081393be 100644
--- a/drivers/input/keyboard/jornada680_kbd.c
+++ b/drivers/input/keyboard/jornada680_kbd.c
@@ -15,7 +15,6 @@
#include <linux/device.h>
#include <linux/input.h>
-#include <linux/input-polldev.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
@@ -64,7 +63,7 @@ static const unsigned short jornada_scancodes[] = {
#define JORNADA_SCAN_SIZE 18
struct jornadakbd {
- struct input_polled_dev *poll_dev;
+ struct input_dev *input;
unsigned short keymap[ARRAY_SIZE(jornada_scancodes)];
unsigned char length;
unsigned char old_scan[JORNADA_SCAN_SIZE];
@@ -73,7 +72,7 @@ struct jornadakbd {
static void jornada_parse_kbd(struct jornadakbd *jornadakbd)
{
- struct input_dev *input_dev = jornadakbd->poll_dev->input;
+ struct input_dev *input_dev = jornadakbd->input;
unsigned short *keymap = jornadakbd->keymap;
unsigned int sync_me = 0;
unsigned int i, j;
@@ -167,9 +166,9 @@ static void jornada_scan_keyb(unsigned char *s)
*s++ = __raw_readb(PHDR);
}
-static void jornadakbd680_poll(struct input_polled_dev *dev)
+static void jornadakbd680_poll(struct input_dev *input)
{
- struct jornadakbd *jornadakbd = dev->private;
+ struct jornadakbd *jornadakbd = input_get_drvdata(input);
jornada_scan_keyb(jornadakbd->new_scan);
jornada_parse_kbd(jornadakbd);
@@ -179,7 +178,6 @@ static void jornadakbd680_poll(struct input_polled_dev *dev)
static int jornada680kbd_probe(struct platform_device *pdev)
{
struct jornadakbd *jornadakbd;
- struct input_polled_dev *poll_dev;
struct input_dev *input_dev;
int i, error;
@@ -188,29 +186,24 @@ static int jornada680kbd_probe(struct platform_device *pdev)
if (!jornadakbd)
return -ENOMEM;
- poll_dev = devm_input_allocate_polled_device(&pdev->dev);
- if (!poll_dev) {
- dev_err(&pdev->dev, "failed to allocate polled input device\n");
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
return -ENOMEM;
}
- jornadakbd->poll_dev = poll_dev;
+ jornadakbd->input = input_dev;
memcpy(jornadakbd->keymap, jornada_scancodes,
sizeof(jornadakbd->keymap));
- poll_dev->private = jornadakbd;
- poll_dev->poll = jornadakbd680_poll;
- poll_dev->poll_interval = 50; /* msec */
-
- input_dev = poll_dev->input;
+ input_set_drvdata(input_dev, jornadakbd);
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
input_dev->name = "HP Jornada 680 keyboard";
input_dev->phys = "jornadakbd/input0";
input_dev->keycode = jornadakbd->keymap;
input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes);
- input_dev->dev.parent = &pdev->dev;
input_dev->id.bustype = BUS_HOST;
for (i = 0; i < 128; i++)
@@ -220,9 +213,17 @@ static int jornada680kbd_probe(struct platform_device *pdev)
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- error = input_register_polled_device(jornadakbd->poll_dev);
+ error = input_setup_polling(input_dev, jornadakbd680_poll);
+ if (error) {
+ dev_err(&pdev->dev, "failed to set up polling\n");
+ return error;
+ }
+
+ input_set_poll_interval(input_dev, 50 /* msec */);
+
+ error = input_register_device(input_dev);
if (error) {
- dev_err(&pdev->dev, "failed to register polled input device\n");
+ dev_err(&pdev->dev, "failed to register input device\n");
return error;
}
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index a34e3271b0c9..348af2aeb5de 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -172,10 +172,8 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get platform irq\n");
+ if (irq < 0)
return -EINVAL;
- }
kscandat = devm_kzalloc(&pdev->dev, sizeof(*kscandat),
GFP_KERNEL);
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index e9ceaa16b46a..40d6e5087cde 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -54,6 +54,9 @@
/* MPR121 has 12 keys */
#define MPR121_MAX_KEY_COUNT 12
+#define MPR121_MIN_POLL_INTERVAL 10
+#define MPR121_MAX_POLL_INTERVAL 200
+
struct mpr121_touchkey {
struct i2c_client *client;
struct input_dev *input_dev;
@@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
return vdd_supply;
}
-static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+static void mpr_touchkey_report(struct input_dev *dev)
{
- struct mpr121_touchkey *mpr121 = dev_id;
- struct i2c_client *client = mpr121->client;
+ struct mpr121_touchkey *mpr121 = input_get_drvdata(dev);
struct input_dev *input = mpr121->input_dev;
+ struct i2c_client *client = mpr121->client;
unsigned long bit_changed;
unsigned int key_num;
int reg;
@@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
if (reg < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", reg);
- goto out;
+ return;
}
reg <<= 8;
reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR);
if (reg < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", reg);
- goto out;
+ return;
}
reg &= TOUCH_STATUS_MASK;
@@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
}
input_sync(input);
+}
+
+static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+{
+ struct mpr121_touchkey *mpr121 = dev_id;
+
+ mpr_touchkey_report(mpr121->input_dev);
-out:
return IRQ_HANDLED;
}
@@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client,
int vdd_uv;
struct mpr121_touchkey *mpr121;
struct input_dev *input_dev;
+ u32 poll_interval = 0;
int error;
int i;
- if (!client->irq) {
- dev_err(dev, "irq number should not be zero\n");
- return -EINVAL;
- }
-
vdd_supply = mpr121_vdd_supply_init(dev);
if (IS_ERR(vdd_supply))
return PTR_ERR(vdd_supply);
@@ -253,8 +258,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
mpr121->client = client;
mpr121->input_dev = input_dev;
- mpr121->keycount = device_property_read_u32_array(dev, "linux,keycodes",
- NULL, 0);
+ mpr121->keycount = device_property_count_u32(dev, "linux,keycodes");
if (mpr121->keycount > MPR121_MAX_KEY_COUNT) {
dev_err(dev, "too many keys defined (%d)\n", mpr121->keycount);
return -EINVAL;
@@ -275,6 +279,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
if (device_property_read_bool(dev, "autorepeat"))
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+ input_set_drvdata(input_dev, mpr121);
input_dev->keycode = mpr121->keycodes;
input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
@@ -289,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client,
return error;
}
- error = devm_request_threaded_irq(dev, client->irq, NULL,
- mpr_touchkey_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- dev->driver->name, mpr121);
- if (error) {
- dev_err(dev, "Failed to register interrupt\n");
- return error;
+ device_property_read_u32(dev, "poll-interval", &poll_interval);
+
+ if (client->irq) {
+ error = devm_request_threaded_irq(dev, client->irq, NULL,
+ mpr_touchkey_interrupt,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ dev->driver->name, mpr121);
+ if (error) {
+ dev_err(dev, "Failed to register interrupt\n");
+ return error;
+ }
+ } else if (poll_interval) {
+ if (poll_interval < MPR121_MIN_POLL_INTERVAL)
+ return -EINVAL;
+
+ if (poll_interval > MPR121_MAX_POLL_INTERVAL)
+ return -EINVAL;
+
+ error = input_setup_polling(input_dev, mpr_touchkey_report);
+ if (error) {
+ dev_err(dev, "Failed to setup polling\n");
+ return error;
+ }
+
+ input_set_poll_interval(input_dev, poll_interval);
+ input_set_min_poll_interval(input_dev,
+ MPR121_MIN_POLL_INTERVAL);
+ input_set_max_poll_interval(input_dev,
+ MPR121_MAX_POLL_INTERVAL);
+ } else {
+ dev_err(dev,
+ "invalid IRQ number and polling not configured\n");
+ return -EINVAL;
}
error = input_register_device(input_dev);
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index fa265fdce2c4..608446e14614 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -235,10 +235,8 @@ static int __init ske_keypad_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get keypad irq\n");
+ if (irq < 0)
return -EINVAL;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c
index 57eac91ecd76..63d5e488137d 100644
--- a/drivers/input/keyboard/nspire-keypad.c
+++ b/drivers/input/keyboard/nspire-keypad.c
@@ -165,10 +165,8 @@ static int nspire_keypad_probe(struct platform_device *pdev)
int error;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get keypad irq\n");
+ if (irq < 0)
return -EINVAL;
- }
keypad = devm_kzalloc(&pdev->dev, sizeof(struct nspire_keypad),
GFP_KERNEL);
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c
index 159346cb4060..b0ea387414c1 100644
--- a/drivers/input/keyboard/opencores-kbd.c
+++ b/drivers/input/keyboard/opencores-kbd.c
@@ -49,10 +49,8 @@ static int opencores_kbd_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "missing board IRQ resource\n");
+ if (irq < 0)
return -EINVAL;
- }
opencores_kbd = devm_kzalloc(&pdev->dev, sizeof(*opencores_kbd),
GFP_KERNEL);
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index d529768a1d06..91d5811d6f0e 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -544,16 +544,12 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
}
kp->key_sense_irq = platform_get_irq(pdev, 0);
- if (kp->key_sense_irq < 0) {
- dev_err(&pdev->dev, "unable to get keypad sense irq\n");
+ if (kp->key_sense_irq < 0)
return kp->key_sense_irq;
- }
kp->key_stuck_irq = platform_get_irq(pdev, 1);
- if (kp->key_stuck_irq < 0) {
- dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
+ if (kp->key_stuck_irq < 0)
return kp->key_stuck_irq;
- }
kp->input->name = "PMIC8XXX keypad";
kp->input->phys = "pmic8xxx_keypad/input0";
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 39023664d2f2..7e65708b25a4 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -727,10 +727,8 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
return -EINVAL;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get keypad irq\n");
+ if (irq < 0)
return -ENXIO;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
index 585e7765cbf0..2fe9dcfe0a6f 100644
--- a/drivers/input/keyboard/pxa930_rotary.c
+++ b/drivers/input/keyboard/pxa930_rotary.c
@@ -89,10 +89,8 @@ static int pxa930_rotary_probe(struct platform_device *pdev)
int err;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "no irq for rotary controller\n");
+ if (irq < 0)
return -ENXIO;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -109,7 +107,7 @@ static int pxa930_rotary_probe(struct platform_device *pdev)
if (!r)
return -ENOMEM;
- r->mmio_base = ioremap_nocache(res->start, resource_size(res));
+ r->mmio_base = ioremap(res->start, resource_size(res));
if (r->mmio_base == NULL) {
dev_err(&pdev->dev, "failed to remap IO memory\n");
err = -ENXIO;
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index 08ba41a81f14..c155adebf96e 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -181,10 +181,8 @@ static int sh_keysc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get irq\n");
+ if (irq < 0)
goto err0;
- }
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL) {
@@ -197,7 +195,7 @@ static int sh_keysc_probe(struct platform_device *pdev)
memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata));
pdata = &priv->pdata;
- priv->iomem_base = ioremap_nocache(res->start, resource_size(res));
+ priv->iomem_base = ioremap(res->start, resource_size(res));
if (priv->iomem_base == NULL) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
error = -ENXIO;
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 5342d8d45f81..2f5e3ab5ed63 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -19,15 +19,16 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
-#define SNVS_LPSR_REG 0x4C /* LP Status Register */
-#define SNVS_LPCR_REG 0x38 /* LP Control Register */
-#define SNVS_HPSR_REG 0x14
-#define SNVS_HPSR_BTN BIT(6)
-#define SNVS_LPSR_SPO BIT(18)
-#define SNVS_LPCR_DEP_EN BIT(5)
+#define SNVS_HPVIDR1_REG 0xF8
+#define SNVS_LPSR_REG 0x4C /* LP Status Register */
+#define SNVS_LPCR_REG 0x38 /* LP Control Register */
+#define SNVS_HPSR_REG 0x14
+#define SNVS_HPSR_BTN BIT(6)
+#define SNVS_LPSR_SPO BIT(18)
+#define SNVS_LPCR_DEP_EN BIT(5)
-#define DEBOUNCE_TIME 30
-#define REPEAT_INTERVAL 60
+#define DEBOUNCE_TIME 30
+#define REPEAT_INTERVAL 60
struct pwrkey_drv_data {
struct regmap *snvs;
@@ -37,6 +38,7 @@ struct pwrkey_drv_data {
int wakeup;
struct timer_list check_timer;
struct input_dev *input;
+ u8 minor_rev;
};
static void imx_imx_snvs_check_for_events(struct timer_list *t)
@@ -67,13 +69,29 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = dev_id;
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
+ struct input_dev *input = pdata->input;
u32 lp_status;
- pm_wakeup_event(pdata->input->dev.parent, 0);
+ pm_wakeup_event(input->dev.parent, 0);
regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status);
- if (lp_status & SNVS_LPSR_SPO)
- mod_timer(&pdata->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
+ if (lp_status & SNVS_LPSR_SPO) {
+ if (pdata->minor_rev == 0) {
+ /*
+ * The first generation i.MX6 SoCs only sends an
+ * interrupt on button release. To mimic power-key
+ * usage, we'll prepend a press event.
+ */
+ input_report_key(input, pdata->keycode, 1);
+ input_sync(input);
+ input_report_key(input, pdata->keycode, 0);
+ input_sync(input);
+ pm_relax(input->dev.parent);
+ } else {
+ mod_timer(&pdata->check_timer,
+ jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
+ }
+ }
/* clear SPO status */
regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
@@ -90,10 +108,11 @@ static void imx_snvs_pwrkey_act(void *pdata)
static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
{
- struct pwrkey_drv_data *pdata = NULL;
- struct input_dev *input = NULL;
+ struct pwrkey_drv_data *pdata;
+ struct input_dev *input;
struct device_node *np;
int error;
+ u32 vid;
/* Get SNVS register Page */
np = pdev->dev.of_node;
@@ -118,10 +137,11 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
pdata->wakeup = of_property_read_bool(np, "wakeup-source");
pdata->irq = platform_get_irq(pdev, 0);
- if (pdata->irq < 0) {
- dev_err(&pdev->dev, "no irq defined in platform data\n");
+ if (pdata->irq < 0)
return -EINVAL;
- }
+
+ regmap_read(pdata->snvs, SNVS_HPVIDR1_REG, &vid);
+ pdata->minor_rev = vid & 0xff;
regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN);
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 7d25fa338ab4..9b8d78f87253 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -191,10 +191,8 @@ static int spear_kbd_probe(struct platform_device *pdev)
int error;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "not able to get irq for the device\n");
+ if (irq < 0)
return irq;
- }
kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL);
if (!kbd) {
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index f097128b93fe..27562cd67fb6 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -187,10 +187,8 @@ static int keyscan_probe(struct platform_device *pdev)
keyscan_stop(keypad_data);
keypad_data->irq = platform_get_irq(pdev, 0);
- if (keypad_data->irq < 0) {
- dev_err(&pdev->dev, "no IRQ specified\n");
+ if (keypad_data->irq < 0)
return -EINVAL;
- }
error = devm_request_irq(&pdev->dev, keypad_data->irq, keyscan_isr, 0,
pdev->name, keypad_data);
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index 2a14769de637..21758767ccf0 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -33,7 +33,7 @@ MODULE_DEVICE_TABLE(i2c, tca6416_id);
struct tca6416_drv_data {
struct input_dev *input;
- struct tca6416_button data[0];
+ struct tca6416_button data[];
};
struct tca6416_keypad_chip {
@@ -48,7 +48,7 @@ struct tca6416_keypad_chip {
int irqnum;
u16 pinmask;
bool use_polling;
- struct tca6416_button buttons[0];
+ struct tca6416_button buttons[];
};
static int tca6416_write_reg(struct tca6416_keypad_chip *chip, int reg, u16 val)
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index a37a7a9e9171..d34d6947960f 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -631,10 +631,8 @@ static int tegra_kbc_probe(struct platform_device *pdev)
return -EINVAL;
kbc->irq = platform_get_irq(pdev, 0);
- if (kbc->irq < 0) {
- dev_err(&pdev->dev, "failed to get keyboard IRQ\n");
+ if (kbc->irq < 0)
return -ENXIO;
- }
kbc->idev = devm_input_allocate_device(&pdev->dev);
if (!kbc->idev) {
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
deleted file mode 100644
index c88d05d6108a..000000000000
--- a/drivers/input/keyboard/w90p910_keypad.c
+++ /dev/null
@@ -1,264 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2008-2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/platform_data/keypad-w90p910.h>
-
-/* Keypad Interface Control Registers */
-#define KPI_CONF 0x00
-#define KPI_3KCONF 0x04
-#define KPI_LPCONF 0x08
-#define KPI_STATUS 0x0C
-
-#define IS1KEY (0x01 << 16)
-#define INTTR (0x01 << 21)
-#define KEY0R (0x0f << 3)
-#define KEY0C 0x07
-#define DEBOUNCE_BIT 0x08
-#define KSIZE0 (0x01 << 16)
-#define KSIZE1 (0x01 << 17)
-#define KPSEL (0x01 << 19)
-#define ENKP (0x01 << 18)
-
-#define KGET_RAW(n) (((n) & KEY0R) >> 3)
-#define KGET_COLUMN(n) ((n) & KEY0C)
-
-#define W90P910_NUM_ROWS 8
-#define W90P910_NUM_COLS 8
-#define W90P910_ROW_SHIFT 3
-
-struct w90p910_keypad {
- const struct w90p910_keypad_platform_data *pdata;
- struct clk *clk;
- struct input_dev *input_dev;
- void __iomem *mmio_base;
- int irq;
- unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS];
-};
-
-static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad,
- unsigned int status)
-{
- struct input_dev *input_dev = keypad->input_dev;
- unsigned int row = KGET_RAW(status);
- unsigned int col = KGET_COLUMN(status);
- unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT);
- unsigned int key = keypad->keymap[code];
-
- input_event(input_dev, EV_MSC, MSC_SCAN, code);
- input_report_key(input_dev, key, 1);
- input_sync(input_dev);
-
- input_event(input_dev, EV_MSC, MSC_SCAN, code);
- input_report_key(input_dev, key, 0);
- input_sync(input_dev);
-}
-
-static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id)
-{
- struct w90p910_keypad *keypad = dev_id;
- unsigned int kstatus, val;
-
- kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS);
-
- val = INTTR | IS1KEY;
-
- if (kstatus & val)
- w90p910_keypad_scan_matrix(keypad, kstatus);
-
- return IRQ_HANDLED;
-}
-
-static int w90p910_keypad_open(struct input_dev *dev)
-{
- struct w90p910_keypad *keypad = input_get_drvdata(dev);
- const struct w90p910_keypad_platform_data *pdata = keypad->pdata;
- unsigned int val, config;
-
- /* Enable unit clock */
- clk_enable(keypad->clk);
-
- val = __raw_readl(keypad->mmio_base + KPI_CONF);
- val |= (KPSEL | ENKP);
- val &= ~(KSIZE0 | KSIZE1);
-
- config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT);
-
- val |= config;
-
- __raw_writel(val, keypad->mmio_base + KPI_CONF);
-
- return 0;
-}
-
-static void w90p910_keypad_close(struct input_dev *dev)
-{
- struct w90p910_keypad *keypad = input_get_drvdata(dev);
-
- /* Disable clock unit */
- clk_disable(keypad->clk);
-}
-
-static int w90p910_keypad_probe(struct platform_device *pdev)
-{
- const struct w90p910_keypad_platform_data *pdata =
- dev_get_platdata(&pdev->dev);
- const struct matrix_keymap_data *keymap_data;
- struct w90p910_keypad *keypad;
- struct input_dev *input_dev;
- struct resource *res;
- int irq;
- int error;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data defined\n");
- return -EINVAL;
- }
-
- keymap_data = pdata->keymap_data;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get keypad irq\n");
- return -ENXIO;
- }
-
- keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!keypad || !input_dev) {
- dev_err(&pdev->dev, "failed to allocate driver data\n");
- error = -ENOMEM;
- goto failed_free;
- }
-
- keypad->pdata = pdata;
- keypad->input_dev = input_dev;
- keypad->irq = irq;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to get I/O memory\n");
- error = -ENXIO;
- goto failed_free;
- }
-
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to request I/O memory\n");
- error = -EBUSY;
- goto failed_free;
- }
-
- keypad->mmio_base = ioremap(res->start, resource_size(res));
- if (keypad->mmio_base == NULL) {
- dev_err(&pdev->dev, "failed to remap I/O memory\n");
- error = -ENXIO;
- goto failed_free_res;
- }
-
- keypad->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(keypad->clk)) {
- dev_err(&pdev->dev, "failed to get keypad clock\n");
- error = PTR_ERR(keypad->clk);
- goto failed_free_io;
- }
-
- /* set multi-function pin for w90p910 kpi. */
- mfp_set_groupi(&pdev->dev);
-
- input_dev->name = pdev->name;
- input_dev->id.bustype = BUS_HOST;
- input_dev->open = w90p910_keypad_open;
- input_dev->close = w90p910_keypad_close;
- input_dev->dev.parent = &pdev->dev;
-
- error = matrix_keypad_build_keymap(keymap_data, NULL,
- W90P910_NUM_ROWS, W90P910_NUM_COLS,
- keypad->keymap, input_dev);
- if (error) {
- dev_err(&pdev->dev, "failed to build keymap\n");
- goto failed_put_clk;
- }
-
- error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
- 0, pdev->name, keypad);
- if (error) {
- dev_err(&pdev->dev, "failed to request IRQ\n");
- goto failed_put_clk;
- }
-
- __set_bit(EV_REP, input_dev->evbit);
- input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- input_set_drvdata(input_dev, keypad);
-
- /* Register the input device */
- error = input_register_device(input_dev);
- if (error) {
- dev_err(&pdev->dev, "failed to register input device\n");
- goto failed_free_irq;
- }
-
- platform_set_drvdata(pdev, keypad);
- return 0;
-
-failed_free_irq:
- free_irq(irq, keypad);
-failed_put_clk:
- clk_put(keypad->clk);
-failed_free_io:
- iounmap(keypad->mmio_base);
-failed_free_res:
- release_mem_region(res->start, resource_size(res));
-failed_free:
- input_free_device(input_dev);
- kfree(keypad);
- return error;
-}
-
-static int w90p910_keypad_remove(struct platform_device *pdev)
-{
- struct w90p910_keypad *keypad = platform_get_drvdata(pdev);
- struct resource *res;
-
- free_irq(keypad->irq, keypad);
-
- clk_put(keypad->clk);
-
- input_unregister_device(keypad->input_dev);
-
- iounmap(keypad->mmio_base);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
- kfree(keypad);
-
- return 0;
-}
-
-static struct platform_driver w90p910_keypad_driver = {
- .probe = w90p910_keypad_probe,
- .remove = w90p910_keypad_remove,
- .driver = {
- .name = "nuc900-kpi",
- },
-};
-module_platform_driver(w90p910_keypad_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 keypad driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-keypad");
OpenPOWER on IntegriCloud