1*62f0f079SAndrey Smirnov // SPDX-License-Identifier: GPL-2.0+
2*62f0f079SAndrey Smirnov //
3*62f0f079SAndrey Smirnov // Power Button driver for RAVE SP
4*62f0f079SAndrey Smirnov //
5*62f0f079SAndrey Smirnov // Copyright (C) 2017 Zodiac Inflight Innovations
6*62f0f079SAndrey Smirnov //
7*62f0f079SAndrey Smirnov //
8*62f0f079SAndrey Smirnov
9*62f0f079SAndrey Smirnov #include <linux/input.h>
10*62f0f079SAndrey Smirnov #include <linux/kernel.h>
11*62f0f079SAndrey Smirnov #include <linux/module.h>
12*62f0f079SAndrey Smirnov #include <linux/mfd/rave-sp.h>
13*62f0f079SAndrey Smirnov #include <linux/platform_device.h>
14*62f0f079SAndrey Smirnov
15*62f0f079SAndrey Smirnov #define RAVE_SP_EVNT_BUTTON_PRESS (RAVE_SP_EVNT_BASE + 0x00)
16*62f0f079SAndrey Smirnov
17*62f0f079SAndrey Smirnov struct rave_sp_power_button {
18*62f0f079SAndrey Smirnov struct input_dev *idev;
19*62f0f079SAndrey Smirnov struct notifier_block nb;
20*62f0f079SAndrey Smirnov };
21*62f0f079SAndrey Smirnov
rave_sp_power_button_event(struct notifier_block * nb,unsigned long action,void * data)22*62f0f079SAndrey Smirnov static int rave_sp_power_button_event(struct notifier_block *nb,
23*62f0f079SAndrey Smirnov unsigned long action, void *data)
24*62f0f079SAndrey Smirnov {
25*62f0f079SAndrey Smirnov struct rave_sp_power_button *pb =
26*62f0f079SAndrey Smirnov container_of(nb, struct rave_sp_power_button, nb);
27*62f0f079SAndrey Smirnov const u8 event = rave_sp_action_unpack_event(action);
28*62f0f079SAndrey Smirnov const u8 value = rave_sp_action_unpack_value(action);
29*62f0f079SAndrey Smirnov struct input_dev *idev = pb->idev;
30*62f0f079SAndrey Smirnov
31*62f0f079SAndrey Smirnov if (event == RAVE_SP_EVNT_BUTTON_PRESS) {
32*62f0f079SAndrey Smirnov input_report_key(idev, KEY_POWER, value);
33*62f0f079SAndrey Smirnov input_sync(idev);
34*62f0f079SAndrey Smirnov
35*62f0f079SAndrey Smirnov return NOTIFY_STOP;
36*62f0f079SAndrey Smirnov }
37*62f0f079SAndrey Smirnov
38*62f0f079SAndrey Smirnov return NOTIFY_DONE;
39*62f0f079SAndrey Smirnov }
40*62f0f079SAndrey Smirnov
rave_sp_pwrbutton_probe(struct platform_device * pdev)41*62f0f079SAndrey Smirnov static int rave_sp_pwrbutton_probe(struct platform_device *pdev)
42*62f0f079SAndrey Smirnov {
43*62f0f079SAndrey Smirnov struct device *dev = &pdev->dev;
44*62f0f079SAndrey Smirnov struct rave_sp_power_button *pb;
45*62f0f079SAndrey Smirnov struct input_dev *idev;
46*62f0f079SAndrey Smirnov int error;
47*62f0f079SAndrey Smirnov
48*62f0f079SAndrey Smirnov pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
49*62f0f079SAndrey Smirnov if (!pb)
50*62f0f079SAndrey Smirnov return -ENOMEM;
51*62f0f079SAndrey Smirnov
52*62f0f079SAndrey Smirnov idev = devm_input_allocate_device(dev);
53*62f0f079SAndrey Smirnov if (!idev)
54*62f0f079SAndrey Smirnov return -ENOMEM;
55*62f0f079SAndrey Smirnov
56*62f0f079SAndrey Smirnov idev->name = pdev->name;
57*62f0f079SAndrey Smirnov
58*62f0f079SAndrey Smirnov input_set_capability(idev, EV_KEY, KEY_POWER);
59*62f0f079SAndrey Smirnov
60*62f0f079SAndrey Smirnov error = input_register_device(idev);
61*62f0f079SAndrey Smirnov if (error)
62*62f0f079SAndrey Smirnov return error;
63*62f0f079SAndrey Smirnov
64*62f0f079SAndrey Smirnov pb->idev = idev;
65*62f0f079SAndrey Smirnov pb->nb.notifier_call = rave_sp_power_button_event;
66*62f0f079SAndrey Smirnov pb->nb.priority = 128;
67*62f0f079SAndrey Smirnov
68*62f0f079SAndrey Smirnov error = devm_rave_sp_register_event_notifier(dev, &pb->nb);
69*62f0f079SAndrey Smirnov if (error)
70*62f0f079SAndrey Smirnov return error;
71*62f0f079SAndrey Smirnov
72*62f0f079SAndrey Smirnov return 0;
73*62f0f079SAndrey Smirnov }
74*62f0f079SAndrey Smirnov
75*62f0f079SAndrey Smirnov static const struct of_device_id rave_sp_pwrbutton_of_match[] = {
76*62f0f079SAndrey Smirnov { .compatible = "zii,rave-sp-pwrbutton" },
77*62f0f079SAndrey Smirnov {}
78*62f0f079SAndrey Smirnov };
79*62f0f079SAndrey Smirnov
80*62f0f079SAndrey Smirnov static struct platform_driver rave_sp_pwrbutton_driver = {
81*62f0f079SAndrey Smirnov .probe = rave_sp_pwrbutton_probe,
82*62f0f079SAndrey Smirnov .driver = {
83*62f0f079SAndrey Smirnov .name = KBUILD_MODNAME,
84*62f0f079SAndrey Smirnov .of_match_table = rave_sp_pwrbutton_of_match,
85*62f0f079SAndrey Smirnov },
86*62f0f079SAndrey Smirnov };
87*62f0f079SAndrey Smirnov module_platform_driver(rave_sp_pwrbutton_driver);
88*62f0f079SAndrey Smirnov
89*62f0f079SAndrey Smirnov MODULE_DEVICE_TABLE(of, rave_sp_pwrbutton_of_match);
90*62f0f079SAndrey Smirnov MODULE_LICENSE("GPL");
91*62f0f079SAndrey Smirnov MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
92*62f0f079SAndrey Smirnov MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
93*62f0f079SAndrey Smirnov MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
94*62f0f079SAndrey Smirnov MODULE_DESCRIPTION("RAVE SP Power Button driver");
95