2 * CPCAP Power Button Input Driver
4 * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
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.
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.
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>
24 #include <linux/platform_device.h>
25 #include <linux/mfd/motorola-cpcap.h>
27 #define CPCAP_IRQ_ON 23
28 #define CPCAP_IRQ_ON_BITMASK (1 << (CPCAP_IRQ_ON % 16))
30 struct cpcap_power_button
{
31 struct regmap
*regmap
;
32 struct input_dev
*idev
;
36 static irqreturn_t
powerbutton_irq(int irq
, void *_button
)
38 struct cpcap_power_button
*button
= _button
;
41 val
= cpcap_sense_virq(button
->regmap
, irq
);
43 dev_err(button
->dev
, "irq read failed: %d", val
);
47 pm_wakeup_event(button
->dev
, 0);
48 input_report_key(button
->idev
, KEY_POWER
, val
);
49 input_sync(button
->idev
);
54 static int cpcap_power_button_probe(struct platform_device
*pdev
)
56 struct cpcap_power_button
*button
;
57 int irq
= platform_get_irq(pdev
, 0);
60 button
= devm_kmalloc(&pdev
->dev
, sizeof(*button
), GFP_KERNEL
);
64 button
->idev
= devm_input_allocate_device(&pdev
->dev
);
68 button
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
72 button
->dev
= &pdev
->dev
;
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
);
79 err
= devm_request_threaded_irq(&pdev
->dev
, irq
, NULL
,
80 powerbutton_irq
, IRQF_ONESHOT
, "cpcap_pwrbutton", button
);
82 dev_err(&pdev
->dev
, "IRQ request failed: %d\n", err
);
86 err
= input_register_device(button
->idev
);
88 dev_err(&pdev
->dev
, "Input register failed: %d\n", err
);
92 device_init_wakeup(&pdev
->dev
, true);
98 static const struct of_device_id cpcap_pwrbutton_dt_match_table
[] = {
99 { .compatible
= "motorola,cpcap-pwrbutton" },
102 MODULE_DEVICE_TABLE(of
, cpcap_pwrbutton_dt_match_table
);
105 static struct platform_driver cpcap_power_button_driver
= {
106 .probe
= cpcap_power_button_probe
,
108 .name
= "cpcap-pwrbutton",
109 .of_match_table
= of_match_ptr(cpcap_pwrbutton_dt_match_table
),
112 module_platform_driver(cpcap_power_button_driver
);
114 MODULE_ALIAS("platform:cpcap-pwrbutton");
115 MODULE_DESCRIPTION("CPCAP Power Button");
116 MODULE_LICENSE("GPL");
117 MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");