[PATCH RFC 3/4] Input: gpio-keys - add regulator to gpio_keys
From: Griffin Kroah-Hartman
Date: Fri May 08 2026 - 08:59:38 EST
Allow gpio-keys to have vdd power suppy through regulators.
Signed-off-by: Griffin Kroah-Hartman <griffin.kroah@xxxxxxxxxxxxx>
---
drivers/input/keyboard/gpio_keys.c | 41 ++++++++++++++++++++++++++++++++++++++
include/linux/gpio_keys.h | 2 ++
2 files changed, 43 insertions(+)
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index e196174856796b391f14c31da9b2fee5ff742172..2199ce7455cfc763569e173d4d18da92507f38d3 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -28,6 +28,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
+#include <linux/regulator/consumer.h>
#include <dt-bindings/input/gpio-keys.h>
struct gpio_button_data {
@@ -729,6 +730,7 @@ static int gpio_keys_open(struct input_dev *input)
struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
const struct gpio_keys_platform_data *pdata = ddata->pdata;
int error;
+ int i;
if (pdata->enable) {
error = pdata->enable(input->dev.parent);
@@ -736,19 +738,48 @@ static int gpio_keys_open(struct input_dev *input)
return error;
}
+ for (i = 0; i < pdata->nbuttons; i++) {
+ const struct gpio_keys_button *button = &pdata->buttons[i];
+
+ if (!button->regulator)
+ continue;
+ error = regulator_enable(button->regulator);
+ if (error)
+ goto reg_err;
+ }
+
/* Report current state of buttons that are connected to GPIOs */
gpio_keys_report_state(ddata);
return 0;
+
+reg_err:
+ for (--i; i >= 0; i--) {
+ const struct gpio_keys_button *button = &pdata->buttons[i];
+
+ if (!button->regulator)
+ continue;
+ regulator_disable(button->regulator);
+ }
+ return error;
}
static void gpio_keys_close(struct input_dev *input)
{
struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
const struct gpio_keys_platform_data *pdata = ddata->pdata;
+ int i;
if (pdata->disable)
pdata->disable(input->dev.parent);
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ const struct gpio_keys_button *button = &pdata->buttons[i];
+
+ if (!button->regulator)
+ continue;
+ regulator_disable(button->regulator);
+ }
}
/*
@@ -829,6 +860,16 @@ gpio_keys_get_devtree_pdata(struct device *dev)
&button->debounce_interval))
button->debounce_interval = 5;
+ if (fwnode_property_present(child, "vdd-supply")) {
+ button->regulator = devm_fwnode_regulator_get_optional(dev, child, "vdd");
+ if (IS_ERR(button->regulator)) {
+ if (PTR_ERR(button->regulator) != -ENODEV)
+ return dev_err_ptr_probe(dev, PTR_ERR(button->regulator),
+ "Failed to get regulator\n");
+ button->regulator = NULL;
+ }
+ }
+
button++;
}
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 80fa930b04c6795eb7c6143a79655a6f918446eb..66e786ad7eba407dbea2545941f5b6e464a4f61c 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -3,6 +3,7 @@
#define _GPIO_KEYS_H
#include <linux/types.h>
+#include <linux/regulator/consumer.h>
struct device;
@@ -36,6 +37,7 @@ struct gpio_keys_button {
int value;
unsigned int irq;
unsigned int wakeirq;
+ struct regulator *regulator;
};
/**
--
2.43.0