Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

input: cpcap-pwrbutton: New driver

Motorola CPCAP is a PMIC found in multiple smartphones.
This driver adds support for the power/on button and has
been tested in Droid 4.

Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Sebastian Reichel and committed by
Lee Jones
6d999718 ab781ec0

+148
+20
Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
··· 1 + Motorola CPCAP on key 2 + 3 + This module is part of the CPCAP. For more details about the whole 4 + chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt. 5 + 6 + This module provides a simple power button event via an Interrupt. 7 + 8 + Required properties: 9 + - compatible: should be one of the following 10 + - "motorola,cpcap-pwrbutton" 11 + - interrupts: irq specifier for CPCAP's ON IRQ 12 + 13 + Example: 14 + 15 + &cpcap { 16 + cpcap_pwrbutton: pwrbutton { 17 + compatible = "motorola,cpcap-pwrbutton"; 18 + interrupts = <23 IRQ_TYPE_NONE>; 19 + }; 20 + };
+10
drivers/input/misc/Kconfig
··· 316 316 To compile this driver as a module, choose M here: the 317 317 module will be called cobalt_btns. 318 318 319 + config INPUT_CPCAP_PWRBUTTON 320 + tristate "CPCAP OnKey" 321 + depends on MFD_CPCAP 322 + help 323 + Say Y here if you want to enable power key reporting via the 324 + Motorola CPCAP chip. 325 + 326 + To compile this driver as a module, choose M here. The module will 327 + be called cpcap-pwrbutton. 328 + 319 329 config INPUT_WISTRON_BTNS 320 330 tristate "x86 Wistron laptop button interface" 321 331 depends on X86_32
+1
drivers/input/misc/Makefile
··· 24 24 obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o 25 25 obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o 26 26 obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o 27 + obj-$(CONFIG_INPUT_CPCAP_PWRBUTTON) += cpcap-pwrbutton.o 27 28 obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o 28 29 obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o 29 30 obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o
+117
drivers/input/misc/cpcap-pwrbutton.c
··· 1 + /** 2 + * CPCAP Power Button Input Driver 3 + * 4 + * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org> 5 + * 6 + * This file is subject to the terms and conditions of the GNU General 7 + * Public License. See the file "COPYING" in the main directory of this 8 + * archive for more details. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + */ 15 + 16 + #include <linux/module.h> 17 + #include <linux/init.h> 18 + #include <linux/kernel.h> 19 + #include <linux/errno.h> 20 + #include <linux/input.h> 21 + #include <linux/interrupt.h> 22 + #include <linux/regmap.h> 23 + #include <linux/of.h> 24 + #include <linux/platform_device.h> 25 + #include <linux/mfd/motorola-cpcap.h> 26 + 27 + #define CPCAP_IRQ_ON 23 28 + #define CPCAP_IRQ_ON_BITMASK (1 << (CPCAP_IRQ_ON % 16)) 29 + 30 + struct cpcap_power_button { 31 + struct regmap *regmap; 32 + struct input_dev *idev; 33 + struct device *dev; 34 + }; 35 + 36 + static irqreturn_t powerbutton_irq(int irq, void *_button) 37 + { 38 + struct cpcap_power_button *button = _button; 39 + int val; 40 + 41 + val = cpcap_sense_virq(button->regmap, irq); 42 + if (val < 0) { 43 + dev_err(button->dev, "irq read failed: %d", val); 44 + return IRQ_HANDLED; 45 + } 46 + 47 + pm_wakeup_event(button->dev, 0); 48 + input_report_key(button->idev, KEY_POWER, val); 49 + input_sync(button->idev); 50 + 51 + return IRQ_HANDLED; 52 + } 53 + 54 + static int cpcap_power_button_probe(struct platform_device *pdev) 55 + { 56 + struct cpcap_power_button *button; 57 + int irq = platform_get_irq(pdev, 0); 58 + int err; 59 + 60 + button = devm_kmalloc(&pdev->dev, sizeof(*button), GFP_KERNEL); 61 + if (!button) 62 + return -ENOMEM; 63 + 64 + button->idev = devm_input_allocate_device(&pdev->dev); 65 + if (!button->idev) 66 + return -ENOMEM; 67 + 68 + button->regmap = dev_get_regmap(pdev->dev.parent, NULL); 69 + if (!button->regmap) 70 + return -ENODEV; 71 + 72 + button->dev = &pdev->dev; 73 + 74 + button->idev->name = "cpcap-pwrbutton"; 75 + button->idev->phys = "cpcap-pwrbutton/input0"; 76 + button->idev->dev.parent = button->dev; 77 + input_set_capability(button->idev, EV_KEY, KEY_POWER); 78 + 79 + err = devm_request_threaded_irq(&pdev->dev, irq, NULL, 80 + powerbutton_irq, IRQF_ONESHOT, "cpcap_pwrbutton", button); 81 + if (err < 0) { 82 + dev_err(&pdev->dev, "IRQ request failed: %d\n", err); 83 + return err; 84 + } 85 + 86 + err = input_register_device(button->idev); 87 + if (err) { 88 + dev_err(&pdev->dev, "Input register failed: %d\n", err); 89 + return err; 90 + } 91 + 92 + device_init_wakeup(&pdev->dev, true); 93 + 94 + return 0; 95 + } 96 + 97 + #ifdef CONFIG_OF 98 + static const struct of_device_id cpcap_pwrbutton_dt_match_table[] = { 99 + { .compatible = "motorola,cpcap-pwrbutton" }, 100 + {}, 101 + }; 102 + MODULE_DEVICE_TABLE(of, cpcap_pwrbutton_dt_match_table); 103 + #endif 104 + 105 + static struct platform_driver cpcap_power_button_driver = { 106 + .probe = cpcap_power_button_probe, 107 + .driver = { 108 + .name = "cpcap-pwrbutton", 109 + .of_match_table = of_match_ptr(cpcap_pwrbutton_dt_match_table), 110 + }, 111 + }; 112 + module_platform_driver(cpcap_power_button_driver); 113 + 114 + MODULE_ALIAS("platform:cpcap-pwrbutton"); 115 + MODULE_DESCRIPTION("CPCAP Power Button"); 116 + MODULE_LICENSE("GPL"); 117 + MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");