[PATCH v6 6/8] input: stpmic1: add stpmic1 onkey driver

2018-11-27 Thread Pascal PAILLET-LME
The stpmic1 pmic is able to manage an onkey button. This driver exposes
the stpmic1 onkey as an input device. It can also be configured to
shut-down the power supplies on a long key-press with an adjustable
duration.

Signed-off-by: Pascal Paillet 
Acked-by: Dmitry Torokhov 
---
changes in v6: nothing

 drivers/input/misc/Kconfig |  11 +++
 drivers/input/misc/Makefile|   2 +
 drivers/input/misc/stpmic1_onkey.c | 198 +
 3 files changed, 211 insertions(+)
 create mode 100644 drivers/input/misc/stpmic1_onkey.c

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ca59a2b..279fb02 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA
  To compile this driver as a module, choose M here. The module will
  be called sc27xx_vibra.
 
+config INPUT_STPMIC1_ONKEY
+   tristate "STPMIC1 PMIC Onkey support"
+   depends on MFD_STPMIC1
+   help
+ Say Y to enable support of onkey embedded into STPMIC1 PMIC. onkey
+ can be used to wakeup from low power modes and force a shut-down on
+ long press.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stpmic1_onkey.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 9d0f9d1..1b44202 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS)  += sgi_btns.o
 obj-$(CONFIG_INPUT_SIRFSOC_ONKEY)  += sirfsoc-onkey.o
 obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY)   += soc_button_array.o
 obj-$(CONFIG_INPUT_SPARCSPKR)  += sparcspkr.o
+obj-$(CONFIG_INPUT_STPMIC1_ONKEY)  += stpmic1_onkey.o
 obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)  += twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)  += twl4030-vibra.o
@@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)+= yealink.o
 obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR)   += ideapad_slidebar.o
+
diff --git a/drivers/input/misc/stpmic1_onkey.c 
b/drivers/input/misc/stpmic1_onkey.c
new file mode 100644
index 000..7b49c99
--- /dev/null
+++ b/drivers/input/misc/stpmic1_onkey.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet  for STMicroelectronics.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * struct stpmic1_onkey - OnKey data
+ * @input_dev: pointer to input device
+ * @irq_falling:   irq that we are hooked on to
+ * @irq_rising:irq that we are hooked on to
+ */
+struct stpmic1_onkey {
+   struct input_dev *input_dev;
+   int irq_falling;
+   int irq_rising;
+};
+
+static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
+{
+   struct stpmic1_onkey *onkey = ponkey;
+   struct input_dev *input_dev = onkey->input_dev;
+
+   input_report_key(input_dev, KEY_POWER, 1);
+   pm_wakeup_event(input_dev->dev.parent, 0);
+   input_sync(input_dev);
+
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
+{
+   struct stpmic1_onkey *onkey = ponkey;
+   struct input_dev *input_dev = onkey->input_dev;
+
+   input_report_key(input_dev, KEY_POWER, 0);
+   pm_wakeup_event(input_dev->dev.parent, 0);
+   input_sync(input_dev);
+
+   return IRQ_HANDLED;
+}
+
+static int stpmic1_onkey_probe(struct platform_device *pdev)
+{
+   struct stpmic1 *pmic = dev_get_drvdata(pdev->dev.parent);
+   struct device *dev = >dev;
+   struct input_dev *input_dev;
+   struct stpmic1_onkey *onkey;
+   unsigned int val, reg = 0;
+   int error;
+
+   onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+   if (!onkey)
+   return -ENOMEM;
+
+   onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
+   if (onkey->irq_falling < 0) {
+   dev_err(dev, "failed: request IRQ onkey-falling %d\n",
+   onkey->irq_falling);
+   return onkey->irq_falling;
+   }
+
+   onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
+   if (onkey->irq_rising < 0) {
+   dev_err(dev, "failed: request IRQ onkey-rising %d\n",
+   onkey->irq_rising);
+   return onkey->irq_rising;
+   }
+
+   if (!device_property_read_u32(dev, "power-off-time-sec", )) {
+   if (val > 0 && val <= 16) {
+   dev_dbg(dev, "power-off-time=%d seconds\n", val);
+   reg |= PONKEY_PWR_OFF;
+   reg |= ((16 - val) & PONKEY_TURNOFF_TIMER_MASK);
+   } else {
+   dev_err(dev, 

[PATCH v6 6/8] input: stpmic1: add stpmic1 onkey driver

2018-11-27 Thread Pascal PAILLET-LME
The stpmic1 pmic is able to manage an onkey button. This driver exposes
the stpmic1 onkey as an input device. It can also be configured to
shut-down the power supplies on a long key-press with an adjustable
duration.

Signed-off-by: Pascal Paillet 
Acked-by: Dmitry Torokhov 
---
changes in v6: nothing

 drivers/input/misc/Kconfig |  11 +++
 drivers/input/misc/Makefile|   2 +
 drivers/input/misc/stpmic1_onkey.c | 198 +
 3 files changed, 211 insertions(+)
 create mode 100644 drivers/input/misc/stpmic1_onkey.c

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ca59a2b..279fb02 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA
  To compile this driver as a module, choose M here. The module will
  be called sc27xx_vibra.
 
+config INPUT_STPMIC1_ONKEY
+   tristate "STPMIC1 PMIC Onkey support"
+   depends on MFD_STPMIC1
+   help
+ Say Y to enable support of onkey embedded into STPMIC1 PMIC. onkey
+ can be used to wakeup from low power modes and force a shut-down on
+ long press.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stpmic1_onkey.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 9d0f9d1..1b44202 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS)  += sgi_btns.o
 obj-$(CONFIG_INPUT_SIRFSOC_ONKEY)  += sirfsoc-onkey.o
 obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY)   += soc_button_array.o
 obj-$(CONFIG_INPUT_SPARCSPKR)  += sparcspkr.o
+obj-$(CONFIG_INPUT_STPMIC1_ONKEY)  += stpmic1_onkey.o
 obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)  += twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)  += twl4030-vibra.o
@@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)+= yealink.o
 obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR)   += ideapad_slidebar.o
