diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2024-09-20 01:24:24 -0700 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2024-09-20 01:24:24 -0700 |
| commit | 36ec807b627b4c0a0a382f0ae48eac7187d14b2b (patch) | |
| tree | df9d682d66492722dbd186bd01af2d7334ea408a /drivers/input/keyboard | |
| parent | eb017f4ea13b1a5ad7f4332279f2e4c67b44bdea (diff) | |
| parent | 55bef83509f0cbe4cc54a583ac0313389dabee66 (diff) | |
| download | linux-36ec807b627b4c0a0a382f0ae48eac7187d14b2b.tar.gz linux-36ec807b627b4c0a0a382f0ae48eac7187d14b2b.tar.bz2 linux-36ec807b627b4c0a0a382f0ae48eac7187d14b2b.zip | |
Merge branch 'next' into for-linus
Prepare input updates for 6.12 merge window.
Diffstat (limited to 'drivers/input/keyboard')
| -rw-r--r-- | drivers/input/keyboard/Kconfig | 23 | ||||
| -rw-r--r-- | drivers/input/keyboard/Makefile | 2 | ||||
| -rw-r--r-- | drivers/input/keyboard/adc-keys.c | 5 | ||||
| -rw-r--r-- | drivers/input/keyboard/adp5588-keys.c | 97 | ||||
| -rw-r--r-- | drivers/input/keyboard/atkbd.c | 37 | ||||
| -rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 48 | ||||
| -rw-r--r-- | drivers/input/keyboard/gpio_keys_polled.c | 4 | ||||
| -rw-r--r-- | drivers/input/keyboard/iqs62x-keys.c | 7 | ||||
| -rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 334 | ||||
| -rw-r--r-- | drivers/input/keyboard/mcs_touchkey.c | 268 | ||||
| -rw-r--r-- | drivers/input/keyboard/mt6779-keypad.c | 19 | ||||
| -rw-r--r-- | drivers/input/keyboard/nomadik-ske-keypad.c | 378 | ||||
| -rw-r--r-- | drivers/input/keyboard/qt1050.c | 15 | ||||
| -rw-r--r-- | drivers/input/keyboard/snvs_pwrkey.c | 24 | ||||
| -rw-r--r-- | drivers/input/keyboard/spear-keyboard.c | 16 | ||||
| -rw-r--r-- | drivers/input/keyboard/tc3589x-keypad.c | 3 | ||||
| -rw-r--r-- | drivers/input/keyboard/tegra-kbc.c | 117 |
17 files changed, 284 insertions, 1113 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1d0c5f4c0f99..a5015d6f8bed 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 @@ -485,17 +473,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..3631a9294c6f 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -41,12 +41,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 5acaffb7f6e1..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); @@ -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/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/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/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", |
