From 9acb215cbebdce721af2219e2859ad17342c9084 Mon Sep 17 00:00:00 2001 From: Samuel Kayode Date: Wed, 1 Oct 2025 11:42:40 -0400 Subject: Input: pf1550 - add onkey support Add support for the onkey of the pf1550 PMIC. Signed-off-by: Samuel Kayode Acked-by: Dmitry Torokhov Reviewed-by: Frank Li Tested-by: Sean Nyekjaer Link: https://patch.msgid.link/20251001-pf1550-v12-4-a3302aa41687@savoirfairelinux.com Signed-off-by: Lee Jones --- drivers/input/misc/Kconfig | 11 +++ drivers/input/misc/Makefile | 1 + drivers/input/misc/pf1550-onkey.c | 197 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 drivers/input/misc/pf1550-onkey.c (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index cc2558630797..94a753fcb64f 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -190,6 +190,17 @@ config INPUT_PCSPKR To compile this driver as a module, choose M here: the module will be called pcspkr. +config INPUT_PF1550_ONKEY + tristate "NXP PF1550 Onkey support" + depends on MFD_PF1550 + help + Say Y here if you want support for PF1550 PMIC. Onkey can trigger + release and 1s(push hold), 2s, 3s, 4s, 8s interrupt for long press + detect. + + To compile this driver as a module, choose M here. The module will be + called pf1550-onkey. + config INPUT_PM8941_PWRKEY tristate "Qualcomm PM8941 power key support" depends on MFD_SPMI_PMIC diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f5ebfa9d9983..415fc4e2918b 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o +obj-$(CONFIG_INPUT_PF1550_ONKEY) += pf1550-onkey.o obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o diff --git a/drivers/input/misc/pf1550-onkey.c b/drivers/input/misc/pf1550-onkey.c new file mode 100644 index 000000000000..9be6377151cb --- /dev/null +++ b/drivers/input/misc/pf1550-onkey.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for the PF1550 ONKEY + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved. + * + * Portions Copyright (c) 2025 Savoir-faire Linux Inc. + * Samuel Kayode + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PF1550_ONKEY_IRQ_NR 6 + +struct onkey_drv_data { + struct device *dev; + const struct pf1550_ddata *pf1550; + bool wakeup; + struct input_dev *input; +}; + +static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data) +{ + struct onkey_drv_data *onkey = data; + struct platform_device *pdev = to_platform_device(onkey->dev); + int i, state, irq_type = -1; + + for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) + if (irq == platform_get_irq(pdev, i)) + irq_type = i; + + switch (irq_type) { + case PF1550_ONKEY_IRQ_PUSHI: + state = 0; + break; + case PF1550_ONKEY_IRQ_1SI: + case PF1550_ONKEY_IRQ_2SI: + case PF1550_ONKEY_IRQ_3SI: + case PF1550_ONKEY_IRQ_4SI: + case PF1550_ONKEY_IRQ_8SI: + state = 1; + break; + default: + dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n", + irq_type); + return IRQ_HANDLED; + } + + input_event(onkey->input, EV_KEY, KEY_POWER, state); + input_sync(onkey->input); + + return IRQ_HANDLED; +} + +static int pf1550_onkey_probe(struct platform_device *pdev) +{ + struct onkey_drv_data *onkey; + struct input_dev *input; + bool key_power = false; + int i, irq, error; + + onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL); + if (!onkey) + return -ENOMEM; + + onkey->dev = &pdev->dev; + + onkey->pf1550 = dev_get_drvdata(pdev->dev.parent); + if (!onkey->pf1550->regmap) + return dev_err_probe(&pdev->dev, -ENODEV, + "failed to get regmap\n"); + + onkey->wakeup = device_property_read_bool(pdev->dev.parent, + "wakeup-source"); + + if (device_property_read_bool(pdev->dev.parent, + "nxp,disable-key-power")) { + error = regmap_clear_bits(onkey->pf1550->regmap, + PF1550_PMIC_REG_PWRCTRL1, + PF1550_ONKEY_RST_EN); + if (error) + return dev_err_probe(&pdev->dev, error, + "failed: disable turn system off"); + } else { + key_power = true; + } + + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return dev_err_probe(&pdev->dev, -ENOMEM, + "failed to allocate the input device\n"); + + input->name = pdev->name; + input->phys = "pf1550-onkey/input0"; + input->id.bustype = BUS_HOST; + + if (key_power) + input_set_capability(input, EV_KEY, KEY_POWER); + + onkey->input = input; + platform_set_drvdata(pdev, onkey); + + for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) { + irq = platform_get_irq(pdev, i); + if (irq < 0) + return irq; + + error = devm_request_threaded_irq(&pdev->dev, irq, NULL, + pf1550_onkey_irq_handler, + IRQF_NO_SUSPEND, + "pf1550-onkey", onkey); + if (error) + return dev_err_probe(&pdev->dev, error, + "failed: irq request (IRQ: %d)\n", + i); + } + + error = input_register_device(input); + if (error) + return dev_err_probe(&pdev->dev, error, + "failed to register input device\n"); + + device_init_wakeup(&pdev->dev, onkey->wakeup); + + return 0; +} + +static int pf1550_onkey_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct onkey_drv_data *onkey = platform_get_drvdata(pdev); + int i, irq; + + if (!device_may_wakeup(&pdev->dev)) + regmap_write(onkey->pf1550->regmap, + PF1550_PMIC_REG_ONKEY_INT_MASK0, + ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI | + ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI); + else + for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) { + irq = platform_get_irq(pdev, i); + if (irq > 0) + enable_irq_wake(irq); + } + + return 0; +} + +static int pf1550_onkey_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct onkey_drv_data *onkey = platform_get_drvdata(pdev); + int i, irq; + + if (!device_may_wakeup(&pdev->dev)) + regmap_write(onkey->pf1550->regmap, + PF1550_PMIC_REG_ONKEY_INT_MASK0, + ~((u8)(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | + ONKEY_IRQ_2SI | ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | + ONKEY_IRQ_8SI))); + else + for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) { + irq = platform_get_irq(pdev, i); + if (irq > 0) + disable_irq_wake(irq); + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend, + pf1550_onkey_resume); + +static const struct platform_device_id pf1550_onkey_id[] = { + { "pf1550-onkey", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, pf1550_onkey_id); + +static struct platform_driver pf1550_onkey_driver = { + .driver = { + .name = "pf1550-onkey", + .pm = pm_sleep_ptr(&pf1550_onkey_pm_ops), + }, + .probe = pf1550_onkey_probe, + .id_table = pf1550_onkey_id, +}; +module_platform_driver(pf1550_onkey_driver); + +MODULE_AUTHOR("Freescale Semiconductor"); +MODULE_DESCRIPTION("PF1550 onkey Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 7f9d1e0c954c499fc1ecef646a89d6c6e14d162c Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 27 Oct 2025 13:58:22 +0200 Subject: Input: cs40l50 - remove redundant pm_runtime_mark_last_busy() calls pm_runtime_put_autosuspend(), pm_runtime_put_sync_autosuspend(), pm_runtime_autosuspend() and pm_request_autosuspend() now include a call to pm_runtime_mark_last_busy(). Remove the now-reduntant explicit call to pm_runtime_mark_last_busy(). Signed-off-by: Sakari Ailus Link: https://patch.msgid.link/20251027115823.391080-2-sakari.ailus@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cs40l50-vibra.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/cs40l50-vibra.c b/drivers/input/misc/cs40l50-vibra.c index 7aa7d577e01b..90410025bbae 100644 --- a/drivers/input/misc/cs40l50-vibra.c +++ b/drivers/input/misc/cs40l50-vibra.c @@ -308,7 +308,6 @@ err_free: list_add(&effect->list, &vib->effect_head); } err_pm: - pm_runtime_mark_last_busy(vib->dev); pm_runtime_put_autosuspend(vib->dev); err_exit: work_data->error = error; @@ -368,7 +367,6 @@ static void cs40l50_start_worker(struct work_struct *work) dev_err(vib->dev, "Effect to play not found\n"); } - pm_runtime_mark_last_busy(vib->dev); pm_runtime_put_autosuspend(vib->dev); err_free: kfree(work_data); @@ -384,7 +382,6 @@ static void cs40l50_stop_worker(struct work_struct *work) vib->dsp.write(vib->dev, vib->regmap, vib->dsp.stop_cmd); - pm_runtime_mark_last_busy(vib->dev); pm_runtime_put_autosuspend(vib->dev); kfree(work_data); @@ -456,7 +453,6 @@ static void cs40l50_erase_worker(struct work_struct *work) list_del(&erase_effect->list); kfree(erase_effect); err_pm: - pm_runtime_mark_last_busy(vib->dev); pm_runtime_put_autosuspend(vib->dev); err_exit: work_data->error = error; -- cgit v1.2.3 From 673b192dbe174b61bdf784d293b5a6e7f2fd20f6 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Wed, 10 Dec 2025 21:11:41 +0000 Subject: Input: pf1550 - remove "defined but unused" warning If 'CONFIG_PM_SLEEP' is not set, compiler throws warning for *suspend() and *resume() function for this driver. Using new 'DEFINE_SIMPLE_DEV_PM_OPS' fixes it. Signed-off-by: Vaibhav Gupta Link: https://patch.msgid.link/20251210211149.543928-1-vaibhavgupta40@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pf1550-onkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/pf1550-onkey.c b/drivers/input/misc/pf1550-onkey.c index 9be6377151cb..0d1b570bbe47 100644 --- a/drivers/input/misc/pf1550-onkey.c +++ b/drivers/input/misc/pf1550-onkey.c @@ -173,7 +173,7 @@ static int pf1550_onkey_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend, +static DEFINE_SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend, pf1550_onkey_resume); static const struct platform_device_id pf1550_onkey_id[] = { -- cgit v1.2.3 From a4fcf43b63b6c319f8b998f461d02a18f584a88b Mon Sep 17 00:00:00 2001 From: Marco Crivellari Date: Thu, 6 Nov 2025 15:19:53 +0100 Subject: Input: palmas-pwrbutton - replace use of system_wq with system_dfl_wq Currently if a user enqueues a work item using schedule_delayed_work() the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to schedule_work() that is using system_wq and queue_work(), that makes use again of WORK_CPU_UNBOUND. This lack of consistency cannot be addressed without refactoring the API. This patch continues the effort to refactor worqueue APIs, which has begun with the change introducing new workqueues and a new alloc_workqueue flag: commit 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq") commit 930c2ea566af ("workqueue: Add new WQ_PERCPU flag") This specific workload do not benefit from a per-cpu workqueue, so use the default unbound workqueue (system_dfl_wq) instead. Suggested-by: Tejun Heo Signed-off-by: Marco Crivellari Link: https://patch.msgid.link/20251106141955.218911-3-marco.crivellari@suse.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/palmas-pwrbutton.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/palmas-pwrbutton.c b/drivers/input/misc/palmas-pwrbutton.c index 39fc451c56e9..d9c5aae143dc 100644 --- a/drivers/input/misc/palmas-pwrbutton.c +++ b/drivers/input/misc/palmas-pwrbutton.c @@ -91,7 +91,7 @@ static irqreturn_t pwron_irq(int irq, void *palmas_pwron) pm_wakeup_event(input_dev->dev.parent, 0); input_sync(input_dev); - mod_delayed_work(system_wq, &pwron->input_work, + mod_delayed_work(system_dfl_wq, &pwron->input_work, msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS)); return IRQ_HANDLED; -- cgit v1.2.3 From ec8fce2a57e96e07d82d4e884430c2cb6c048998 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Thu, 18 Dec 2025 21:10:50 -0800 Subject: Input: twl4030 - add TWL603x power button Like the TWL4030, these PMICs also have a power button feature, so extend the TWL4030 power button driver. As the irqchip of the TWL6030 mfd driver does not provide mask, unmask finctions, do it manually. Signed-off-by: Andreas Kemnade Link: https://patch.msgid.link/20251106-twl6030-button-v4-2-fdf1aa6e1e9a@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl4030-pwrbutton.c | 60 +++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 5 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index f85cc289c053..d82a3fb28d95 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -20,6 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -30,17 +31,31 @@ #include #include -#define PWR_PWRON_IRQ (1 << 0) +#define PWR_PWRON_IRQ BIT(0) -#define STS_HW_CONDITIONS 0xf +struct twl_pwrbutton_chipdata { + u8 status_reg; + bool need_manual_irq; +}; + +static const struct twl_pwrbutton_chipdata twl4030_chipdata = { + .status_reg = 0xf, + .need_manual_irq = false, +}; + +static const struct twl_pwrbutton_chipdata twl6030_chipdata = { + .status_reg = 0x2, + .need_manual_irq = true, +}; static irqreturn_t powerbutton_irq(int irq, void *_pwr) { struct input_dev *pwr = _pwr; + const struct twl_pwrbutton_chipdata *pdata = dev_get_drvdata(pwr->dev.parent); int err; u8 value; - err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); + err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, pdata->status_reg); if (!err) { pm_wakeup_event(pwr->dev.parent, 0); input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); @@ -55,10 +70,17 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) static int twl4030_pwrbutton_probe(struct platform_device *pdev) { + const struct twl_pwrbutton_chipdata *pdata; struct input_dev *pwr; int irq = platform_get_irq(pdev, 0); int err; + pdata = device_get_match_data(&pdev->dev); + if (!pdata) + return -EINVAL; + + platform_set_drvdata(pdev, (void *)pdata); + pwr = devm_input_allocate_device(&pdev->dev); if (!pwr) { dev_err(&pdev->dev, "Can't allocate power button\n"); @@ -85,21 +107,49 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) return err; } + if (pdata->need_manual_irq) { + err = twl6030_interrupt_unmask(0x01, REG_INT_MSK_LINE_A); + if (err) + return err; + + err = twl6030_interrupt_unmask(0x01, REG_INT_MSK_STS_A); + if (err) + return err; + } + device_init_wakeup(&pdev->dev, true); return 0; } +static void twl4030_pwrbutton_remove(struct platform_device *pdev) +{ + const struct twl_pwrbutton_chipdata *pdata = platform_get_drvdata(pdev); + + if (pdata->need_manual_irq) { + twl6030_interrupt_mask(0x01, REG_INT_MSK_LINE_A); + twl6030_interrupt_mask(0x01, REG_INT_MSK_STS_A); + } +} + #ifdef CONFIG_OF static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { - { .compatible = "ti,twl4030-pwrbutton" }, - {}, + { + .compatible = "ti,twl4030-pwrbutton", + .data = &twl4030_chipdata, + }, + { + .compatible = "ti,twl6030-pwrbutton", + .data = &twl6030_chipdata, + }, + { } }; MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); #endif static struct platform_driver twl4030_pwrbutton_driver = { .probe = twl4030_pwrbutton_probe, + .remove = twl4030_pwrbutton_remove, .driver = { .name = "twl4030_pwrbutton", .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table), -- cgit v1.2.3 From 71ed55143d9dba39b564d63d89411b07ef294c58 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Wed, 7 Jan 2026 21:52:14 -0800 Subject: Input: twl4030 - fix warnings without CONFIG_OF There are unused variables without CONFIG_OF: drivers/input/misc/twl4030-pwrbutton.c:41:44: error: unused variable 'twl4030_chipdata' [-Werror,-Wunused-const-variable] 41 | static const struct twl_pwrbutton_chipdata twl4030_chipdata = { | ^~~~~~~~~~~~~~~~ drivers/input/misc/twl4030-pwrbutton.c:46:44: error: unused variable 'twl6030_chipdata' [-Werror,-Wunused-const-variable] 46 | static const struct twl_pwrbutton_chipdata twl6030_chipdata = { Fix that by avoiding some #ifdef CONFIG_OF Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202512220251.jDE8tKup-lkp@intel.com/ Fixes: ec8fce2a57e9 ("Input: twl4030 - add TWL603x power button") Signed-off-by: Andreas Kemnade Link: https://patch.msgid.link/20251227115918.76969-1-andreas@kemnade.info Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl4030-pwrbutton.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index d82a3fb28d95..b0feef19515d 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include #include @@ -132,7 +133,6 @@ static void twl4030_pwrbutton_remove(struct platform_device *pdev) } } -#ifdef CONFIG_OF static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { { .compatible = "ti,twl4030-pwrbutton", @@ -145,14 +145,13 @@ static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { { } }; MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); -#endif static struct platform_driver twl4030_pwrbutton_driver = { .probe = twl4030_pwrbutton_probe, .remove = twl4030_pwrbutton_remove, .driver = { .name = "twl4030_pwrbutton", - .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table), + .of_match_table = twl4030_pwrbutton_dt_match_table, }, }; module_platform_driver(twl4030_pwrbutton_driver); -- cgit v1.2.3 From c83504aac85a47e9f69cc78df396e1ab63343299 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Nov 2025 16:44:42 +0100 Subject: Input: gpio_decoder - make use of device properties Convert the module to be property provider agnostic and allow it to be used on non-OF platforms. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251113154616.3107676-2-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/gpio_decoder.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c index ee668eba302f..459abc749a49 100644 --- a/drivers/input/misc/gpio_decoder.c +++ b/drivers/input/misc/gpio_decoder.c @@ -10,9 +10,10 @@ #include #include #include +#include #include -#include #include +#include struct gpio_decoder { struct gpio_descs *input_gpios; @@ -110,19 +111,17 @@ static int gpio_decoder_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id gpio_decoder_of_match[] = { { .compatible = "gpio-decoder", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, gpio_decoder_of_match); -#endif static struct platform_driver gpio_decoder_driver = { .probe = gpio_decoder_probe, .driver = { .name = "gpio-decoder", - .of_match_table = of_match_ptr(gpio_decoder_of_match), + .of_match_table = gpio_decoder_of_match, } }; module_platform_driver(gpio_decoder_driver); -- cgit v1.2.3 From 7cda46c30d17e6c7011fd7067f7b7638fa45934d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Nov 2025 16:44:43 +0100 Subject: Input: gpio_decoder - unify messages with help of dev_err_probe() Unify error messages that might appear during probe phase by switching to use dev_err_probe(). Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251113154616.3107676-3-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/gpio_decoder.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c index 459abc749a49..a2ae400790f9 100644 --- a/drivers/input/misc/gpio_decoder.c +++ b/drivers/input/misc/gpio_decoder.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -73,15 +74,12 @@ static int gpio_decoder_probe(struct platform_device *pdev) device_property_read_u32(dev, "linux,axis", &decoder->axis); decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); - if (IS_ERR(decoder->input_gpios)) { - dev_err(dev, "unable to acquire input gpios\n"); - return PTR_ERR(decoder->input_gpios); - } + if (IS_ERR(decoder->input_gpios)) + return dev_err_probe(dev, PTR_ERR(decoder->input_gpios), + "unable to acquire input gpios\n"); - if (decoder->input_gpios->ndescs < 2) { - dev_err(dev, "not enough gpios found\n"); - return -EINVAL; - } + if (decoder->input_gpios->ndescs < 2) + return dev_err_probe(dev, -EINVAL, "not enough gpios found\n"); if (device_property_read_u32(dev, "decoder-max-value", &max)) max = (1U << decoder->input_gpios->ndescs) - 1; @@ -97,16 +95,12 @@ static int gpio_decoder_probe(struct platform_device *pdev) input_set_abs_params(input, decoder->axis, 0, max, 0, 0); err = input_setup_polling(input, gpio_decoder_poll_gpios); - if (err) { - dev_err(dev, "failed to set up polling\n"); - return err; - } + if (err) + return dev_err_probe(dev, err, "failed to set up polling\n"); err = input_register_device(input); - if (err) { - dev_err(dev, "failed to register input device\n"); - return err; - } + if (err) + return dev_err_probe(dev, err, "failed to register input device\n"); return 0; } -- cgit v1.2.3 From 4eec8772e4f501b719df5264fc345b37a9af3c68 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Nov 2025 16:44:44 +0100 Subject: Input: gpio_decoder - replace custom loop by gpiod_get_array_value_cansleep() There is a custom loop that repeats parts of gpiod_get_array_value_cansleep(). Use that in conjunction with bitmap API to make code shorter and easier to follow. With this done, add an upper check for amount of GPIOs given based on the driver's code. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251113154616.3107676-4-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/gpio_decoder.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c index a2ae400790f9..7f319b932550 100644 --- a/drivers/input/misc/gpio_decoder.c +++ b/drivers/input/misc/gpio_decoder.c @@ -6,11 +6,13 @@ * encoded numeric value into an input event. */ +#include #include #include #include #include #include +#include #include #include #include @@ -26,23 +28,18 @@ struct gpio_decoder { static int gpio_decoder_get_gpios_state(struct gpio_decoder *decoder) { struct gpio_descs *gpios = decoder->input_gpios; - unsigned int ret = 0; - int i, val; - - for (i = 0; i < gpios->ndescs; i++) { - val = gpiod_get_value_cansleep(gpios->desc[i]); - if (val < 0) { - dev_err(decoder->dev, - "Error reading gpio %d: %d\n", - desc_to_gpio(gpios->desc[i]), val); - return val; - } - - val = !!val; - ret = (ret << 1) | val; + DECLARE_BITMAP(values, 32); + unsigned int size; + int err; + + size = min(gpios->ndescs, 32U); + err = gpiod_get_array_value_cansleep(size, gpios->desc, gpios->info, values); + if (err) { + dev_err(decoder->dev, "Error reading GPIO: %d\n", err); + return err; } - return ret; + return bitmap_read(values, 0, size); } static void gpio_decoder_poll_gpios(struct input_dev *input) @@ -81,6 +78,9 @@ static int gpio_decoder_probe(struct platform_device *pdev) if (decoder->input_gpios->ndescs < 2) return dev_err_probe(dev, -EINVAL, "not enough gpios found\n"); + if (decoder->input_gpios->ndescs > 31) + return dev_err_probe(dev, -EINVAL, "too many gpios found\n"); + if (device_property_read_u32(dev, "decoder-max-value", &max)) max = (1U << decoder->input_gpios->ndescs) - 1; -- cgit v1.2.3 From 829400644b0afe02107e2e19a8b90dfdcd23aafe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Nov 2025 16:44:45 +0100 Subject: Input: gpio_decoder - make use of the macros from bits.h Make use of BIT() where it makes sense. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251113154616.3107676-5-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/gpio_decoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c index 7f319b932550..057717de9849 100644 --- a/drivers/input/misc/gpio_decoder.c +++ b/drivers/input/misc/gpio_decoder.c @@ -60,7 +60,7 @@ static int gpio_decoder_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct gpio_decoder *decoder; struct input_dev *input; - u32 max; + u32 max; int err; decoder = devm_kzalloc(dev, sizeof(*decoder), GFP_KERNEL); @@ -82,7 +82,7 @@ static int gpio_decoder_probe(struct platform_device *pdev) return dev_err_probe(dev, -EINVAL, "too many gpios found\n"); if (device_property_read_u32(dev, "decoder-max-value", &max)) - max = (1U << decoder->input_gpios->ndescs) - 1; + max = BIT(decoder->input_gpios->ndescs) - 1; input = devm_input_allocate_device(dev); if (!input) -- cgit v1.2.3 From 219be8d98bd758a4d06b2ac2b1fdbb6a8c76cebe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Nov 2025 16:44:46 +0100 Subject: Input: gpio_decoder - don't use "proxy" headers Update header inclusions to follow IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251113154616.3107676-6-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/gpio_decoder.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/input/misc') diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c index 057717de9849..f0759dd39b35 100644 --- a/drivers/input/misc/gpio_decoder.c +++ b/drivers/input/misc/gpio_decoder.c @@ -7,16 +7,17 @@ */ #include -#include +#include +#include #include #include #include -#include #include #include #include #include #include +#include struct gpio_decoder { struct gpio_descs *input_gpios; -- cgit v1.2.3