summaryrefslogtreecommitdiff
path: root/drivers/input/keyboard
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r--drivers/input/keyboard/Kconfig34
-rw-r--r--drivers/input/keyboard/Makefile3
-rw-r--r--drivers/input/keyboard/adc-keys.c5
-rw-r--r--drivers/input/keyboard/adp5588-keys.c99
-rw-r--r--drivers/input/keyboard/applespi.c1
-rw-r--r--drivers/input/keyboard/atkbd.c37
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c74
-rw-r--r--drivers/input/keyboard/gpio_keys.c48
-rw-r--r--drivers/input/keyboard/gpio_keys_polled.c4
-rw-r--r--drivers/input/keyboard/imx-sm-bbm-key.c225
-rw-r--r--drivers/input/keyboard/iqs62x-keys.c7
-rw-r--r--drivers/input/keyboard/matrix_keypad.c334
-rw-r--r--drivers/input/keyboard/mcs_touchkey.c268
-rw-r--r--drivers/input/keyboard/mt6779-keypad.c19
-rw-r--r--drivers/input/keyboard/nomadik-ske-keypad.c378
-rw-r--r--drivers/input/keyboard/qt1050.c15
-rw-r--r--drivers/input/keyboard/snvs_pwrkey.c24
-rw-r--r--drivers/input/keyboard/spear-keyboard.c16
-rw-r--r--drivers/input/keyboard/tc3589x-keypad.c3
-rw-r--r--drivers/input/keyboard/tegra-kbc.c117
20 files changed, 544 insertions, 1167 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 1d0c5f4c0f99..721ab69e84ac 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -421,18 +421,6 @@ config KEYBOARD_MAX7359
To compile this driver as a module, choose M here: the
module will be called max7359_keypad.
-config KEYBOARD_MCS
- tristate "MELFAS MCS Touchkey"
- depends on I2C
- help
- Say Y here if you have the MELFAS MCS5000/5080 touchkey controller
- chip in your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mcs_touchkey.
-
config KEYBOARD_MPR121
tristate "Freescale MPR121 Touchkey"
depends on I2C
@@ -466,6 +454,17 @@ config KEYBOARD_IMX
To compile this driver as a module, choose M here: the
module will be called imx_keypad.
+config KEYBOARD_IMX_BBM_SCMI
+ tristate "IMX BBM SCMI Key Driver"
+ depends on IMX_SCMI_BBM_EXT || COMPILE_TEST
+ default y if ARCH_MXC
+ help
+ This is the BBM key driver for NXP i.MX SoCs managed through
+ SCMI protocol.
+
+ To compile this driver as a module, choose M here: the
+ module will be called scmi-imx-bbm-key.
+
config KEYBOARD_IMX_SC_KEY
tristate "IMX SCU Key Driver"
depends on IMX_SCU
@@ -485,17 +484,6 @@ config KEYBOARD_NEWTON
To compile this driver as a module, choose M here: the
module will be called newtonkbd.
-config KEYBOARD_NOMADIK
- tristate "ST-Ericsson Nomadik SKE keyboard"
- depends on (ARCH_NOMADIK || ARCH_U8500 || COMPILE_TEST)
- select INPUT_MATRIXKMAP
- help
- Say Y here if you want to use a keypad provided on the SKE controller
- used on the Ux500 and Nomadik platforms
-
- To compile this driver as a module, choose M here: the
- module will be called nmk-ske-keypad.
-
config KEYBOARD_NSPIRE
tristate "TI-NSPIRE built-in keyboard"
depends on ARCH_NSPIRE && OF
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index aecef00c5d09..1e0721c30709 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o
obj-$(CONFIG_KEYBOARD_IQS62X) += iqs62x-keys.o
obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o
obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o
+obj-$(CONFIG_KEYBOARD_IMX_BBM_SCMI) += imx-sm-bbm-key.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
@@ -41,12 +42,10 @@ obj-$(CONFIG_KEYBOARD_LPC32XX) += lpc32xx-keys.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
-obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o
obj-$(CONFIG_KEYBOARD_MT6779) += mt6779-keypad.o
obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
-obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o
diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c
index bf72ab8df817..f1753207429d 100644
--- a/drivers/input/keyboard/adc-keys.c
+++ b/drivers/input/keyboard/adc-keys.c
@@ -66,7 +66,6 @@ static void adc_keys_poll(struct input_dev *input)
static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st)
{
struct adc_keys_button *map;
- struct fwnode_handle *child;
int i;
st->num_keys = device_get_child_node_count(dev);
@@ -80,11 +79,10 @@ static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st)
return -ENOMEM;
i = 0;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
if (fwnode_property_read_u32(child, "press-threshold-microvolt",
&map[i].voltage)) {
dev_err(dev, "Key with invalid or missing voltage\n");
- fwnode_handle_put(child);
return -EINVAL;
}
map[i].voltage /= 1000;
@@ -92,7 +90,6 @@ static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st)
if (fwnode_property_read_u32(child, "linux,code",
&map[i].keycode)) {
dev_err(dev, "Key with invalid or missing linux,code\n");
- fwnode_handle_put(child);
return -EINVAL;
}
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 1b0279393df4..d25d63a807f2 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -188,6 +188,7 @@ struct adp5588_kpad {
u32 cols;
u32 unlock_keys[2];
int nkeys_unlock;
+ bool gpio_only;
unsigned short keycode[ADP5588_KEYMAPSIZE];
unsigned char gpiomap[ADP5588_MAXGPIO];
struct gpio_chip gc;
@@ -221,15 +222,13 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned int off)
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
int val;
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
if (kpad->dir[bank] & bit)
val = kpad->dat_out[bank];
else
val = adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank);
- mutex_unlock(&kpad->gpio_lock);
-
return !!(val & bit);
}
@@ -240,7 +239,7 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
if (val)
kpad->dat_out[bank] |= bit;
@@ -248,8 +247,6 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
kpad->dat_out[bank] &= ~bit;
adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, kpad->dat_out[bank]);
-
- mutex_unlock(&kpad->gpio_lock);
}
static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off,
@@ -259,7 +256,6 @@ static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off,
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
bool pull_disable;
- int ret;
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_BIAS_PULL_UP:
@@ -272,19 +268,15 @@ static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off,
return -ENOTSUPP;
}
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
if (pull_disable)
kpad->pull_dis[bank] |= bit;
else
kpad->pull_dis[bank] &= bit;
- ret = adp5588_write(kpad->client, GPIO_PULL1 + bank,
- kpad->pull_dis[bank]);
-
- mutex_unlock(&kpad->gpio_lock);
-
- return ret;
+ return adp5588_write(kpad->client, GPIO_PULL1 + bank,
+ kpad->pull_dis[bank]);
}
static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned int off)
@@ -292,16 +284,11 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned int off
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
- int ret;
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
kpad->dir[bank] &= ~bit;
- ret = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]);
-
- mutex_unlock(&kpad->gpio_lock);
-
- return ret;
+ return adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]);
}
static int adp5588_gpio_direction_output(struct gpio_chip *chip,
@@ -310,9 +297,9 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
- int ret;
+ int error;
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
kpad->dir[bank] |= bit;
@@ -321,17 +308,16 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
else
kpad->dat_out[bank] &= ~bit;
- ret = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,
- kpad->dat_out[bank]);
- if (ret)
- goto out_unlock;
-
- ret = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]);
+ error = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,
+ kpad->dat_out[bank]);
+ if (error)
+ return error;
-out_unlock:
- mutex_unlock(&kpad->gpio_lock);
+ error = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]);
+ if (error)
+ return error;
- return ret;
+ return 0;
}
static int adp5588_build_gpiomap(struct adp5588_kpad *kpad)
@@ -446,10 +432,17 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
kpad->gc.label = kpad->client->name;
kpad->gc.owner = THIS_MODULE;
- girq = &kpad->gc.irq;
- gpio_irq_chip_set_chip(girq, &adp5588_irq_chip);
- girq->handler = handle_bad_irq;
- girq->threaded = true;
+ if (device_property_present(dev, "interrupt-controller")) {
+ if (!kpad->client->irq) {
+ dev_err(dev, "Unable to serve as interrupt controller without interrupt");
+ return -EINVAL;
+ }
+
+ girq = &kpad->gc.irq;
+ gpio_irq_chip_set_chip(girq, &adp5588_irq_chip);
+ girq->handler = handle_bad_irq;
+ girq->threaded = true;
+ }
mutex_init(&kpad->gpio_lock);
@@ -627,7 +620,7 @@ static int adp5588_setup(struct adp5588_kpad *kpad)
for (i = 0; i < KEYP_MAX_EVENT; i++) {
ret = adp5588_read(client, KEY_EVENTA);
- if (ret)
+ if (ret < 0)
return ret;
}
@@ -647,6 +640,18 @@ static int adp5588_fw_parse(struct adp5588_kpad *kpad)
struct i2c_client *client = kpad->client;
int ret, i;
+ /*
+ * Check if the device is to be operated purely in GPIO mode. To do
+ * so, check that no keypad rows or columns have been specified,
+ * since all GPINS should be configured as GPIO.
+ */
+ if (!device_property_present(&client->dev, "keypad,num-rows") &&
+ !device_property_present(&client->dev, "keypad,num-columns")) {
+ /* If purely GPIO, skip keypad setup */
+ kpad->gpio_only = true;
+ return 0;
+ }
+
ret = matrix_keypad_parse_properties(&client->dev, &kpad->rows,
&kpad->cols);
if (ret)
@@ -790,17 +795,19 @@ static int adp5588_probe(struct i2c_client *client)
if (error)
return error;
- error = devm_request_threaded_irq(&client->dev, client->irq,
- adp5588_hard_irq, adp5588_thread_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- client->dev.driver->name, kpad);
- if (error) {
- dev_err(&client->dev, "failed to request irq %d: %d\n",
- client->irq, error);
- return error;
+ if (client->irq) {
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ adp5588_hard_irq, adp5588_thread_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->dev.driver->name, kpad);
+ if (error) {
+ dev_err(&client->dev, "failed to request irq %d: %d\n",
+ client->irq, error);
+ return error;
+ }
}
- dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
+ dev_info(&client->dev, "Rev.%d controller\n", revid);
return 0;
}
diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c
index cf25177b4830..707c5a8ae736 100644
--- a/drivers/input/keyboard/applespi.c
+++ b/drivers/input/keyboard/applespi.c
@@ -1007,7 +1007,6 @@ static const struct file_operations applespi_tp_dim_fops = {
.owner = THIS_MODULE,
.open = applespi_tp_dim_open,
.read = applespi_tp_dim_read,
- .llseek = no_llseek,
};
static void report_finger_data(struct input_dev *input, int slot,
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index f4f2078cf501..5855d4fc6e6a 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -639,7 +639,7 @@ static void atkbd_event_work(struct work_struct *work)
{
struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
- mutex_lock(&atkbd->mutex);
+ guard(mutex)(&atkbd->mutex);
if (!atkbd->enabled) {
/*
@@ -657,8 +657,6 @@ static void atkbd_event_work(struct work_struct *work)
if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
atkbd_set_repeat_rate(atkbd);
}
-
- mutex_unlock(&atkbd->mutex);
}
/*
@@ -1361,7 +1359,7 @@ static int atkbd_reconnect(struct serio *serio)
{
struct atkbd *atkbd = atkbd_from_serio(serio);
struct serio_driver *drv = serio->drv;
- int retval = -1;
+ int error;
if (!atkbd || !drv) {
dev_dbg(&serio->dev,
@@ -1369,16 +1367,17 @@ static int atkbd_reconnect(struct serio *serio)
return -1;
}
- mutex_lock(&atkbd->mutex);
+ guard(mutex)(&atkbd->mutex);
atkbd_disable(atkbd);
if (atkbd->write) {
- if (atkbd_probe(atkbd))
- goto out;
+ error = atkbd_probe(atkbd);
+ if (error)
+ return error;
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
- goto out;
+ return -EIO;
/*
* Restore LED state and repeat rate. While input core
@@ -1404,11 +1403,7 @@ static int atkbd_reconnect(struct serio *serio)
if (atkbd->write)
atkbd_activate(atkbd);
- retval = 0;
-
- out:
- mutex_unlock(&atkbd->mutex);
- return retval;
+ return 0;
}
static const struct serio_device_id atkbd_serio_ids[] = {
@@ -1465,17 +1460,15 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t
struct atkbd *atkbd = atkbd_from_serio(serio);
int retval;
- retval = mutex_lock_interruptible(&atkbd->mutex);
- if (retval)
- return retval;
+ scoped_guard(mutex_intr, &atkbd->mutex) {
+ atkbd_disable(atkbd);
+ retval = handler(atkbd, buf, count);
+ atkbd_enable(atkbd);
- atkbd_disable(atkbd);
- retval = handler(atkbd, buf, count);
- atkbd_enable(atkbd);
-
- mutex_unlock(&atkbd->mutex);
+ return retval;
+ }
- return retval;
+ return -EINTR;
}
static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 6b811d6bf625..dcbc50304a5a 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -6,20 +6,13 @@
*
* Based on the pxa27x matrix keypad controller by Rodolfo Giometti.
*
- * NOTE:
- *
- * The 3-key reset is triggered by pressing the 3 keys in
- * Row 0, Columns 2, 4, and 7 at the same time. This action can
- * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag.
- *
- * Normal operation for the matrix does not autorepeat the key press.
- * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT
- * flag.
*/
#include <linux/bits.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -27,7 +20,6 @@
#include <linux/input/matrix_keypad.h>
#include <linux/slab.h>
#include <linux/soc/cirrus/ep93xx.h>
-#include <linux/platform_data/keypad-ep93xx.h>
#include <linux/pm_wakeirq.h>
/*
@@ -61,12 +53,16 @@
#define KEY_REG_KEY1_MASK GENMASK(5, 0)
#define KEY_REG_KEY1_SHIFT 0
+#define EP93XX_MATRIX_ROWS (8)
+#define EP93XX_MATRIX_COLS (8)
+
#define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
struct ep93xx_keypad {
- struct ep93xx_keypad_platform_data *pdata;
struct input_dev *input_dev;
struct clk *clk;
+ unsigned int debounce;
+ u16 prescale;
void __iomem *mmio_base;
@@ -133,23 +129,11 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
{
- struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
unsigned int val = 0;
- clk_set_rate(keypad->clk, pdata->clk_rate);
-
- if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
- val |= KEY_INIT_DIS3KY;
- if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE)
- val |= KEY_INIT_DIAG;
- if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE)
- val |= KEY_INIT_BACK;
- if (pdata->flags & EP93XX_KEYPAD_TEST_MODE)
- val |= KEY_INIT_T2;
-
- val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK);
+ val |= (keypad->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK;
- val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
+ val |= (keypad->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK;
__raw_writel(val, keypad->mmio_base + KEY_INIT);
}
@@ -220,17 +204,10 @@ static int ep93xx_keypad_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
ep93xx_keypad_suspend, ep93xx_keypad_resume);
-static void ep93xx_keypad_release_gpio_action(void *_pdev)
-{
- struct platform_device *pdev = _pdev;
-
- ep93xx_keypad_release_gpio(pdev);
-}
-
static int ep93xx_keypad_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct ep93xx_keypad *keypad;
- const struct matrix_keymap_data *keymap_data;
struct input_dev *input_dev;
int err;
@@ -238,14 +215,6 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
if (!keypad)
return -ENOMEM;
- keypad->pdata = dev_get_platdata(&pdev->dev);
- if (!keypad->pdata)
- return -EINVAL;
-
- keymap_data = keypad->pdata->keymap_data;
- if (!keymap_data)
- return -EINVAL;
-
keypad->irq = platform_get_irq(pdev, 0);
if (keypad->irq < 0)
return keypad->irq;
@@ -254,19 +223,13 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
if (IS_ERR(keypad->mmio_base))
return PTR_ERR(keypad->mmio_base);
- err = ep93xx_keypad_acquire_gpio(pdev);
- if (err)
- return err;
-
- err = devm_add_action_or_reset(&pdev->dev,
- ep93xx_keypad_release_gpio_action, pdev);
- if (err)
- return err;
-
keypad->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(keypad->clk))
return PTR_ERR(keypad->clk);
+ device_property_read_u32(dev, "debounce-delay-ms", &keypad->debounce);
+ device_property_read_u16(dev, "cirrus,prescale", &keypad->prescale);
+
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev)
return -ENOMEM;
@@ -278,13 +241,13 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
input_dev->open = ep93xx_keypad_open;
input_dev->close = ep93xx_keypad_close;
- err = matrix_keypad_build_keymap(keymap_data, NULL,
+ err = matrix_keypad_build_keymap(NULL, NULL,
EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
keypad->keycodes, input_dev);
if (err)
return err;
- if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
+ if (device_property_read_bool(&pdev->dev, "autorepeat"))
__set_bit(EV_REP, input_dev->evbit);
input_set_drvdata(input_dev, keypad);
@@ -313,10 +276,17 @@ static void ep93xx_keypad_remove(struct platform_device *pdev)
dev_pm_clear_wake_irq(&pdev->dev);
}
+static const struct of_device_id ep93xx_keypad_of_ids[] = {
+ { .compatible = "cirrus,ep9307-keypad" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ep93xx_keypad_of_ids);
+
static struct platform_driver ep93xx_keypad_driver = {
.driver = {
.name = "ep93xx-keypad",
.pm = pm_sleep_ptr(&ep93xx_keypad_pm_ops),
+ .of_match_table = ep93xx_keypad_of_ids,
},
.probe = ep93xx_keypad_probe,
.remove_new = ep93xx_keypad_remove,
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 9f3bcd41cf67..380fe8dab3b0 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -245,23 +245,20 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
{
int n_events = get_n_events_by_type(type);
const unsigned long *bitmap = get_bm_events_by_type(ddata->input, type);
- unsigned long *bits;
ssize_t error;
int i;
- bits = bitmap_alloc(n_events, GFP_KERNEL);
+ unsigned long *bits __free(bitmap) = bitmap_alloc(n_events, GFP_KERNEL);
if (!bits)
return -ENOMEM;
error = bitmap_parselist(buf, bits, n_events);
if (error)
- goto out;
+ return error;
/* First validate */
- if (!bitmap_subset(bits, bitmap, n_events)) {
- error = -EINVAL;
- goto out;
- }
+ if (!bitmap_subset(bits, bitmap, n_events))
+ return -EINVAL;
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
@@ -271,12 +268,11 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
if (test_bit(*bdata->code, bits) &&
!bdata->button->can_disable) {
- error = -EINVAL;
- goto out;
+ return -EINVAL;
}
}
- mutex_lock(&ddata->disable_lock);
+ guard(mutex)(&ddata->disable_lock);
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
@@ -290,11 +286,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
gpio_keys_enable_button(bdata);
}
- mutex_unlock(&ddata->disable_lock);
-
-out:
- bitmap_free(bits);
- return error;
+ return 0;
}
#define ATTR_SHOW_FN(name, type, only_disabled) \
@@ -470,11 +462,10 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
{
struct gpio_button_data *bdata = dev_id;
struct input_dev *input = bdata->input;
- unsigned long flags;
BUG_ON(irq != bdata->irq);
- spin_lock_irqsave(&bdata->lock, flags);
+ guard(spinlock_irqsave)(&bdata->lock);
if (!bdata->key_pressed) {
if (bdata->button->wakeup)
@@ -497,7 +488,6 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
ms_to_ktime(bdata->release_delay),
HRTIMER_MODE_REL_HARD);
out:
- spin_unlock_irqrestore(&bdata->lock, flags);
return IRQ_HANDLED;
}
@@ -768,7 +758,6 @@ gpio_keys_get_devtree_pdata(struct device *dev)
{
struct gpio_keys_platform_data *pdata;
struct gpio_keys_button *button;
- struct fwnode_handle *child;
int nbuttons, irq;
nbuttons = device_get_child_node_count(dev);
@@ -790,7 +779,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
device_property_read_string(dev, "label", &pdata->name);
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
if (is_of_node(child)) {
irq = of_irq_get_byname(to_of_node(child), "irq");
if (irq > 0)
@@ -808,7 +797,6 @@ gpio_keys_get_devtree_pdata(struct device *dev)
if (fwnode_property_read_u32(child, "linux,code",
&button->code)) {
dev_err(dev, "Button without keycode\n");
- fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
@@ -1064,10 +1052,10 @@ static int gpio_keys_suspend(struct device *dev)
if (error)
return error;
} else {
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
+
if (input_device_enabled(input))
gpio_keys_close(input);
- mutex_unlock(&input->mutex);
}
return 0;
@@ -1077,20 +1065,20 @@ static int gpio_keys_resume(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
- int error = 0;
+ int error;
if (device_may_wakeup(dev)) {
gpio_keys_disable_wakeup(ddata);
} else {
- mutex_lock(&input->mutex);
- if (input_device_enabled(input))
+ guard(mutex)(&input->mutex);
+
+ if (input_device_enabled(input)) {
error = gpio_keys_open(input);
- mutex_unlock(&input->mutex);
+ if (error)
+ return error;
+ }
}
- if (error)
- return error;
-
gpio_keys_report_state(ddata);
return 0;
}
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index b41fd1240f43..41ca0d3c9098 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -144,7 +144,6 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev)
{
struct gpio_keys_platform_data *pdata;
struct gpio_keys_button *button;
- struct fwnode_handle *child;
int nbuttons;
nbuttons = device_get_child_node_count(dev);
@@ -166,11 +165,10 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev)
device_property_read_string(dev, "label", &pdata->name);
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
if (fwnode_property_read_u32(child, "linux,code",
&button->code)) {
dev_err(dev, "button without keycode\n");
- fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/input/keyboard/imx-sm-bbm-key.c b/drivers/input/keyboard/imx-sm-bbm-key.c
new file mode 100644
index 000000000000..96486bd23d60
--- /dev/null
+++ b/drivers/input/keyboard/imx-sm-bbm-key.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP.
+ */
+
+#include <linux/input.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/scmi_protocol.h>
+#include <linux/scmi_imx_protocol.h>
+#include <linux/suspend.h>
+
+#define DEBOUNCE_TIME 30
+#define REPEAT_INTERVAL 60
+
+struct scmi_imx_bbm {
+ struct scmi_protocol_handle *ph;
+ const struct scmi_imx_bbm_proto_ops *ops;
+ struct notifier_block nb;
+ int keycode;
+ int keystate; /* 1:pressed */
+ bool suspended;
+ struct delayed_work check_work;
+ struct input_dev *input;
+};
+
+static void scmi_imx_bbm_pwrkey_check_for_events(struct work_struct *work)
+{
+ struct scmi_imx_bbm *bbnsm = container_of(to_delayed_work(work),
+ struct scmi_imx_bbm, check_work);
+ struct scmi_protocol_handle *ph = bbnsm->ph;
+ struct input_dev *input = bbnsm->input;
+ u32 state = 0;
+ int ret;
+
+ ret = bbnsm->ops->button_get(ph, &state);
+ if (ret) {
+ pr_err("%s: %d\n", __func__, ret);
+ return;
+ }
+
+ pr_debug("%s: state: %d, keystate %d\n", __func__, state, bbnsm->keystate);
+
+ /* only report new event if status changed */
+ if (state ^ bbnsm->keystate) {
+ bbnsm->keystate = state;
+ input_event(input, EV_KEY, bbnsm->keycode, state);
+ input_sync(input);
+ pm_relax(bbnsm->input->dev.parent);
+ pr_debug("EV_KEY: %x\n", bbnsm->keycode);
+ }
+
+ /* repeat check if pressed long */
+ if (state)
+ schedule_delayed_work(&bbnsm->check_work, msecs_to_jiffies(REPEAT_INTERVAL));
+}
+
+static int scmi_imx_bbm_pwrkey_event(struct scmi_imx_bbm *bbnsm)
+{
+ struct input_dev *input = bbnsm->input;
+
+ pm_wakeup_event(input->dev.parent, 0);
+
+ /*
+ * Directly report key event after resume to make no key press
+ * event is missed.
+ */
+ if (READ_ONCE(bbnsm->suspended)) {
+ bbnsm->keystate = 1;
+ input_event(input, EV_KEY, bbnsm->keycode, 1);
+ input_sync(input);
+ WRITE_ONCE(bbnsm->suspended, false);
+ }
+
+ schedule_delayed_work(&bbnsm->check_work, msecs_to_jiffies(DEBOUNCE_TIME));
+
+ return 0;
+}
+
+static void scmi_imx_bbm_pwrkey_act(void *pdata)
+{
+ struct scmi_imx_bbm *bbnsm = pdata;
+
+ cancel_delayed_work_sync(&bbnsm->check_work);
+}
+
+static int scmi_imx_bbm_key_notifier(struct notifier_block *nb, unsigned long event, void *data)
+{
+ struct scmi_imx_bbm *bbnsm = container_of(nb, struct scmi_imx_bbm, nb);
+ struct scmi_imx_bbm_notif_report *r = data;
+
+ if (r->is_button) {
+ pr_debug("BBM Button Power key pressed\n");
+ scmi_imx_bbm_pwrkey_event(bbnsm);
+ } else {
+ /* Should never reach here */
+ pr_err("Unexpected BBM event: %s\n", __func__);
+ }
+
+ return 0;
+}
+
+static int scmi_imx_bbm_pwrkey_init(struct scmi_device *sdev)
+{
+ const struct scmi_handle *handle = sdev->handle;
+ struct device *dev = &sdev->dev;
+ struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);
+ struct input_dev *input;
+ int ret;
+
+ if (device_property_read_u32(dev, "linux,code", &bbnsm->keycode)) {
+ bbnsm->keycode = KEY_POWER;
+ dev_warn(dev, "key code is not specified, using default KEY_POWER\n");
+ }
+
+ INIT_DELAYED_WORK(&bbnsm->check_work, scmi_imx_bbm_pwrkey_check_for_events);
+
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(dev, "failed to allocate the input device for SCMI IMX BBM\n");
+ return -ENOMEM;
+ }
+
+ input->name = dev_name(dev);
+ input->phys = "bbnsm-pwrkey/input0";
+ input->id.bustype = BUS_HOST;
+
+ input_set_capability(input, EV_KEY, bbnsm->keycode);
+
+ ret = devm_add_action_or_reset(dev, scmi_imx_bbm_pwrkey_act, bbnsm);
+ if (ret) {
+ dev_err(dev, "failed to register remove action\n");
+ return ret;
+ }
+
+ bbnsm->input = input;
+
+ bbnsm->nb.notifier_call = &scmi_imx_bbm_key_notifier;
+ ret = handle->notify_ops->devm_event_notifier_register(sdev, SCMI_PROTOCOL_IMX_BBM,
+ SCMI_EVENT_IMX_BBM_BUTTON,
+ NULL, &bbnsm->nb);
+
+ if (ret)
+ dev_err(dev, "Failed to register BBM Button Events %d:", ret);
+
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(dev, "failed to register input device\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int scmi_imx_bbm_key_probe(struct scmi_device *sdev)
+{
+ const struct scmi_handle *handle = sdev->handle;
+ struct device *dev = &sdev->dev;
+ struct scmi_protocol_handle *ph;
+ struct scmi_imx_bbm *bbnsm;
+ int ret;
+
+ if (!handle)
+ return -ENODEV;
+
+ bbnsm = devm_kzalloc(dev, sizeof(*bbnsm), GFP_KERNEL);
+ if (!bbnsm)
+ return -ENOMEM;
+
+ bbnsm->ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_BBM, &ph);
+ if (IS_ERR(bbnsm->ops))
+ return PTR_ERR(bbnsm->ops);
+
+ bbnsm->ph = ph;
+
+ device_init_wakeup(dev, true);
+
+ dev_set_drvdata(dev, bbnsm);
+
+ ret = scmi_imx_bbm_pwrkey_init(sdev);
+ if (ret)
+ device_init_wakeup(dev, false);
+
+ return ret;
+}
+
+static int __maybe_unused scmi_imx_bbm_key_suspend(struct device *dev)
+{
+ struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);
+
+ WRITE_ONCE(bbnsm->suspended, true);
+
+ return 0;
+}
+
+static int __maybe_unused scmi_imx_bbm_key_resume(struct device *dev)
+{
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(scmi_imx_bbm_pm_key_ops, scmi_imx_bbm_key_suspend,
+ scmi_imx_bbm_key_resume);
+
+static const struct scmi_device_id scmi_id_table[] = {
+ { SCMI_PROTOCOL_IMX_BBM, "imx-bbm-key" },
+ { },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_imx_bbm_key_driver = {
+ .driver = {
+ .pm = &scmi_imx_bbm_pm_key_ops,
+ },
+ .name = "scmi-imx-bbm-key",
+ .probe = scmi_imx_bbm_key_probe,
+ .id_table = scmi_id_table,
+};
+module_scmi_driver(scmi_imx_bbm_key_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_DESCRIPTION("IMX SM BBM Key driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/iqs62x-keys.c b/drivers/input/keyboard/iqs62x-keys.c
index 688d61244b5f..1315b0f0862f 100644
--- a/drivers/input/keyboard/iqs62x-keys.c
+++ b/drivers/input/keyboard/iqs62x-keys.c
@@ -45,7 +45,6 @@ struct iqs62x_keys_private {
static int iqs62x_keys_parse_prop(struct platform_device *pdev,
struct iqs62x_keys_private *iqs62x_keys)
{
- struct fwnode_handle *child;
unsigned int val;
int ret, i;
@@ -68,7 +67,8 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev,
}
for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
- child = device_get_named_child_node(&pdev->dev,
+ struct fwnode_handle *child __free(fwnode_handle) =
+ device_get_named_child_node(&pdev->dev,
iqs62x_switch_names[i]);
if (!child)
continue;
@@ -77,7 +77,6 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev,
if (ret) {
dev_err(&pdev->dev, "Failed to read switch code: %d\n",
ret);
- fwnode_handle_put(child);
return ret;
}
iqs62x_keys->switches[i].code = val;
@@ -91,8 +90,6 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev,
iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
IQS62X_EVENT_HALL_N_T :
IQS62X_EVENT_HALL_S_T);
-
- fwnode_handle_put(child);
}
return 0;
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 7a56f3d3aacd..3c38bae576ed 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -17,19 +17,27 @@
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/input/matrix_keypad.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
struct matrix_keypad {
- const struct matrix_keypad_platform_data *pdata;
struct input_dev *input_dev;
unsigned int row_shift;
+ unsigned int col_scan_delay_us;
+ /* key debounce interval in milli-second */
+ unsigned int debounce_ms;
+ bool drive_inactive_cols;
+
+ struct gpio_desc *row_gpios[MATRIX_MAX_ROWS];
+ unsigned int num_row_gpios;
+
+ struct gpio_desc *col_gpios[MATRIX_MAX_ROWS];
+ unsigned int num_col_gpios;
+
unsigned int row_irqs[MATRIX_MAX_ROWS];
- unsigned int num_row_irqs;
DECLARE_BITMAP(wakeup_enabled_irqs, MATRIX_MAX_ROWS);
uint32_t last_key_state[MATRIX_MAX_COLS];
@@ -45,50 +53,43 @@ struct matrix_keypad {
* columns. In that case it is configured here to be input, otherwise it is
* driven with the inactive value.
*/
-static void __activate_col(const struct matrix_keypad_platform_data *pdata,
- int col, bool on)
+static void __activate_col(struct matrix_keypad *keypad, int col, bool on)
{
- bool level_on = !pdata->active_low;
-
if (on) {
- gpio_direction_output(pdata->col_gpios[col], level_on);
+ gpiod_direction_output(keypad->col_gpios[col], 1);
} else {
- gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
- if (!pdata->drive_inactive_cols)
- gpio_direction_input(pdata->col_gpios[col]);
+ gpiod_set_value_cansleep(keypad->col_gpios[col], 0);
+ if (!keypad->drive_inactive_cols)
+ gpiod_direction_input(keypad->col_gpios[col]);
}
}
-static void activate_col(const struct matrix_keypad_platform_data *pdata,
- int col, bool on)
+static void activate_col(struct matrix_keypad *keypad, int col, bool on)
{
- __activate_col(pdata, col, on);
+ __activate_col(keypad, col, on);
- if (on && pdata->col_scan_delay_us)
- udelay(pdata->col_scan_delay_us);
+ if (on && keypad->col_scan_delay_us)
+ udelay(keypad->col_scan_delay_us);
}
-static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
- bool on)
+static void activate_all_cols(struct matrix_keypad *keypad, bool on)
{
int col;
- for (col = 0; col < pdata->num_col_gpios; col++)
- __activate_col(pdata, col, on);
+ for (col = 0; col < keypad->num_col_gpios; col++)
+ __activate_col(keypad, col, on);
}
-static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
- int row)
+static bool row_asserted(struct matrix_keypad *keypad, int row)
{
- return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
- !pdata->active_low : pdata->active_low;
+ return gpiod_get_value_cansleep(keypad->row_gpios[row]);
}
static void enable_row_irqs(struct matrix_keypad *keypad)
{
int i;
- for (i = 0; i < keypad->num_row_irqs; i++)
+ for (i = 0; i < keypad->num_row_gpios; i++)
enable_irq(keypad->row_irqs[i]);
}
@@ -96,7 +97,7 @@ static void disable_row_irqs(struct matrix_keypad *keypad)
{
int i;
- for (i = 0; i < keypad->num_row_irqs; i++)
+ for (i = 0; i < keypad->num_row_gpios; i++)
disable_irq_nosync(keypad->row_irqs[i]);
}
@@ -109,39 +110,38 @@ static void matrix_keypad_scan(struct work_struct *work)
container_of(work, struct matrix_keypad, work.work);
struct input_dev *input_dev = keypad->input_dev;
const unsigned short *keycodes = input_dev->keycode;
- const struct matrix_keypad_platform_data *pdata = keypad->pdata;
uint32_t new_state[MATRIX_MAX_COLS];
int row, col, code;
/* de-activate all columns for scanning */
- activate_all_cols(pdata, false);
+ activate_all_cols(keypad, false);
memset(new_state, 0, sizeof(new_state));
- for (row = 0; row < pdata->num_row_gpios; row++)
- gpio_direction_input(pdata->row_gpios[row]);
+ for (row = 0; row < keypad->num_row_gpios; row++)
+ gpiod_direction_input(keypad->row_gpios[row]);
/* assert each column and read the row status out */
- for (col = 0; col < pdata->num_col_gpios; col++) {
+ for (col = 0; col < keypad->num_col_gpios; col++) {
- activate_col(pdata, col, true);
+ activate_col(keypad, col, true);
- for (row = 0; row < pdata->num_row_gpios; row++)
+ for (row = 0; row < keypad->num_row_gpios; row++)
new_state[col] |=
- row_asserted(pdata, row) ? (1 << row) : 0;
+ row_asserted(keypad, row) ? BIT(row) : 0;
- activate_col(pdata, col, false);
+ activate_col(keypad, col, false);
}
- for (col = 0; col < pdata->num_col_gpios; col++) {
+ for (col = 0; col < keypad->num_col_gpios; col++) {
uint32_t bits_changed;
bits_changed = keypad->last_key_state[col] ^ new_state[col];
if (bits_changed == 0)
continue;
- for (row = 0; row < pdata->num_row_gpios; row++) {
- if ((bits_changed & (1 << row)) == 0)
+ for (row = 0; row < keypad->num_row_gpios; row++) {
+ if (!(bits_changed & BIT(row)))
continue;
code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
@@ -155,7 +155,7 @@ static void matrix_keypad_scan(struct work_struct *work)
memcpy(keypad->last_key_state, new_state, sizeof(new_state));
- activate_all_cols(pdata, true);
+ activate_all_cols(keypad, true);
/* Enable IRQs again */
spin_lock_irq(&keypad->lock);
@@ -182,7 +182,7 @@ static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
disable_row_irqs(keypad);
keypad->scan_pending = true;
schedule_delayed_work(&keypad->work,
- msecs_to_jiffies(keypad->pdata->debounce_ms));
+ msecs_to_jiffies(keypad->debounce_ms));
out:
spin_unlock_irqrestore(&keypad->lock, flags);
@@ -225,7 +225,8 @@ static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
{
int i;
- for_each_clear_bit(i, keypad->wakeup_enabled_irqs, keypad->num_row_irqs)
+ for_each_clear_bit(i, keypad->wakeup_enabled_irqs,
+ keypad->num_row_gpios)
if (enable_irq_wake(keypad->row_irqs[i]) == 0)
__set_bit(i, keypad->wakeup_enabled_irqs);
}
@@ -234,7 +235,8 @@ static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
{
int i;
- for_each_set_bit(i, keypad->wakeup_enabled_irqs, keypad->num_row_irqs) {
+ for_each_set_bit(i, keypad->wakeup_enabled_irqs,
+ keypad->num_row_gpios) {
disable_irq_wake(keypad->row_irqs[i]);
__clear_bit(i, keypad->wakeup_enabled_irqs);
}
@@ -272,182 +274,108 @@ static DEFINE_SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
static int matrix_keypad_init_gpio(struct platform_device *pdev,
struct matrix_keypad *keypad)
{
- const struct matrix_keypad_platform_data *pdata = keypad->pdata;
- int i, irq, err;
-
- /* initialized strobe lines as outputs, activated */
- for (i = 0; i < pdata->num_col_gpios; i++) {
- err = devm_gpio_request(&pdev->dev,
- pdata->col_gpios[i], "matrix_kbd_col");
- if (err) {
- dev_err(&pdev->dev,
- "failed to request GPIO%d for COL%d\n",
- pdata->col_gpios[i], i);
- return err;
- }
+ bool active_low;
+ int nrow, ncol;
+ int err;
+ int i;
- gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
+ nrow = gpiod_count(&pdev->dev, "row");
+ ncol = gpiod_count(&pdev->dev, "col");
+ if (nrow < 0 || ncol < 0) {
+ dev_err(&pdev->dev, "missing row or column GPIOs\n");
+ return -EINVAL;
}
- for (i = 0; i < pdata->num_row_gpios; i++) {
- err = devm_gpio_request(&pdev->dev,
- pdata->row_gpios[i], "matrix_kbd_row");
+ keypad->num_row_gpios = nrow;
+ keypad->num_col_gpios = ncol;
+
+ active_low = device_property_read_bool(&pdev->dev, "gpio-activelow");
+
+ /* initialize strobe lines as outputs, activated */
+ for (i = 0; i < keypad->num_col_gpios; i++) {
+ keypad->col_gpios[i] = devm_gpiod_get_index(&pdev->dev, "col",
+ i, GPIOD_ASIS);
+ err = PTR_ERR_OR_ZERO(keypad->col_gpios[i]);
if (err) {
dev_err(&pdev->dev,
- "failed to request GPIO%d for ROW%d\n",
- pdata->row_gpios[i], i);
+ "failed to request GPIO for COL%d: %d\n",
+ i, err);
return err;
}
- gpio_direction_input(pdata->row_gpios[i]);
+ gpiod_set_consumer_name(keypad->col_gpios[i], "matrix_kbd_col");
+
+ if (active_low ^ gpiod_is_active_low(keypad->col_gpios[i]))
+ gpiod_toggle_active_low(keypad->col_gpios[i]);
+
+ gpiod_direction_output(keypad->col_gpios[i], 1);
}
- if (pdata->clustered_irq > 0) {
- err = devm_request_any_context_irq(&pdev->dev,
- pdata->clustered_irq,
- matrix_keypad_interrupt,
- pdata->clustered_irq_flags,
- "matrix-keypad", keypad);
- if (err < 0) {
+ for (i = 0; i < keypad->num_row_gpios; i++) {
+ keypad->row_gpios[i] = devm_gpiod_get_index(&pdev->dev, "row",
+ i, GPIOD_IN);
+ err = PTR_ERR_OR_ZERO(keypad->row_gpios[i]);
+ if (err) {
dev_err(&pdev->dev,
- "Unable to acquire clustered interrupt\n");
+ "failed to request GPIO for ROW%d: %d\n",
+ i, err);
return err;
}
- keypad->row_irqs[0] = pdata->clustered_irq;
- keypad->num_row_irqs = 1;
- } else {
- for (i = 0; i < pdata->num_row_gpios; i++) {
- irq = gpio_to_irq(pdata->row_gpios[i]);
- if (irq < 0) {
- err = irq;
- dev_err(&pdev->dev,
- "Unable to convert GPIO line %i to irq: %d\n",
- pdata->row_gpios[i], err);
- return err;
- }
-
- err = devm_request_any_context_irq(&pdev->dev,
- irq,
- matrix_keypad_interrupt,
- IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING,
- "matrix-keypad", keypad);
- if (err < 0) {
- dev_err(&pdev->dev,
- "Unable to acquire interrupt for GPIO line %i\n",
- pdata->row_gpios[i]);
- return err;
- }
-
- keypad->row_irqs[i] = irq;
- }
+ gpiod_set_consumer_name(keypad->row_gpios[i], "matrix_kbd_row");
- keypad->num_row_irqs = pdata->num_row_gpios;
+ if (active_low ^ gpiod_is_active_low(keypad->row_gpios[i]))
+ gpiod_toggle_active_low(keypad->row_gpios[i]);
}
- /* initialized as disabled - enabled by input->open */
- disable_row_irqs(keypad);
-
return 0;
}
-#ifdef CONFIG_OF
-static struct matrix_keypad_platform_data *
-matrix_keypad_parse_dt(struct device *dev)
+static int matrix_keypad_setup_interrupts(struct platform_device *pdev,
+ struct matrix_keypad *keypad)
{
- struct matrix_keypad_platform_data *pdata;
- struct device_node *np = dev->of_node;
- unsigned int *gpios;
- int ret, i, nrow, ncol;
-
- if (!np) {
- dev_err(dev, "device lacks DT data\n");
- return ERR_PTR(-ENODEV);
- }
-
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(dev, "could not allocate memory for platform data\n");
- return ERR_PTR(-ENOMEM);
- }
-
- pdata->num_row_gpios = nrow = gpiod_count(dev, "row");
- pdata->num_col_gpios = ncol = gpiod_count(dev, "col");
- if (nrow < 0 || ncol < 0) {
- dev_err(dev, "number of keypad rows/columns not specified\n");
- return ERR_PTR(-EINVAL);
- }
-
- pdata->no_autorepeat = of_property_read_bool(np, "linux,no-autorepeat");
-
- pdata->wakeup = of_property_read_bool(np, "wakeup-source") ||
- of_property_read_bool(np, "linux,wakeup"); /* legacy */
-
- pdata->active_low = of_property_read_bool(np, "gpio-activelow");
-
- pdata->drive_inactive_cols =
- of_property_read_bool(np, "drive-inactive-cols");
-
- of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms);
- of_property_read_u32(np, "col-scan-delay-us",
- &pdata->col_scan_delay_us);
+ int err;
+ int irq;
+ int i;
- gpios = devm_kcalloc(dev,
- pdata->num_row_gpios + pdata->num_col_gpios,
- sizeof(unsigned int),
- GFP_KERNEL);
- if (!gpios) {
- dev_err(dev, "could not allocate memory for gpios\n");
- return ERR_PTR(-ENOMEM);
- }
+ for (i = 0; i < keypad->num_row_gpios; i++) {
+ irq = gpiod_to_irq(keypad->row_gpios[i]);
+ if (irq < 0) {
+ err = irq;
+ dev_err(&pdev->dev,
+ "Unable to convert GPIO line %i to irq: %d\n",
+ i, err);
+ return err;
+ }
- for (i = 0; i < nrow; i++) {
- ret = of_get_named_gpio(np, "row-gpios", i);
- if (ret < 0)
- return ERR_PTR(ret);
- gpios[i] = ret;
- }
+ err = devm_request_any_context_irq(&pdev->dev, irq,
+ matrix_keypad_interrupt,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "matrix-keypad", keypad);
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Unable to acquire interrupt for row %i: %d\n",
+ i, err);
+ return err;
+ }
- for (i = 0; i < ncol; i++) {
- ret = of_get_named_gpio(np, "col-gpios", i);
- if (ret < 0)
- return ERR_PTR(ret);
- gpios[nrow + i] = ret;
+ keypad->row_irqs[i] = irq;
}
- pdata->row_gpios = gpios;
- pdata->col_gpios = &gpios[pdata->num_row_gpios];
-
- return pdata;
-}
-#else
-static inline struct matrix_keypad_platform_data *
-matrix_keypad_parse_dt(struct device *dev)
-{
- dev_err(dev, "no platform data defined\n");
+ /* initialized as disabled - enabled by input->open */
+ disable_row_irqs(keypad);
- return ERR_PTR(-EINVAL);
+ return 0;
}
-#endif
static int matrix_keypad_probe(struct platform_device *pdev)
{
- const struct matrix_keypad_platform_data *pdata;
struct matrix_keypad *keypad;
struct input_dev *input_dev;
+ bool wakeup;
int err;
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata) {
- pdata = matrix_keypad_parse_dt(&pdev->dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
- } else if (!pdata->keymap_data) {
- dev_err(&pdev->dev, "no keymap data defined\n");
- return -EINVAL;
- }
-
keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
if (!keypad)
return -ENOMEM;
@@ -457,40 +385,56 @@ static int matrix_keypad_probe(struct platform_device *pdev)
return -ENOMEM;
keypad->input_dev = input_dev;
- keypad->pdata = pdata;
- keypad->row_shift = get_count_order(pdata->num_col_gpios);
keypad->stopped = true;
INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
spin_lock_init(&keypad->lock);
+ keypad->drive_inactive_cols =
+ device_property_read_bool(&pdev->dev, "drive-inactive-cols");
+ device_property_read_u32(&pdev->dev, "debounce-delay-ms",
+ &keypad->debounce_ms);
+ device_property_read_u32(&pdev->dev, "col-scan-delay-us",
+ &keypad->col_scan_delay_us);
+
+ err = matrix_keypad_init_gpio(pdev, keypad);
+ if (err)
+ return err;
+
+ keypad->row_shift = get_count_order(keypad->num_col_gpios);
+
+ err = matrix_keypad_setup_interrupts(pdev, keypad);
+ if (err)
+ return err;
+
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->open = matrix_keypad_start;
input_dev->close = matrix_keypad_stop;
- err = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
- pdata->num_row_gpios,
- pdata->num_col_gpios,
+ err = matrix_keypad_build_keymap(NULL, NULL,
+ keypad->num_row_gpios,
+ keypad->num_col_gpios,
NULL, input_dev);
if (err) {
dev_err(&pdev->dev, "failed to build keymap\n");
return -ENOMEM;
}
- if (!pdata->no_autorepeat)
+ if (!device_property_read_bool(&pdev->dev, "linux,no-autorepeat"))
__set_bit(EV_REP, input_dev->evbit);
+
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad);
- err = matrix_keypad_init_gpio(pdev, keypad);
- if (err)
- return err;
-
err = input_register_device(keypad->input_dev);
if (err)
return err;
- device_init_wakeup(&pdev->dev, pdata->wakeup);
+ wakeup = device_property_read_bool(&pdev->dev, "wakeup-source") ||
+ /* legacy */
+ device_property_read_bool(&pdev->dev, "linux,wakeup");
+ device_init_wakeup(&pdev->dev, wakeup);
+
platform_set_drvdata(pdev, keypad);
return 0;
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
deleted file mode 100644
index 2410f676c7f9..000000000000
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ /dev/null
@@ -1,268 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Touchkey driver for MELFAS MCS5000/5080 controller
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- */
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/platform_data/mcs.h>
-#include <linux/pm.h>
-
-/* MCS5000 Touchkey */
-#define MCS5000_TOUCHKEY_STATUS 0x04
-#define MCS5000_TOUCHKEY_STATUS_PRESS 7
-#define MCS5000_TOUCHKEY_FW 0x0a
-#define MCS5000_TOUCHKEY_BASE_VAL 0x61
-
-/* MCS5080 Touchkey */
-#define MCS5080_TOUCHKEY_STATUS 0x00
-#define MCS5080_TOUCHKEY_STATUS_PRESS 3
-#define MCS5080_TOUCHKEY_FW 0x01
-#define MCS5080_TOUCHKEY_BASE_VAL 0x1
-
-enum mcs_touchkey_type {
- MCS5000_TOUCHKEY,
- MCS5080_TOUCHKEY,
-};
-
-struct mcs_touchkey_chip {
- unsigned int status_reg;
- unsigned int pressbit;
- unsigned int press_invert;
- unsigned int baseval;
-};
-
-struct mcs_touchkey_data {
- void (*poweron)(bool);
-
- struct i2c_client *client;
- struct input_dev *input_dev;
- struct mcs_touchkey_chip chip;
- unsigned int key_code;
- unsigned int key_val;
- unsigned short keycodes[];
-};
-
-static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
-{
- struct mcs_touchkey_data *data = dev_id;
- struct mcs_touchkey_chip *chip = &data->chip;
- struct i2c_client *client = data->client;
- struct input_dev *input = data->input_dev;
- unsigned int key_val;
- unsigned int pressed;
- int val;
-
- val = i2c_smbus_read_byte_data(client, chip->status_reg);
- if (val < 0) {
- dev_err(&client->dev, "i2c read error [%d]\n", val);
- goto out;
- }
-
- pressed = (val & (1 << chip->pressbit)) >> chip->pressbit;
- if (chip->press_invert)
- pressed ^= chip->press_invert;
-
- /* key_val is 0 when released, so we should use key_val of press. */
- if (pressed) {
- key_val = val & (0xff >> (8 - chip->pressbit));
- if (!key_val)
- goto out;
- key_val -= chip->baseval;
- data->key_code = data->keycodes[key_val];
- data->key_val = key_val;
- }
-
- input_event(input, EV_MSC, MSC_SCAN, data->key_val);
- input_report_key(input, data->key_code, pressed);
- input_sync(input);
-
- dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code,
- pressed ? "pressed" : "released");
-
- out:
- return IRQ_HANDLED;
-}
-
-static void mcs_touchkey_poweroff(void *data)
-{
- struct mcs_touchkey_data *touchkey = data;
-
- touchkey->poweron(false);
-}
-
-static int mcs_touchkey_probe(struct i2c_client *client)
-{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
- const struct mcs_platform_data *pdata;
- struct mcs_touchkey_data *data;
- struct input_dev *input_dev;
- unsigned int fw_reg;
- int fw_ver;
- int error;
- int i;
-
- pdata = dev_get_platdata(&client->dev);
- if (!pdata) {
- dev_err(&client->dev, "no platform data defined\n");
- return -EINVAL;
- }
-
- data = devm_kzalloc(&client->dev,
- struct_size(data, keycodes, pdata->key_maxval + 1),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- input_dev = devm_input_allocate_device(&client->dev);
- if (!input_dev) {
- dev_err(&client->dev, "Failed to allocate input device\n");
- return -ENOMEM;
- }
-
- data->client = client;
- data->input_dev = input_dev;
-
- if (id->driver_data == MCS5000_TOUCHKEY) {
- data->chip.status_reg = MCS5000_TOUCHKEY_STATUS;
- data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS;
- data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL;
- fw_reg = MCS5000_TOUCHKEY_FW;
- } else {
- data->chip.status_reg = MCS5080_TOUCHKEY_STATUS;
- data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS;
- data->chip.press_invert = 1;
- data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL;
- fw_reg = MCS5080_TOUCHKEY_FW;
- }
-
- fw_ver = i2c_smbus_read_byte_data(client, fw_reg);
- if (fw_ver < 0) {
- dev_err(&client->dev, "i2c read error[%d]\n", fw_ver);
- return fw_ver;
- }
- dev_info(&client->dev, "Firmware version: %d\n", fw_ver);
-
- input_dev->name = "MELFAS MCS Touchkey";
- input_dev->id.bustype = BUS_I2C;
- input_dev->evbit[0] = BIT_MASK(EV_KEY);
- if (!pdata->no_autorepeat)
- input_dev->evbit[0] |= BIT_MASK(EV_REP);
- input_dev->keycode = data->keycodes;
- input_dev->keycodesize = sizeof(data->keycodes[0]);
- input_dev->keycodemax = pdata->key_maxval + 1;
-
- for (i = 0; i < pdata->keymap_size; i++) {
- unsigned int val = MCS_KEY_VAL(pdata->keymap[i]);
- unsigned int code = MCS_KEY_CODE(pdata->keymap[i]);
-
- data->keycodes[val] = code;
- __set_bit(code, input_dev->keybit);
- }
-
- input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- input_set_drvdata(input_dev, data);
-
- if (pdata->cfg_pin)
- pdata->cfg_pin();
-
- if (pdata->poweron) {
- data->poweron = pdata->poweron;
- data->poweron(true);
-
- error = devm_add_action_or_reset(&client->dev,
- mcs_touchkey_poweroff, data);
- if (error)
- return error;
- }
-
- error = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, mcs_touchkey_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- client->dev.driver->name, data);
- if (error) {
- dev_err(&client->dev, "Failed to register interrupt\n");
- return error;
- }
-
- error = input_register_device(input_dev);
- if (error)
- return error;
-
- i2c_set_clientdata(client, data);
- return 0;
-}
-
-static void mcs_touchkey_shutdown(struct i2c_client *client)
-{
- struct mcs_touchkey_data *data = i2c_get_clientdata(client);
-
- if (data->poweron)
- data->poweron(false);
-}
-
-static int mcs_touchkey_suspend(struct device *dev)
-{
- struct mcs_touchkey_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
-
- /* Disable the work */
- disable_irq(client->irq);
-
- /* Finally turn off the power */
- if (data->poweron)
- data->poweron(false);
-
- return 0;
-}
-
-static int mcs_touchkey_resume(struct device *dev)
-{
- struct mcs_touchkey_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
-
- /* Enable the device first */
- if (data->poweron)
- data->poweron(true);
-
- /* Enable irq again */
- enable_irq(client->irq);
-
- return 0;
-}
-
-static DEFINE_SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
- mcs_touchkey_suspend, mcs_touchkey_resume);
-
-static const struct i2c_device_id mcs_touchkey_id[] = {
- { "mcs5000_touchkey", MCS5000_TOUCHKEY },
- { "mcs5080_touchkey", MCS5080_TOUCHKEY },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
-
-static struct i2c_driver mcs_touchkey_driver = {
- .driver = {
- .name = "mcs_touchkey",
- .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops),
- },
- .probe = mcs_touchkey_probe,
- .shutdown = mcs_touchkey_shutdown,
- .id_table = mcs_touchkey_id,
-};
-
-module_i2c_driver(mcs_touchkey_driver);
-
-/* Module information */
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
-MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/mt6779-keypad.c b/drivers/input/keyboard/mt6779-keypad.c
index 19f69d167fbd..e5eb025c5e99 100644
--- a/drivers/input/keyboard/mt6779-keypad.c
+++ b/drivers/input/keyboard/mt6779-keypad.c
@@ -92,11 +92,6 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void mt6779_keypad_clk_disable(void *data)
-{
- clk_disable_unprepare(data);
-}
-
static void mt6779_keypad_calc_row_col_single(unsigned int key,
unsigned int *row,
unsigned int *col)
@@ -213,21 +208,10 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev)
regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_COL,
MTK_KPD_SEL_COLMASK(keypad->n_cols));
- keypad->clk = devm_clk_get(&pdev->dev, "kpd");
+ keypad->clk = devm_clk_get_enabled(&pdev->dev, "kpd");
if (IS_ERR(keypad->clk))
return PTR_ERR(keypad->clk);
- error = clk_prepare_enable(keypad->clk);
- if (error) {
- dev_err(&pdev->dev, "cannot prepare/enable keypad clock\n");
- return error;
- }
-
- error = devm_add_action_or_reset(&pdev->dev, mt6779_keypad_clk_disable,
- keypad->clk);
- if (error)
- return error;
-
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -260,6 +244,7 @@ static const struct of_device_id mt6779_keypad_of_match[] = {
{ .compatible = "mediatek,mt6873-keypad" },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, mt6779_keypad_of_match);
static struct platform_driver mt6779_keypad_pdrv = {
.probe = mt6779_keypad_pdrv_probe,
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
deleted file mode 100644
index b3ccc97f61e1..000000000000
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ /dev/null
@@ -1,378 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
- * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
- *
- * Keypad controller driver for the SKE (Scroll Key Encoder) module used in
- * the Nomadik 8815 and Ux500 platforms.
- */
-
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-
-#include <linux/platform_data/keypad-nomadik-ske.h>
-
-/* SKE_CR bits */
-#define SKE_KPMLT (0x1 << 6)
-#define SKE_KPCN (0x7 << 3)
-#define SKE_KPASEN (0x1 << 2)
-#define SKE_KPASON (0x1 << 7)
-
-/* SKE_IMSC bits */
-#define SKE_KPIMA (0x1 << 2)
-
-/* SKE_ICR bits */
-#define SKE_KPICS (0x1 << 3)
-#define SKE_KPICA (0x1 << 2)
-
-/* SKE_RIS bits */
-#define SKE_KPRISA (0x1 << 2)
-
-#define SKE_KEYPAD_ROW_SHIFT 3
-#define SKE_KPD_NUM_ROWS 8
-#define SKE_KPD_NUM_COLS 8
-
-/* keypad auto scan registers */
-#define SKE_ASR0 0x20
-#define SKE_ASR1 0x24
-#define SKE_ASR2 0x28
-#define SKE_ASR3 0x2C
-
-#define SKE_NUM_ASRX_REGISTERS (4)
-#define KEY_PRESSED_DELAY 10
-
-/**
- * struct ske_keypad - data structure used by keypad driver
- * @irq: irq no
- * @reg_base: ske registers base address
- * @input: pointer to input device object
- * @board: keypad platform device
- * @keymap: matrix scan code table for keycodes
- * @clk: clock structure pointer
- * @pclk: clock structure pointer
- * @ske_keypad_lock: spinlock protecting the keypad read/writes
- */
-struct ske_keypad {
- int irq;
- void __iomem *reg_base;
- struct input_dev *input;
- const struct ske_keypad_platform_data *board;
- unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS];
- struct clk *clk;
- struct clk *pclk;
- spinlock_t ske_keypad_lock;
-};
-
-static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
- u8 mask, u8 data)
-{
- u32 ret;
-
- spin_lock(&keypad->ske_keypad_lock);
-
- ret = readl(keypad->reg_base + addr);
- ret &= ~mask;
- ret |= data;
- writel(ret, keypad->reg_base + addr);
-
- spin_unlock(&keypad->ske_keypad_lock);
-}
-
-/*
- * ske_keypad_chip_init: init keypad controller configuration
- *
- * Enable Multi key press detection, auto scan mode
- */
-static int __init ske_keypad_chip_init(struct ske_keypad *keypad)
-{
- u32 value;
- int timeout = keypad->board->debounce_ms;
-
- /* check SKE_RIS to be 0 */
- while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
- cpu_relax();
-
- if (timeout == -1)
- return -EINVAL;
-
- /*
- * set debounce value
- * keypad dbounce is configured in DBCR[15:8]
- * dbounce value in steps of 32/32.768 ms
- */
- spin_lock(&keypad->ske_keypad_lock);
- value = readl(keypad->reg_base + SKE_DBCR);
- value = value & 0xff;
- value |= ((keypad->board->debounce_ms * 32000)/32768) << 8;
- writel(value, keypad->reg_base + SKE_DBCR);
- spin_unlock(&keypad->ske_keypad_lock);
-
- /* enable multi key detection */
- ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT);
-
- /*
- * set up the number of columns
- * KPCN[5:3] defines no. of keypad columns to be auto scanned
- */
- value = (keypad->board->kcol - 1) << 3;
- ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value);
-
- /* clear keypad interrupt for auto(and pending SW) scans */
- ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS);
-
- /* un-mask keypad interrupts */
- ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
-
- /* enable automatic scan */
- ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN);
-
- return 0;
-}
-
-static void ske_keypad_report(struct ske_keypad *keypad, u8 status, int col)
-{
- int row = 0, code, pos;
- struct input_dev *input = keypad->input;
- u32 ske_ris;
- int key_pressed;
- int num_of_rows;
-
- /* find out the row */
- num_of_rows = hweight8(status);
- do {
- pos = __ffs(status);
- row = pos;
- status &= ~(1 << pos);
-
- code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT);
- ske_ris = readl(keypad->reg_base + SKE_RIS);
- key_pressed = ske_ris & SKE_KPRISA;
-
- input_event(input, EV_MSC, MSC_SCAN, code);
- input_report_key(input, keypad->keymap[code], key_pressed);
- input_sync(input);
- num_of_rows--;
- } while (num_of_rows);
-}
-
-static void ske_keypad_read_data(struct ske_keypad *keypad)
-{
- u8 status;
- int col = 0;
- int ske_asr, i;
-
- /*
- * Read the auto scan registers
- *
- * Each SKE_ASRx (x=0 to x=3) contains two row values.
- * lower byte contains row value for column 2*x,
- * upper byte contains row value for column 2*x + 1
- */
- for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) {
- ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i));
- if (!ske_asr)
- continue;
-
- /* now that ASRx is zero, find out the coloumn x and row y */
- status = ske_asr & 0xff;
- if (status) {
- col = i * 2;
- ske_keypad_report(keypad, status, col);
- }
- status = (ske_asr & 0xff00) >> 8;
- if (status) {
- col = (i * 2) + 1;
- ske_keypad_report(keypad, status, col);
- }
- }
-}
-
-static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
-{
- struct ske_keypad *keypad = dev_id;
- int timeout = keypad->board->debounce_ms;
-
- /* disable auto scan interrupt; mask the interrupt generated */
- ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
- ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA);
-
- while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --timeout)
- cpu_relax();
-
- /* SKEx registers are stable and can be read */
- ske_keypad_read_data(keypad);
-
- /* wait until raw interrupt is clear */
- while ((readl(keypad->reg_base + SKE_RIS)) && --timeout)
- msleep(KEY_PRESSED_DELAY);
-
- /* enable auto scan interrupts */
- ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
-
- return IRQ_HANDLED;
-}
-
-static void ske_keypad_board_exit(void *data)
-{
- struct ske_keypad *keypad = data;
-
- keypad->board->exit();
-}
-
-static int __init ske_keypad_probe(struct platform_device *pdev)
-{
- const struct ske_keypad_platform_data *plat =
- dev_get_platdata(&pdev->dev);
- struct device *dev = &pdev->dev;
- struct ske_keypad *keypad;
- struct input_dev *input;
- int irq;
- int error;
-
- if (!plat) {
- dev_err(&pdev->dev, "invalid keypad platform data\n");
- return -EINVAL;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-
- keypad = devm_kzalloc(dev, sizeof(struct ske_keypad),
- GFP_KERNEL);
- input = devm_input_allocate_device(dev);
- if (!keypad || !input) {
- dev_err(&pdev->dev, "failed to allocate keypad memory\n");
- return -ENOMEM;
- }
-
- keypad->irq = irq;
- keypad->board = plat;
- keypad->input = input;
- spin_lock_init(&keypad->ske_keypad_lock);
-
- keypad->reg_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(keypad->reg_base))
- return PTR_ERR(keypad->reg_base);
-
- keypad->pclk = devm_clk_get_enabled(dev, "apb_pclk");
- if (IS_ERR(keypad->pclk)) {
- dev_err(&pdev->dev, "failed to get pclk\n");
- return PTR_ERR(keypad->pclk);
- }
-
- keypad->clk = devm_clk_get_enabled(dev, NULL);
- if (IS_ERR(keypad->clk)) {
- dev_err(&pdev->dev, "failed to get clk\n");
- return PTR_ERR(keypad->clk);
- }
-
- input->id.bustype = BUS_HOST;
- input->name = "ux500-ske-keypad";
- input->dev.parent = &pdev->dev;
-
- error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
- SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS,
- keypad->keymap, input);
- if (error) {
- dev_err(&pdev->dev, "Failed to build keymap\n");
- return error;
- }
-
- input_set_capability(input, EV_MSC, MSC_SCAN);
- if (!plat->no_autorepeat)
- __set_bit(EV_REP, input->evbit);
-
- /* go through board initialization helpers */
- if (keypad->board->init)
- keypad->board->init();
-
- if (keypad->board->exit) {
- error = devm_add_action_or_reset(dev, ske_keypad_board_exit,
- keypad);
- if (error)
- return error;
- }
-
- error = ske_keypad_chip_init(keypad);
- if (error) {
- dev_err(&pdev->dev, "unable to init keypad hardware\n");
- return error;
- }
-
- error = devm_request_threaded_irq(dev, keypad->irq,
- NULL, ske_keypad_irq,
- IRQF_ONESHOT, "ske-keypad", keypad);
- if (error) {
- dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
- return error;
- }
-
- error = input_register_device(input);
- if (error) {
- dev_err(&pdev->dev,
- "unable to register input device: %d\n", error);
- return error;
- }
-
- if (plat->wakeup_enable)
- device_init_wakeup(&pdev->dev, true);
-
- platform_set_drvdata(pdev, keypad);
-
- return 0;
-}
-
-static int ske_keypad_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct ske_keypad *keypad = platform_get_drvdata(pdev);
- int irq = platform_get_irq(pdev, 0);
-
- if (device_may_wakeup(dev))
- enable_irq_wake(irq);
- else
- ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
-
- return 0;
-}
-
-static int ske_keypad_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct ske_keypad *keypad = platform_get_drvdata(pdev);
- int irq = platform_get_irq(pdev, 0);
-
- if (device_may_wakeup(dev))
- disable_irq_wake(irq);
- else
- ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
-
- return 0;
-}
-
-static DEFINE_SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops,
- ske_keypad_suspend, ske_keypad_resume);
-
-static struct platform_driver ske_keypad_driver = {
- .driver = {
- .name = "nmk-ske-keypad",
- .pm = pm_sleep_ptr(&ske_keypad_dev_pm_ops),
- },
-};
-
-module_platform_driver_probe(ske_keypad_driver, ske_keypad_probe);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
-MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver");
-MODULE_ALIAS("platform:nomadik-ske-keypad");
diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c
index 5a2592e6293d..bce8157d1871 100644
--- a/drivers/input/keyboard/qt1050.c
+++ b/drivers/input/keyboard/qt1050.c
@@ -346,35 +346,34 @@ static int qt1050_apply_fw_data(struct qt1050_priv *ts)
static int qt1050_parse_fw(struct qt1050_priv *ts)
{
struct device *dev = &ts->client->dev;
- struct fwnode_handle *child;
int nbuttons;
nbuttons = device_get_child_node_count(dev);
if (nbuttons == 0 || nbuttons > QT1050_MAX_KEYS)
return -ENODEV;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct qt1050_key button;
/* Required properties */
if (fwnode_property_read_u32(child, "linux,code",
&button.keycode)) {
dev_err(dev, "Button without keycode\n");
- goto err;
+ return -EINVAL;
}
if (button.keycode >= KEY_MAX) {
dev_err(dev, "Invalid keycode 0x%x\n",
button.keycode);
- goto err;
+ return -EINVAL;
}
if (fwnode_property_read_u32(child, "reg",
&button.num)) {
dev_err(dev, "Button without pad number\n");
- goto err;
+ return -EINVAL;
}
if (button.num < 0 || button.num > QT1050_MAX_KEYS - 1)
- goto err;
+ return -EINVAL;
ts->reg_keys |= BIT(button.num);
@@ -424,10 +423,6 @@ static int qt1050_parse_fw(struct qt1050_priv *ts)
}
return 0;
-
-err:
- fwnode_handle_put(child);
- return -EINVAL;
}
static int qt1050_probe(struct i2c_client *client)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index ad8660be0127..f7b5f1e25c80 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -100,11 +100,6 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void imx_snvs_pwrkey_disable_clk(void *data)
-{
- clk_disable_unprepare(data);
-}
-
static void imx_snvs_pwrkey_act(void *pdata)
{
struct pwrkey_drv_data *pd = pdata;
@@ -141,28 +136,12 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
}
- clk = devm_clk_get_optional(&pdev->dev, NULL);
+ clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Failed to get snvs clock (%pe)\n", clk);
return PTR_ERR(clk);
}
- error = clk_prepare_enable(clk);
- if (error) {
- dev_err(&pdev->dev, "Failed to enable snvs clock (%pe)\n",
- ERR_PTR(error));
- return error;
- }
-
- error = devm_add_action_or_reset(&pdev->dev,
- imx_snvs_pwrkey_disable_clk, clk);
- if (error) {
- dev_err(&pdev->dev,
- "Failed to register clock cleanup handler (%pe)\n",
- ERR_PTR(error));
- return error;
- }
-
pdata->wakeup = of_property_read_bool(np, "wakeup-source");
pdata->irq = platform_get_irq(pdev, 0);
@@ -204,7 +183,6 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
error = devm_request_irq(&pdev->dev, pdata->irq,
imx_snvs_pwrkey_interrupt,
0, pdev->name, pdev);
-
if (error) {
dev_err(&pdev->dev, "interrupt not available.\n");
return error;
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 557d00a667ce..1df4feb8ba01 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -222,7 +222,7 @@ static int spear_kbd_probe(struct platform_device *pdev)
if (IS_ERR(kbd->io_base))
return PTR_ERR(kbd->io_base);
- kbd->clk = devm_clk_get(&pdev->dev, NULL);
+ kbd->clk = devm_clk_get_prepared(&pdev->dev, NULL);
if (IS_ERR(kbd->clk))
return PTR_ERR(kbd->clk);
@@ -255,14 +255,9 @@ static int spear_kbd_probe(struct platform_device *pdev)
return error;
}
- error = clk_prepare(kbd->clk);
- if (error)
- return error;
-
error = input_register_device(input_dev);
if (error) {
dev_err(&pdev->dev, "Unable to register keyboard device\n");
- clk_unprepare(kbd->clk);
return error;
}
@@ -272,14 +267,6 @@ static int spear_kbd_probe(struct platform_device *pdev)
return 0;
}
-static void spear_kbd_remove(struct platform_device *pdev)
-{
- struct spear_kbd *kbd = platform_get_drvdata(pdev);
-
- input_unregister_device(kbd->input);
- clk_unprepare(kbd->clk);
-}
-
static int spear_kbd_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -373,7 +360,6 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
static struct platform_driver spear_kbd_driver = {
.probe = spear_kbd_probe,
- .remove_new = spear_kbd_remove,
.driver = {
.name = "keyboard",
.pm = pm_sleep_ptr(&spear_kbd_pm_ops),
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
index b0d86621c60a..11988cffdfae 100644
--- a/drivers/input/keyboard/tc3589x-keypad.c
+++ b/drivers/input/keyboard/tc3589x-keypad.c
@@ -325,7 +325,6 @@ tc3589x_keypad_of_probe(struct device *dev)
struct tc3589x_keypad_platform_data *plat;
u32 cols, rows;
u32 debounce_ms;
- int proplen;
if (!np)
return ERR_PTR(-ENODEV);
@@ -346,7 +345,7 @@ tc3589x_keypad_of_probe(struct device *dev)
return ERR_PTR(-EINVAL);
}
- if (!of_get_property(np, "linux,keymap", &proplen)) {
+ if (!of_property_present(np, "linux,keymap")) {
dev_err(dev, "property linux,keymap not found\n");
return ERR_PTR(-ENOENT);
}
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index a1765ed8c825..6776dd94ce76 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -241,11 +241,10 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
static void tegra_kbc_keypress_timer(struct timer_list *t)
{
struct tegra_kbc *kbc = from_timer(kbc, t, timer);
- unsigned long flags;
u32 val;
unsigned int i;
- spin_lock_irqsave(&kbc->lock, flags);
+ guard(spinlock_irqsave)(&kbc->lock);
val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf;
if (val) {
@@ -270,17 +269,14 @@ static void tegra_kbc_keypress_timer(struct timer_list *t)
/* All keys are released so enable the keypress interrupt */
tegra_kbc_set_fifo_interrupt(kbc, true);
}
-
- spin_unlock_irqrestore(&kbc->lock, flags);
}
static irqreturn_t tegra_kbc_isr(int irq, void *args)
{
struct tegra_kbc *kbc = args;
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&kbc->lock, flags);
+ guard(spinlock_irqsave)(&kbc->lock);
/*
* Quickly bail out & reenable interrupts if the fifo threshold
@@ -301,8 +297,6 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args)
kbc->keypress_caused_wake = true;
}
- spin_unlock_irqrestore(&kbc->lock, flags);
-
return IRQ_HANDLED;
}
@@ -413,14 +407,13 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
static void tegra_kbc_stop(struct tegra_kbc *kbc)
{
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&kbc->lock, flags);
- val = readl(kbc->mmio + KBC_CONTROL_0);
- val &= ~1;
- writel(val, kbc->mmio + KBC_CONTROL_0);
- spin_unlock_irqrestore(&kbc->lock, flags);
+ scoped_guard(spinlock_irqsave, &kbc->lock) {
+ val = readl(kbc->mmio + KBC_CONTROL_0);
+ val &= ~1;
+ writel(val, kbc->mmio + KBC_CONTROL_0);
+ }
disable_irq(kbc->irq);
del_timer_sync(&kbc->timer);
@@ -491,12 +484,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
struct device_node *np = kbc->dev->of_node;
u32 prop;
int i;
- u32 num_rows = 0;
- u32 num_cols = 0;
+ int num_rows;
+ int num_cols;
u32 cols_cfg[KBC_MAX_GPIO];
u32 rows_cfg[KBC_MAX_GPIO];
- int proplen;
- int ret;
if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop))
kbc->debounce_cnt = prop;
@@ -510,56 +501,23 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */
kbc->wakeup = true;
- if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) {
- dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n");
- return -ENOENT;
- }
- num_rows = proplen / sizeof(u32);
-
- if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) {
- dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n");
- return -ENOENT;
- }
- num_cols = proplen / sizeof(u32);
-
- if (num_rows > kbc->hw_support->max_rows) {
- dev_err(kbc->dev,
- "Number of rows is more than supported by hardware\n");
- return -EINVAL;
- }
-
- if (num_cols > kbc->hw_support->max_columns) {
- dev_err(kbc->dev,
- "Number of cols is more than supported by hardware\n");
- return -EINVAL;
- }
-
- if (!of_get_property(np, "linux,keymap", &proplen)) {
+ if (!of_property_present(np, "linux,keymap")) {
dev_err(kbc->dev, "property linux,keymap not found\n");
return -ENOENT;
}
- if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) {
- dev_err(kbc->dev,
- "keypad rows/columns not properly specified\n");
- return -EINVAL;
- }
-
/* Set all pins as non-configured */
for (i = 0; i < kbc->num_rows_and_columns; i++)
kbc->pin_cfg[i].type = PIN_CFG_IGNORE;
- ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins",
- rows_cfg, num_rows);
- if (ret < 0) {
+ num_rows = of_property_read_variable_u32_array(np, "nvidia,kbc-row-pins",
+ rows_cfg, 1, KBC_MAX_GPIO);
+ if (num_rows < 0) {
dev_err(kbc->dev, "Rows configurations are not proper\n");
- return -EINVAL;
- }
-
- ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins",
- cols_cfg, num_cols);
- if (ret < 0) {
- dev_err(kbc->dev, "Cols configurations are not proper\n");
+ return num_rows;
+ } else if (num_rows > kbc->hw_support->max_rows) {
+ dev_err(kbc->dev,
+ "Number of rows is more than supported by hardware\n");
return -EINVAL;
}
@@ -568,11 +526,28 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
kbc->pin_cfg[rows_cfg[i]].num = i;
}
+ num_cols = of_property_read_variable_u32_array(np, "nvidia,kbc-col-pins",
+ cols_cfg, 1, KBC_MAX_GPIO);
+ if (num_cols < 0) {
+ dev_err(kbc->dev, "Cols configurations are not proper\n");
+ return num_cols;
+ } else if (num_cols > kbc->hw_support->max_columns) {
+ dev_err(kbc->dev,
+ "Number of cols is more than supported by hardware\n");
+ return -EINVAL;
+ }
+
for (i = 0; i < num_cols; i++) {
kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL;
kbc->pin_cfg[cols_cfg[i]].num = i;
}
+ if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) {
+ dev_err(kbc->dev,
+ "keypad rows/columns not properly specified\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -724,7 +699,8 @@ static int tegra_kbc_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct tegra_kbc *kbc = platform_get_drvdata(pdev);
- mutex_lock(&kbc->idev->mutex);
+ guard(mutex)(&kbc->idev->mutex);
+
if (device_may_wakeup(&pdev->dev)) {
disable_irq(kbc->irq);
del_timer_sync(&kbc->timer);
@@ -747,11 +723,9 @@ static int tegra_kbc_suspend(struct device *dev)
tegra_kbc_set_keypress_interrupt(kbc, true);
enable_irq(kbc->irq);
enable_irq_wake(kbc->irq);
- } else {
- if (input_device_enabled(kbc->idev))
- tegra_kbc_stop(kbc);
+ } else if (input_device_enabled(kbc->idev)) {
+ tegra_kbc_stop(kbc);
}
- mutex_unlock(&kbc->idev->mutex);
return 0;
}
@@ -760,9 +734,10 @@ static int tegra_kbc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tegra_kbc *kbc = platform_get_drvdata(pdev);
- int err = 0;
+ int err;
+
+ guard(mutex)(&kbc->idev->mutex);
- mutex_lock(&kbc->idev->mutex);
if (device_may_wakeup(&pdev->dev)) {
disable_irq_wake(kbc->irq);
tegra_kbc_setup_wakekeys(kbc, false);
@@ -787,13 +762,13 @@ static int tegra_kbc_resume(struct device *dev)
input_report_key(kbc->idev, kbc->wakeup_key, 0);
input_sync(kbc->idev);
}
- } else {
- if (input_device_enabled(kbc->idev))
- err = tegra_kbc_start(kbc);
+ } else if (input_device_enabled(kbc->idev)) {
+ err = tegra_kbc_start(kbc);
+ if (err)
+ return err;
}
- mutex_unlock(&kbc->idev->mutex);
- return err;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops,