From: Marco Felsch <m.felsch@pengutronix.de>
To: dmitry.torokhov@gmail.com, broonie@kernel.org,
mark.rutland@arm.com, robh+dt@kernel.org
Cc: linux-spi@vger.kernel.org, devicetree@vger.kernel.org,
linux-input@vger.kernel.org, kernel@pengutronix.de
Subject: [PATCH 3/3] Input: add generic gpio brownout driver
Date: Tue, 25 Sep 2018 11:42:30 +0200 [thread overview]
Message-ID: <20180925094230.32679-4-m.felsch@pengutronix.de> (raw)
In-Reply-To: <20180925094230.32679-1-m.felsch@pengutronix.de>
A brownout can be detected in several ways e.g. a deticated pin on the
soc, a external pmic or by another external hardware which informs the
host via a gpio line.
This patch adds the support for a generic gpio-based brownout
detection. Upon a brownout the host system gets informed and the driver
sends a keycode signal to the userspace. Per default this signal is
mapped to KEY_POWER, so the system will shoutdown.
Additional the driver supports releasing registered devices from their
drivers, see Documentation/devicetree/bindings/input/gpio-brownout.txt
for more details.
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
.../bindings/input/gpio-brownout.txt | 36 ++++
drivers/input/misc/Kconfig | 12 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/gpio-brownout.c | 166 ++++++++++++++++++
4 files changed, 215 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/gpio-brownout.txt
create mode 100644 drivers/input/misc/gpio-brownout.c
diff --git a/Documentation/devicetree/bindings/input/gpio-brownout.txt b/Documentation/devicetree/bindings/input/gpio-brownout.txt
new file mode 100644
index 000000000000..55fbe2aa52a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gpio-brownout.txt
@@ -0,0 +1,36 @@
+Device-Tree bindings for input/gpio_brownout.c driver
+
+Required properties:
+- compatible: Must be "gpio-brownout"
+- interrupt-parent: The phandle to the interrupt controller. For more details
+ see ../interrupt-controller/interrupts.txt.
+- interrupts: The interrupt line for a brownout detection. For more details
+ see ../interrupt-controller/interrupts.txt.
+
+Optional properties:
+- linux,code: Keycode to emit upon a brownout detection, default: KEY_POWER.
+- release-devices: A list of i2c or spi device phandles. All listed devices
+ will be released from their drivers in the order they listed upon a brownout
+ detection. This can be helpful to avoid a interrupt flood, because some
+ system designs power off all external devices immediately and keep the host
+ on for a certain time.
+
+Example:
+
+i2c3 {
+ temp_core: lm75@48 { };
+ temp_chassis: lm75@49 { };
+};
+
+spi1 {
+ ts: ad7879@1 { };
+};
+
+/ {
+ gpio_brownout_det {
+ compatible = "gpio-brownout";
+ interrupts-parent = <&gpio3>;
+ interrupts = <3 IRQ_TYPE_EDGE_LOW>:
+ release-devices = <&temp_core &ts>;
+ };
+};
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ca59a2be9bc5..6b49e681cca7 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -268,6 +268,18 @@ config INPUT_GPIO_BEEPER
To compile this driver as a module, choose M here: the
module will be called gpio-beeper.
+config INPUT_GPIO_BROWNOUT
+ tristate "Generic GPIO Brownout detection support"
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ Say Y here if you have a brownout signal connected to a GPIO pin
+ and want to report a keycode signal on a brownout detection.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gpio-brownout.
+
config INPUT_GPIO_DECODER
tristate "Polled GPIO Decoder Input driver"
depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 9d0f9d1ff68f..8b872b5fc84a 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_DRV2665_HAPTICS) += drv2665.o
obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o
obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o
+obj-$(CONFIG_INPUT_GPIO_BROWNOUT) += gpio-brownout.o
obj-$(CONFIG_INPUT_GPIO_DECODER) += gpio_decoder.o
obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/gpio-brownout.c b/drivers/input/misc/gpio-brownout.c
new file mode 100644
index 000000000000..23992b9e2814
--- /dev/null
+++ b/drivers/input/misc/gpio-brownout.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * gpio-brownout.c - Generic power fail driver
+ *
+ * Copyright (C) 2018 Pengutronix, Marco Felsch <kernel@pengutronix.de>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#define GPIO_BROWNOUT_MOD_NAME "gpio-brownout"
+
+struct gpio_brownout_device {
+ struct list_head list;
+ struct device *dev;
+};
+
+struct gpio_brownout {
+ struct device *dev;
+ struct input_dev *idev;
+ unsigned short kcode;
+ struct list_head devices;
+};
+
+static irqreturn_t gpio_brownout_isr(int irq, void *dev_id)
+{
+ struct gpio_brownout *gb = dev_id;
+ struct input_dev *idev = gb->idev;
+ struct gpio_brownout_device *bout_dev, *tmp;
+
+ /* first inform userspace */
+ input_report_key(idev, gb->kcode, 1);
+ input_sync(idev);
+
+ /* now unregister registered drivers */
+ list_for_each_entry_safe(bout_dev, tmp, &gb->devices, list) {
+ device_release_driver(bout_dev->dev);
+ list_del(&bout_dev->list);
+ }
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_OF
+static int gpio_brownout_probe_dt(struct gpio_brownout *gb)
+{
+ struct device_node *np = gb->dev->of_node;
+ struct of_phandle_iterator it;
+ unsigned int kcode;
+ int ret;
+
+ /* all dt-properties are optional */
+ of_property_read_u32(np, "linux,code", &kcode);
+ gb->kcode = kcode;
+
+ /*
+ * Register all devices which should be unbinded upon a brownout
+ * detection. At the moment only i2c and spi devices are supported
+ */
+ of_for_each_phandle(&it, ret, np, "release-devices", NULL, 0) {
+ struct gpio_brownout_device *elem;
+ struct i2c_client *i2c_c;
+ struct spi_device *spi_c;
+
+ i2c_c = of_find_i2c_device_by_node(it.node);
+ spi_c = of_find_spi_device_by_node(it.node);
+
+ if (!i2c_c && !spi_c)
+ return -EPROBE_DEFER;
+ else if (i2c_c && spi_c)
+ return -EINVAL;
+
+ elem = devm_kzalloc(gb->dev, sizeof(*elem), GFP_KERNEL);
+ if (!elem)
+ return -ENOMEM;
+
+ elem->dev = i2c_c ? &i2c_c->dev : &spi_c->dev;
+
+ INIT_LIST_HEAD(&elem->list);
+ list_add_tail(&elem->list, &gb->devices);
+ }
+
+ return 0;
+}
+#endif
+
+static int gpio_brownout_probe(struct platform_device *pdev)
+{
+ struct gpio_brownout *gb;
+ struct input_dev *idev;
+ int ret, irq;
+
+ gb = devm_kzalloc(&pdev->dev, sizeof(*gb), GFP_KERNEL);
+ if (!gb)
+ return -ENOMEM;
+
+ idev = devm_input_allocate_device(&pdev->dev);
+ if (!idev)
+ return -ENOMEM;
+
+ gb->dev = &pdev->dev;
+ gb->idev = idev;
+ INIT_LIST_HEAD(&gb->devices);
+
+ if (IS_ENABLED(CONFIG_OF)) {
+ ret = gpio_brownout_probe_dt(gb);
+ if (ret) {
+ dev_err(&pdev->dev, "probe_dt failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ idev->name = pdev->name;
+ gb->kcode = gb->kcode == KEY_RESERVED ? KEY_POWER : gb->kcode;
+
+ input_set_capability(idev, EV_KEY, gb->kcode);
+
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ gpio_brownout_isr, IRQF_ONESHOT,
+ GPIO_BROWNOUT_MOD_NAME, gb);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "IRQ request failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Input register failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id gpio_brownout_of_match[] = {
+ { .compatible = GPIO_BROWNOUT_MOD_NAME, },
+ { },
+};
+MODULE_DEVICE_TABLE(of, arm_gpio_brownout_of_match);
+#endif
+
+static struct platform_driver gpio_brownout_driver = {
+ .driver = {
+ .name = GPIO_BROWNOUT_MOD_NAME,
+ .of_match_table = of_match_ptr(gpio_brownout_of_match)
+ },
+ .probe = gpio_brownout_probe,
+};
+
+module_platform_driver(gpio_brownout_driver);
+
+MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("GPIO Brownout Detection");
+MODULE_LICENSE("GPL v2");
--
2.19.0
next prev parent reply other threads:[~2018-09-25 9:42 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-25 9:42 [PATCH 0/3] Add GPIO brownout detection support Marco Felsch
2018-09-25 9:42 ` [PATCH 1/3] spi: switch to SPDX license identifier Marco Felsch
2018-09-27 22:40 ` Applied "spi: switch to SPDX license identifier" to the spi tree Mark Brown
2018-09-25 9:42 ` [PATCH 2/3] spi: make OF helper available for others Marco Felsch
2018-09-27 22:38 ` Mark Brown
2018-09-27 22:40 ` Applied "spi: make OF helper available for others" to the spi tree Mark Brown
2018-09-25 9:42 ` Marco Felsch [this message]
2018-09-29 0:19 ` [PATCH 3/3] Input: add generic gpio brownout driver Dmitry Torokhov
2018-10-01 7:19 ` Marco Felsch
2018-10-01 16:35 ` Trent Piepho
2018-10-09 22:43 ` Marco Felsch
2018-09-25 17:09 ` [PATCH 0/3] Add GPIO brownout detection support Mark Brown
2018-09-26 8:15 ` Marco Felsch
2018-09-26 12:19 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180925094230.32679-4-m.felsch@pengutronix.de \
--to=m.felsch@pengutronix.de \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=kernel@pengutronix.de \
--cc=linux-input@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).