+
diff --git a/drivers/input/misc/stpmic1_onkey.c 
b/drivers/input/misc/stpmic1_onkey.c
new file mode 100644
index 000..7b49c99
--- /dev/null
+++ b/drivers/input/misc/stpmic1_onkey.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet  for STMicroelectronics.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * struct stpmic1_onkey - OnKey data
+ * @input_dev: pointer to input device
+ * @irq_falling:   irq that we are hooked on to
+ * @irq_rising:irq that we are hooked on to
+ */
+struct stpmic1_onkey {
+   struct input_dev *input_dev;
+   int irq_falling;
+   int irq_rising;
+};
+
+static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
+{
+   struct stpmic1_onkey *onkey = ponkey;
+   struct input_dev *input_dev = onkey->input_dev;
+
+   input_report_key(input_dev, KEY_POWER, 1);
+   pm_wakeup_event(input_dev->dev.parent, 0);
+   input_sync(input_dev);
+
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
+{
+   struct stpmic1_onkey *onkey = ponkey;
+   struct input_dev *input_dev = onkey->input_dev;
+
+   input_report_key(input_dev, KEY_POWER, 0);
+   pm_wakeup_event(input_dev->dev.parent, 0);
+   input_sync(input_dev);
+
+   return IRQ_HANDLED;
+}
+
+static int stpmic1_onkey_probe(struct platform_device *pdev)
+{
+   struct stpmic1 *pmic = dev_get_drvdata(pdev->dev.parent);
+   struct device *dev = >dev;
+   struct input_dev *input_dev;
+   struct stpmic1_onkey *onkey;
+   unsigned int val, reg = 0;
+   int error;
+
+   onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+   if (!onkey)
+   return -ENOMEM;
+
+   onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
+   if (onkey->irq_falling < 0) {
+   dev_err(dev, "failed: request IRQ onkey-falling %d\n",
+   onkey->irq_falling);
+   return onkey->irq_falling;
+   }
+
+   onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
+   if (onkey->irq_rising < 0) {
+   dev_err(dev, "failed: request IRQ onkey-rising %d\n",
+   onkey->irq_rising);
+   return onkey->irq_rising;
+   }
+
+   if (!device_property_read_u32(dev, "power-off-time-sec", )) {
+   if (val > 0 && val <= 16) {
+   dev_dbg(dev, "power-off-time=%d seconds\n", val);
+   reg |= PONKEY_PWR_OFF;
+   reg |= ((16 - val) & PONKEY_TURNOFF_TIMER_MASK);
+   } else {
+   dev_err(dev,