From d42c4f8231375dd8113691a81dd11aa7f010e2df Mon Sep 17 00:00:00 2001 From: Marc Paolo Sosa Date: Thu, 5 Dec 2024 10:28:15 +0800 Subject: [PATCH 1/3] dt-bindings: input: add adi,max16150.yaml Add documentation for device tree bindings for MAX16150/MAX16169 Signed-off-by: Marc Paolo Sosa --- .../bindings/input/adi,max16150.yaml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/adi,max16150.yaml diff --git a/Documentation/devicetree/bindings/input/adi,max16150.yaml b/Documentation/devicetree/bindings/input/adi,max16150.yaml new file mode 100644 index 00000000000000..c53e6738d87c1b --- /dev/null +++ b/Documentation/devicetree/bindings/input/adi,max16150.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/adi,max16150.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX16150/MAX16169 nanoPower Pushbutton On/Off Controller + +maintainers: + - Marc Paolo Sosa + +description: | + The MAX16150/MAX16169 is an extremely low-power, pushbutton, on/off controller + with a switch debouncer and built-in latch. This device accepts a noisy input + from a mechanical switch and produces a clean, latched output, as well as a + one-shot interrupt output, in response to a switch closure exceeding the + debounce period at PB_IN. A switch closure longer than the shutdown period at + PB_IN results in a longer one-shot interrupt output. The MAX16150 family has + two sets of devices, one in which a longer switch closure greater than the + shutdown period deasserts the latched output, and another in which the latched + output stays asserted. + + Specifications about the controller can be found at: + https://www.analog.com/en/products/max16150.html + https://www.analog.com/en/products/max16169.html + +properties: + compatible: + enum: + - adi,max16150 + - adi,max16169 + +required: + - compatible + - gpios + - interrupt-parent + - interrupts + +additionalProperties: false + +examples: + - | + gpio { + max16150_pins: max16150_pins { + pins = <17>; + function = <0>; + }; + }; + + power-button { + compatible = "adi,max16150"; + gpios = <&gpio 17 0>; + interrupt-parent = <&gpio>; + interrupts = <17 2>; + status = "okay"; + }; From 2c8717219402a61d7552ee74bf380444b56f115e Mon Sep 17 00:00:00 2001 From: Marc Paolo Sosa Date: Thu, 5 Dec 2024 10:38:31 +0800 Subject: [PATCH 2/3] input: misc: add driver for max16150 MAX16150/MAX16169 nanoPower Pushbutton On/Off Controller Signed-off-by: Marc Paolo Sosa --- drivers/input/misc/Kconfig | 9 +++ drivers/input/misc/Makefile | 1 + drivers/input/misc/max16150.c | 119 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/input/misc/max16150.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6ba984d7f0b186..e4c3dd4cd2275e 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -150,6 +150,15 @@ config INPUT_E3X0_BUTTON To compile this driver as a module, choose M here: the module will be called e3x0_button. +config INPUT_MAX16150_PWRBUTTON + bool "MAX16150/MAX16169 Pushbutton driver" + depends on OF_GPIO + help + This driver supports the MAX16150 and MAX16169 pushbutton + controllers, which are low-power devices with a switch + debouncer and built-in latch. Device bindings are specified + in the device tree. + config INPUT_PCSPKR tristate "PC Speaker support" depends on PCSPKR_PLATFORM diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 04296a4abe8e87..92b57e9522086d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_INPUT_IQS7222) += iqs7222.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o +obj-$(CONFIG_INPUT_MAX16150_PWRBUTTON) += max16150.o obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o diff --git a/drivers/input/misc/max16150.c b/drivers/input/misc/max16150.c new file mode 100644 index 00000000000000..1e2ae66bc27796 --- /dev/null +++ b/drivers/input/misc/max16150.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices MAX16150/MAX16169 Pushbutton Driver + * + * Copyright 2024 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +static int irq_number; +static ktime_t prev_time; +static const ktime_t short_pulse = 32 * NSEC_PER_MSEC; +static const ktime_t long_pulse = 128 * NSEC_PER_MSEC; + +static irqreturn_t max16150_isr(int irq, void *dev_id) +{ + ktime_t now = ktime_get(); + ktime_t duration; + struct input_dev *button = dev_id; + static bool falling_edge = false; + + if (gpio_get_value(irq) == 0) { + prev_time = now; + falling_edge = true; + } else if (falling_edge) { + duration = ktime_sub(now, prev_time); + if (duration >= long_pulse) + input_report_key(button, KEY_POWER, 1); + else + input_report_key(button, KEY_WAKEUP, 1); + + input_sync(button); + falling_edge = false; + } + + return IRQ_HANDLED; +} + +static int get_irq(struct platform_device *pdev) +{ + return platform_get_irq(pdev, 0); +} + +static int max16150_probe(struct platform_device *pdev) +{ + struct input_dev *button; + int ret; + + button = devm_input_allocate_device(&pdev->dev); + if (!button) { + dev_err(&pdev->dev, "Can't allocate input device\n"); + return -ENOMEM; + } + + button->name = "max16150"; + button->phys = "max16150/input0"; + button->id.bustype = BUS_HOST; + input_set_capability(button, EV_KEY, KEY_POWER); + input_set_capability(button, EV_KEY, KEY_WAKEUP); + + ret = input_register_device(button); + if (ret) { + dev_err(&pdev->dev, "Can't register input device: %d\n", ret); + return ret; + } + + irq_number = get_irq(pdev); + if (irq_number < 0) { + dev_err(&pdev->dev, "Can't get IRQ\n"); + return irq_number; + } + + ret = devm_request_irq(&pdev->dev, irq_number, max16150_isr, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "max16150_irq", button); + if (ret) + return ret; + + prev_time = ktime_get(); + platform_set_drvdata(pdev, button); + device_init_wakeup(&pdev->dev, true); + + return 0; +} + +static int max16150_remove(struct platform_device *pdev) +{ + struct input_dev *button = platform_get_drvdata(pdev); + + input_unregister_device(button); + return 0; +} + +static const struct of_device_id max16150_of_match[] = { + { .compatible = "adi,max16150" }, + { .compatible = "adi,max16169" }, + { } +}; +MODULE_DEVICE_TABLE(of, max16150_of_match); + +static struct platform_driver max16150_driver = { + .probe = max16150_probe, + .remove = max16150_remove, + .driver = { + .name = "max16150", + .of_match_table = max16150_of_match, + }, +}; + +module_platform_driver(max16150_driver); + +MODULE_AUTHOR("Marc Paolo Sosa "); +MODULE_DESCRIPTION("MAX16150/MAX16169 Pushbutton Driver"); +MODULE_LICENSE("GPL"); From 84e649dd295fb825ea00c4b821e18f4f56087e32 Mon Sep 17 00:00:00 2001 From: Marc Paolo Sosa Date: Thu, 5 Dec 2024 18:46:42 +0800 Subject: [PATCH 3/3] Kconfig.adi imply MAX16150 Add entry for the MAX16150/MAX16169 driver. Signed-off-by: Marc Paolo Sosa --- drivers/input/Kconfig.adi | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/Kconfig.adi b/drivers/input/Kconfig.adi index d4e324f733ed04..d39babcc866e78 100644 --- a/drivers/input/Kconfig.adi +++ b/drivers/input/Kconfig.adi @@ -15,3 +15,4 @@ config INPUT_ALL_ADI_DRIVERS imply INPUT_AD714X imply INPUT_AD714X_I2C imply INPUT_AD714X_SPI + imply INPUT_MAX16150_PWRBUTTON