diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-08 21:02:58 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-08 21:02:58 +0300 |
commit | cf2e8c544cd3b33e9e403b7b72404c221bf888d1 (patch) | |
tree | 21b46d362626562921df14d75ee106259b3fa936 /drivers/input/misc | |
parent | 04e0361848afbe86fbf8b80945568df4c5bf6f07 (diff) | |
parent | d2d833e0bf2bad221a955626b942b38312630894 (diff) | |
download | linux-cf2e8c544cd3b33e9e403b7b72404c221bf888d1.tar.xz |
Merge tag 'mfd-next-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"New Drivers:
- Add STMPE ADC Input driver
- Add STMicroelectronics STPMIC1 Parent driver
- Add STMicroelectronics STPMIC1 OnKey Misc driver
- Add STMicroelectronics STPMIC1 Watchdog driver
- Add Cirrus Logic Lochnagar Parent driver
- Add TQ-Systems TQMX86 Parent driver
New Device Support:
- Add support for ADC to STMPE
New (or moved) Functionality:
- Move Lightbar functionality to its own driver; cros_ec_lightbar
- Move VBC functionality to its own driver; cros_ec_vbc
- Move VBC functionality to its own driver; cros_ec_vbc
- Move DebugFS functionality to its own driver; cros_ec_debugfs
- Move SYSFS functionality to its own driver; cros_ec_sysfs
- Add support for input voltage options; tps65218
Fixes:
- Use devm_* managed resources; cros_ec
- Device Tree documentation; stmpe, aspeed-lpc, lochnagar
- Trivial Clean-ups; stmpe
- Rip out broken modular code; aat2870-core, adp5520, as3711,
db8500-prcmu, htc-i2cpld, max8925-core, rc5t583, sta2x11-mfd,
syscon, tps65090, tps65910, tps68470 tps80031, wm831x-spi,
wm831x-i2c, wm831x-core, wm8350-i2c, wm8350-core, wm8400-core
- Kconfig fixups; INTEL_SOC_PMIC
- Improve error path; sm501, sec-core
- Use struct_size() helper; sm501
- Constify; at91-usart
- Use pointers instead of copying data; at91-usart
- Deliver proper return value; cros_ec_dev
- Trivial formatting/whitespace; sec-core"
* tag 'mfd-next-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (53 commits)
mfd: mxs-lradc: Mark expected switch fall-through
mfd: sec-core: Cleanup formatting to a consistent style
mfd: tqmx86: IO controller with I2C, Wachdog and GPIO
mfd: intel-lpss: Move linux/pm.h to the local header
mfd: cros_ec_dev: Return number of bytes read with CROS_EC_DEV_IOCRDMEM
mfd: tps68470: Drop unused MODULE_DEVICE_TABLE
mfd: at91-usart: No need to copy mfd_cell in probe
mfd: at91-usart: Constify at91_usart_spi_subdev and at91_usart_serial_subdev
mfd: lochnagar: Add support for the Cirrus Logic Lochnagar
mfd: lochnagar: Add initial binding documentation
dt-bindings: mfd: aspeed-lpc: Make parameter optional
mfd: sec-core: Return gracefully instead of BUG() if device cannot match
mfd: sm501: Use struct_size() in devm_kzalloc()
mfd: sm501: Fix potential NULL pointer dereference
mfd: Kconfig: Fix I2C_DESIGNWARE_PLATFORM dependencies
mfd: tps65218.c: Add input voltage options
mfd: wm8400-core: Make it explicitly non-modular
mfd: wm8350-core: Drop unused module infrastructure from non-modular code
mfd: wm8350-i2c: Make it explicitly non-modular
mfd: wm831x-core: Drop unused module infrastructure from non-modular code
...
Diffstat (limited to 'drivers/input/misc')
-rw-r--r-- | drivers/input/misc/Kconfig | 11 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/misc/stpmic1_onkey.c | 198 |
3 files changed, 211 insertions, 0 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index ca59a2be9bc5..279fb02a0f14 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 9d0f9d1ff68f..1b44202ad8f7 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 000000000000..7b49c9997df7 --- /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 <p.paillet@st.com> for STMicroelectronics. + +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/mfd/stpmic1.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/property.h> +#include <linux/regmap.h> + +/** + * 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 = &pdev->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", &val)) { + 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, "power-off-time-sec out of range\n"); + return -EINVAL; + } + } + + if (device_property_present(dev, "st,onkey-clear-cc-flag")) + reg |= PONKEY_CC_FLAG_CLEAR; + + error = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR, + PONKEY_TURNOFF_MASK, reg); + if (error) { + dev_err(dev, "PKEY_TURNOFF_CR write failed: %d\n", error); + return error; + } + + if (device_property_present(dev, "st,onkey-pu-inactive")) { + error = regmap_update_bits(pmic->regmap, PADS_PULL_CR, + PONKEY_PU_INACTIVE, + PONKEY_PU_INACTIVE); + if (error) { + dev_err(dev, "ONKEY Pads configuration failed: %d\n", + error); + return error; + } + } + + input_dev = devm_input_allocate_device(dev); + if (!input_dev) { + dev_err(dev, "Can't allocate Pwr Onkey Input Device\n"); + return -ENOMEM; + } + + input_dev->name = "pmic_onkey"; + input_dev->phys = "pmic_onkey/input0"; + + input_set_capability(input_dev, EV_KEY, KEY_POWER); + + onkey->input_dev = input_dev; + + /* interrupt is nested in a thread */ + error = devm_request_threaded_irq(dev, onkey->irq_falling, NULL, + onkey_falling_irq, IRQF_ONESHOT, + dev_name(dev), onkey); + if (error) { + dev_err(dev, "Can't get IRQ Onkey Falling: %d\n", error); + return error; + } + + error = devm_request_threaded_irq(dev, onkey->irq_rising, NULL, + onkey_rising_irq, IRQF_ONESHOT, + dev_name(dev), onkey); + if (error) { + dev_err(dev, "Can't get IRQ Onkey Rising: %d\n", error); + return error; + } + + error = input_register_device(input_dev); + if (error) { + dev_err(dev, "Can't register power button: %d\n", error); + return error; + } + + platform_set_drvdata(pdev, onkey); + device_init_wakeup(dev, true); + + return 0; +} + +static int __maybe_unused stpmic1_onkey_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct stpmic1_onkey *onkey = platform_get_drvdata(pdev); + + if (device_may_wakeup(dev)) { + enable_irq_wake(onkey->irq_falling); + enable_irq_wake(onkey->irq_rising); + } + return 0; +} + +static int __maybe_unused stpmic1_onkey_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct stpmic1_onkey *onkey = platform_get_drvdata(pdev); + + if (device_may_wakeup(dev)) { + disable_irq_wake(onkey->irq_falling); + disable_irq_wake(onkey->irq_rising); + } + return 0; +} + +static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm, + stpmic1_onkey_suspend, + stpmic1_onkey_resume); + +static const struct of_device_id of_stpmic1_onkey_match[] = { + { .compatible = "st,stpmic1-onkey" }, + { }, +}; + +MODULE_DEVICE_TABLE(of, of_stpmic1_onkey_match); + +static struct platform_driver stpmic1_onkey_driver = { + .probe = stpmic1_onkey_probe, + .driver = { + .name = "stpmic1_onkey", + .of_match_table = of_match_ptr(of_stpmic1_onkey_match), + .pm = &stpmic1_onkey_pm, + }, +}; +module_platform_driver(stpmic1_onkey_driver); + +MODULE_DESCRIPTION("Onkey driver for STPMIC1"); +MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>"); +MODULE_LICENSE("GPL v2"); |