From 0287e344b79851c82390b4812d14e742dfc92688 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 | 57 +++++++++++++++++++ 1 file changed, 57 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..327811e1ebd4e7 --- /dev/null +++ b/Documentation/devicetree/bindings/input/adi,max16150.yaml @@ -0,0 +1,57 @@ +# 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 a low-power pushbutton on/off controller with a + switch debouncer and built-in latch. It accepts a noisy input from a + mechanical switch and produces a clean latched output, as well as a one-shot + interrupt output. + +properties: + compatible: + description: + Specifies the supported device variants. The MAX16150 and MAX16169 are supported. + enum: + - adi,max16150a + - adi,max16150b + - adi,max16169a + - adi,max16169b + + interrupt-gpio: + maxItems: 1 + + clr-gpios: + description: + Clear Input. Pulling CLR low deasserts the latched OUT signal. If OUT is + already deasserted when CLR is pulled low, the state of OUT is unchanged. + maxItems: 1 + + linux,code: + default: KEY_POWER + +required: + - compatible + - interrupt-gpios + - clr-gpios + +additionalProperties: false + +examples: + - | + #include + #include + + power-button { + compatible = "adi,max16150a"; + interrupt-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + clr-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + linux,code = ; + }; From af35d4aacfda777029cde8d77145aafee2d85ab2 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 | 161 ++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 drivers/input/misc/max16150.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6ba984d7f0b186..f87ad998981bf5 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 + tristate "MAX16150/MAX16169 Pushbutton driver" + help + Say Y here if you want to enable power key reporting via + MAX16150/MAX16169 nanoPower Pushbutton On/Off Controller. + + To compile this driver as a module, choose M here. The module will + be called max16150. + 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..ae353b926afc28 --- /dev/null +++ b/drivers/input/misc/max16150.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices MAX16150/MAX16169 Pushbutton Driver + * + * Copyright 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX16150_LONG_INTERRUPT 120000000 + +struct max16150_chip_info { + bool has_clr_gpio; +}; + +struct max16150_device { + struct input_dev *input; + struct gpio_desc *gpiod; + struct gpio_desc *clr_gpiod; + const struct max16150_chip_info *chip_info; + u64 low, high, duration; + unsigned int keycode; +}; + +static irqreturn_t max16150_irq_handler(int irq, void *_max16150) +{ + struct max16150_device *max16150 = _max16150; + int value; + + value = gpiod_get_value(max16150->gpiod); + + if (!value) { + max16150->low = ktime_get_ns(); + return IRQ_HANDLED; + } + + max16150->high = ktime_get_ns(); + if (max16150->low) { + max16150->duration = max16150->high - max16150->low; + + if (max16150->duration > MAX16150_LONG_INTERRUPT) { + gpiod_set_value(max16150->clr_gpiod, 1); + input_report_key(max16150->input, max16150->keycode, 1); + input_sync(max16150->input); + input_report_key(max16150->input, max16150->keycode, 0); + input_sync(max16150->input); + } + + max16150->low = 0; + } + + return IRQ_HANDLED; +} + +static const struct max16150_chip_info max16150_variant_a = { + .has_clr_gpio = true, +}; + +static const struct max16150_chip_info max16150_variant_b = { + .has_clr_gpio = false, +}; + +static int max16150_probe(struct platform_device *pdev) +{ + const struct max16150_chip_info *chip_info; + struct max16150_device *max16150; + struct device *dev = &pdev->dev; + int err, irq, ret; + u32 keycode; + + chip_info = device_get_match_data(dev); + if (!chip_info) + return -EINVAL; + + max16150 = devm_kzalloc(dev, sizeof(*max16150), GFP_KERNEL); + if (!max16150) + return -ENOMEM; + + max16150->chip_info = chip_info; + + max16150->input = devm_input_allocate_device(dev); + if (!max16150->input) + return -ENOMEM; + + max16150->input->name = "MAX16150 Pushbutton"; + max16150->input->phys = "max16150/input0"; + max16150->input->id.bustype = BUS_HOST; + + keycode = KEY_POWER; + ret = device_property_read_u32(dev, "linux,code", &keycode); + if (ret) + return dev_err_probe(dev, ret, "Failed to get keycode\n"); + + max16150->keycode = keycode; + + input_set_capability(max16150->input, EV_KEY, max16150->keycode); + + max16150->gpiod = devm_gpiod_get(dev, "interrupt", GPIOD_IN); + if (IS_ERR(max16150->gpiod)) + return dev_err_probe(dev, PTR_ERR(max16150->gpiod), + "Failed to get interrupt GPIO\n"); + + if (chip_info->has_clr_gpio) { + max16150->clr_gpiod = devm_gpiod_get(dev, "clr", GPIOD_OUT_HIGH); + if (IS_ERR(max16150->clr_gpiod)) + return dev_err_probe(dev, PTR_ERR(max16150->clr_gpiod), + "Failed to get clr GPIO\n"); + + if (!max16150->clr_gpiod) + return dev_err_probe(dev, -ENODEV, + "clr GPIO is mandatory\n"); + + if (max16150->clr_gpiod) { + fsleep(1000); + gpiod_set_value(max16150->clr_gpiod, 0); + } + } + + irq = gpiod_to_irq(max16150->gpiod); + if (irq < 0) + return dev_err_probe(dev, irq, + "MAX16150: Failed to map GPIO to IRQ"); + + err = devm_request_irq(dev, irq, max16150_irq_handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "max16150_irq", max16150); + if (err) + return err; + + return input_register_device(max16150->input); +} + +static const struct of_device_id max16150_of_match[] = { + { .compatible = "adi,max16150a", .data = &max16150_variant_a }, + { .compatible = "adi,max16150b", .data = &max16150_variant_b }, + { .compatible = "adi,max16169a", .data = &max16150_variant_a }, + { .compatible = "adi,max16169b", .data = &max16150_variant_b }, + { } +}; +MODULE_DEVICE_TABLE(of, max16150_of_match); + +static struct platform_driver max16150_driver = { + .probe = max16150_probe, + .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 b4531256b27c0cc2a89ecaee0f608aedf23e229c Mon Sep 17 00:00:00 2001 From: Marc Paolo Sosa Date: Wed, 19 Feb 2025 09:58:37 +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