xref: /OK3568_Linux_fs/kernel/drivers/input/sensors/hall/mh248.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4  *
5  * Author: Bin Yang <yangbin@rock-chips.com>
6  */
7 
8 
9 #include <linux/platform_device.h>
10 #include <linux/interrupt.h>
11 #include <linux/i2c.h>
12 #include <linux/slab.h>
13 #include <linux/irq.h>
14 #include <linux/miscdevice.h>
15 #include <linux/gpio.h>
16 #include <linux/uaccess.h>
17 #include <linux/atomic.h>
18 #include <linux/delay.h>
19 #include <linux/input.h>
20 #include <linux/workqueue.h>
21 #include <linux/freezer.h>
22 #include <linux/of_gpio.h>
23 #include <linux/sensor-dev.h>
24 #include <linux/fb.h>
25 #include <linux/notifier.h>
26 #include <linux/rk_keys.h>
27 #include <linux/input.h>
28 
29 struct mh248_para {
30 	struct device *dev;
31 	struct notifier_block fb_notif;
32 	struct mutex ops_lock;
33 	struct input_dev *hall_input;
34 	int is_suspend;
35 	int gpio_pin;
36 	int irq;
37 	int active_value;
38 };
39 
hall_fb_notifier_callback(struct notifier_block * self,unsigned long action,void * data)40 static int hall_fb_notifier_callback(struct notifier_block *self,
41 				     unsigned long action, void *data)
42 {
43 	struct mh248_para *mh248;
44 	struct fb_event *event = data;
45 
46 	mh248 = container_of(self, struct mh248_para, fb_notif);
47 
48 	if (action != FB_EVENT_BLANK)
49 		return NOTIFY_DONE;
50 
51 	mutex_lock(&mh248->ops_lock);
52 	switch (*((int *)event->data)) {
53 	case FB_BLANK_UNBLANK:
54 		mh248->is_suspend = 0;
55 		break;
56 	default:
57 		mh248->is_suspend = 1;
58 		break;
59 	}
60 	mutex_unlock(&mh248->ops_lock);
61 
62 	return NOTIFY_OK;
63 }
64 
hall_mh248_interrupt(int irq,void * dev_id)65 static irqreturn_t hall_mh248_interrupt(int irq, void *dev_id)
66 {
67 	struct mh248_para *mh248 = (struct mh248_para *)dev_id;
68 	int gpio_value = 0;
69 
70 	gpio_value = gpio_get_value(mh248->gpio_pin);
71 	if ((gpio_value != mh248->active_value) &&
72 	    (mh248->is_suspend == 0)) {
73 		input_report_key(mh248->hall_input, KEY_POWER, 1);
74 		input_sync(mh248->hall_input);
75 		input_report_key(mh248->hall_input, KEY_POWER, 0);
76 		input_sync(mh248->hall_input);
77 	} else if ((gpio_value == mh248->active_value) &&
78 		   (mh248->is_suspend == 1)) {
79 		input_report_key(mh248->hall_input, KEY_WAKEUP, 1);
80 		input_sync(mh248->hall_input);
81 		input_report_key(mh248->hall_input, KEY_WAKEUP, 0);
82 		input_sync(mh248->hall_input);
83 	}
84 
85 	return IRQ_HANDLED;
86 }
87 
hall_mh248_probe(struct platform_device * pdev)88 static int hall_mh248_probe(struct platform_device *pdev)
89 {
90 	struct device_node *np = pdev->dev.of_node;
91 	struct mh248_para *mh248;
92 	enum of_gpio_flags irq_flags;
93 	int hallactive = 0;
94 	int ret = 0;
95 
96 	mh248 = devm_kzalloc(&pdev->dev, sizeof(*mh248), GFP_KERNEL);
97 	if (!mh248)
98 		return -ENOMEM;
99 
100 	mh248->dev = &pdev->dev;
101 
102 	mh248->gpio_pin = of_get_named_gpio_flags(np, "irq-gpio",
103 						  0, &irq_flags);
104 	if (!gpio_is_valid(mh248->gpio_pin)) {
105 		dev_err(mh248->dev, "Can not read property irq-gpio\n");
106 		return mh248->gpio_pin;
107 	}
108 	mh248->irq = gpio_to_irq(mh248->gpio_pin);
109 
110 	of_property_read_u32(np, "hall-active", &hallactive);
111 	mh248->active_value = hallactive;
112 	mh248->is_suspend = 0;
113 	mutex_init(&mh248->ops_lock);
114 
115 	ret = devm_gpio_request_one(mh248->dev, mh248->gpio_pin,
116 				    GPIOF_DIR_IN, "hall_mh248");
117 	if (ret < 0) {
118 		dev_err(mh248->dev, "fail to request gpio:%d\n", mh248->gpio_pin);
119 		return ret;
120 	}
121 
122 	ret = devm_request_threaded_irq(mh248->dev, mh248->irq,
123 					NULL, hall_mh248_interrupt,
124 					irq_flags | IRQF_NO_SUSPEND | IRQF_ONESHOT,
125 					"hall_mh248", mh248);
126 	if (ret < 0) {
127 		dev_err(mh248->dev, "request irq(%d) failed, ret=%d\n",
128 			mh248->irq, ret);
129 		return ret;
130 	}
131 
132 	mh248->hall_input = devm_input_allocate_device(&pdev->dev);
133 	if (!mh248->hall_input) {
134 		dev_err(&pdev->dev, "Can't allocate hall input dev\n");
135 		return -ENOMEM;
136 	}
137 	mh248->hall_input->name = "hall wake key";
138 	input_set_capability(mh248->hall_input, EV_KEY, KEY_POWER);
139 	input_set_capability(mh248->hall_input, EV_KEY, KEY_WAKEUP);
140 
141 	ret = input_register_device(mh248->hall_input);
142 	if (ret) {
143 		dev_err(&pdev->dev, "Unable to register input device, error: %d\n", ret);
144 		return ret;
145 	}
146 
147 	enable_irq_wake(mh248->irq);
148 	mh248->fb_notif.notifier_call = hall_fb_notifier_callback;
149 	fb_register_client(&mh248->fb_notif);
150 	dev_info(mh248->dev, "hall_mh248_probe success.\n");
151 
152 	return 0;
153 }
154 
155 static const struct of_device_id hall_mh248_match[] = {
156 	{ .compatible = "hall-mh248" },
157 	{ /* Sentinel */ }
158 };
159 
160 static struct platform_driver hall_mh248_driver = {
161 	.probe = hall_mh248_probe,
162 	.driver = {
163 		.name = "mh248",
164 		.owner = THIS_MODULE,
165 		.of_match_table	= hall_mh248_match,
166 	},
167 };
168 
169 module_platform_driver(hall_mh248_driver);
170 
171 MODULE_ALIAS("platform:mh248");
172 MODULE_AUTHOR("Bin Yang <yangbin@rock-chips.com>");
173 MODULE_LICENSE("GPL v2");
174 MODULE_DESCRIPTION("Hall Sensor MH248 driver");
175