blob: 8651a18573a10de1ef58b63f7606cdd70b64ebed [file] [log] [blame]
b.liub17525e2025-05-14 17:22:29 +08001/*******************************************************************************
2* Copyright (C) 2009, mbtk Corporation.
3*
4* File Name: mbtk_GpioWakeUp.c
5* File Mark:
6* Description:
7* Others:
8* Version: V1.0
9* Author: xxxx
10* Date: 2023-07-04
11* History 1:
12* Date:
13* Version:
14* Author:
15* Modification:
16* History 2:
17********************************************************************************/
18
19/****************************************************************************
20* Include files
21****************************************************************************/
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/kthread.h>
25#include <linux/init.h>
26#include <linux/spinlock.h>
27#include <linux/interrupt.h>
28#include <linux/types.h>
29#include <linux/suspend.h>
30#include <linux/tick.h>
31#include <linux/slab.h>
32#include <linux/err.h>
33
34#include <linux/of_irq.h>
35#include <linux/of_address.h>
36#include <linux/of_platform.h>
37#include <linux/of_gpio.h>
hj.shaobbc35142025-08-26 23:30:26 -070038#include <linux/edge_wakeup_mmp.h>
b.liub17525e2025-05-14 17:22:29 +080039
40//#include <mach/irqs.h>
41//#include <uapi/linux/gpio.h>
42//#include <linux/soc/sc/pcu.h>
43#include <linux/irq.h>
44#include <linux/delay.h>
45#include <linux/gpio.h>
46#include <linux/pm_wakeup.h>
47//#include <linux/soc/sc/drv_idle.h>
48
49#include <linux/sysfs.h>
50#include <linux/kobject.h>
51#include <linux/input.h>
52/****************************************************************************
53* Local Macros
54****************************************************************************/
55
56#define HAS_WAKE_OUT_PIN 1 // 1: for output pin level when wakeup or sleeping; 0 is disable
57
58#define HAS_WAKE_SOURCE_LOCK 1 //1: for wakelock when wakeup and release when sleeping with the wake gpio level
59
60#define HAL_GPIO_WAKUP_PM 1 // release or lock wakelock when sleep or wakeup
61
62#define WAKEUP_STATE_VALUE 0
63
64#define WAKEUP_KEY KEY_1 //KEY_POWER ,report key code to application
65
lichengzhange3717712025-06-19 10:43:51 +080066#define CP_WAKE_STATUS 1
b.liub17525e2025-05-14 17:22:29 +080067
lichengzhange3717712025-06-19 10:43:51 +080068#define CP_SLEEP_STATUS 0
b.liub17525e2025-05-14 17:22:29 +080069
70#ifndef TRUE
71#define TRUE 1
72#endif
73
74#ifndef FALSE
75#define FALSE 0
76#endif
77
78
79
80#define GPIO_WAKUP_DEBUG
81
82#ifdef GPIO_WAKUP_DEBUG
83#define GPIO_WAKUP_debug(fmt, args...) printk(KERN_INFO "[SLP] " fmt, ##args)
84#else
85#define GPIO_WAKUP_debug(fmt, args...)
86#endif
87
88#define GPIO_WAKUP_STATE "GpioWakeUp_state"
89/****************************************************************************
90* Local Types
91****************************************************************************/
92
93
94struct mbtkGpioWakeUp_dev
95{
96 struct device *dev;
97 struct pinctrl *pctrl_wk_int;
98 struct pinctrl_state *st_gpio;
99 struct pinctrl_state *st_int;
100 int wake_state;
101 int curr_gpio_value;
102
103 struct task_struct *wake_int_thread;
104 spinlock_t wk_lock;
105
106 struct semaphore wk_sem;
107 int wake_ap_gpio;
108 int wake_me_gpio;
109 struct gpio_desc *gd;
110 struct input_dev *input;
111 int eint_irq;
112 int GpioWakeUp_irq_state;
113 int wake_cnt;
114 int sleep_cnt;
115 struct wakeup_source *GpioWakeUp_ws;
116
117};
118
119
120/****************************************************************************
121* Global Variables
122****************************************************************************/
123
124//static int wakeup_irq_occurs = 0;
125struct wakeup_source *GpioWakeUp_wake_lock;
126static int GpioWakeUp_init_flag = 0;
127
128
129
130static int currState = 1;
131
132/****************************************************************************
133* Local Constants
134****************************************************************************/
135
136
137struct mbtkGpioWakeUp_dev g_GpioWakeUp = {0};
138
139
140/*******************************************************************************
141* Function: ApWakeCp int
142* Description: ap2cp wake up int thread
143* Parameters:
144* Input:
145*
146* Output:
147*
148* Returns:
149*
150* Others:
151********************************************************************************/
152
153irqreturn_t GpioWakeUp_wkcp_thread_fn(int irq, void *priv)
154{
155 unsigned long flags;
156 int gpio_value;
157
158 struct mbtkGpioWakeUp_dev *GpioWakeUp_dev = (struct mbtkGpioWakeUp_dev *)priv;
159
160 disable_irq_nosync(irq);/*jb.qi add for dtr on 20240202*/
161
162 gpio_value = 0 ;
163
164 //pr_err("%s/L%d\n", __func__, __LINE__);
165 if(GpioWakeUp_dev->GpioWakeUp_ws){
166 //gpio_value = gpio_get_value_cansleep(GpioWakeUp_dev->wake_me_gpio) ;
167 //if(gpio_value == 0)
168 __pm_wakeup_event(GpioWakeUp_dev->GpioWakeUp_ws, 2000);
169 }
170
171 /*if (pinctrl_select_state(GpioWakeUp_dev->pctrl_wk_int, GpioWakeUp_dev->st_gpio) < 0) {
172 printk("setting card detect gpio failed\n");
173 }*/
174
175 spin_lock_irqsave(&GpioWakeUp_dev->wk_lock, flags);
176 gpio_value = gpio_get_value_cansleep(GpioWakeUp_dev->wake_me_gpio) ;
177 spin_unlock_irqrestore(&GpioWakeUp_dev->wk_lock, flags);
178
179 if(gpio_value < 0)
180 {
181 printk( "[%s-%d]: gpio get state failed\n",__func__,__LINE__);
182 }
183 if(gpio_value != currState)
184 {
185 GPIO_WAKUP_debug("interrup handler: gpio%d_value is %d \n",GpioWakeUp_dev->wake_me_gpio,gpio_value);
186 GpioWakeUp_dev->wake_state = gpio_value;
187 //input_report_key(GpioWakeUp_dev->input, WAKEUP_KEY, !!gpio_value);
188
189 input_event(GpioWakeUp_dev->input, EV_MSC, MSC_RAW, !!gpio_value);
190 input_sync(GpioWakeUp_dev->input);
191
192#if HAS_WAKE_SOURCE_LOCK
193 if(WAKEUP_STATE_VALUE == gpio_value){ //wake up
194
195 pm_stay_awake(g_GpioWakeUp.dev);
196 }
197 else{ //into sleep
198
199 pm_relax(g_GpioWakeUp.dev);
200 }
201#endif
202 }
203 currState = gpio_value;
204
205 enable_irq(GpioWakeUp_dev->eint_irq);
206
207 return IRQ_HANDLED;
208}
209
210#if HAL_GPIO_WAKUP_PM
211
212static int mbtkGpioWakeUp_pm_resume(struct device *dev)
213{
214
215 //pm_stay_awake(g_GpioWakeUp.dev);
lichengzhangd4192112025-07-02 13:25:50 +0800216 //gpio_direction_output(g_GpioWakeUp.wake_ap_gpio, CP_WAKE_STATUS);
b.liub17525e2025-05-14 17:22:29 +0800217 pr_info("mbtkGpioWakeUp_pm_resume\n");
218 return 0;
219}
220
221static int mbtkGpioWakeUp_pm_suspend(struct device *dev)
222{
223 //pm_relax(g_GpioWakeUp.dev);
224 gpio_direction_output(g_GpioWakeUp.wake_ap_gpio, CP_SLEEP_STATUS);
225 pr_info("mbtkGpioWakeUp_pm_suspend\n");
226 return 0;
227}
228
229static int mbtkGpioWakeUp_pm_runtime_resume(struct device *dev)
230{
231 /* enable clk and restore regs */
232 pr_info("mbtkGpioWakeUp_pm_runtime_resume\n");
233 return 0;
234}
235
236static int mbtkGpioWakeUp_pm_runtime_suspend(struct device *dev)
237{
238 /* backup regs and disable clk */
239 pr_info("mbtkGpioWakeUp_pm_runtime_suspend\n");
240 return 0;
241}
242
243static int mbtkGpioWakeUp_pm_runtime_idle(struct device *dev)
244{
245 pr_info("mbtkGpioWakeUp_pm_runtime_idle\n");
246 return 0;
247}
248
249static const struct dev_pm_ops mbtkGpioWakeUp_pm = {
250 .resume = mbtkGpioWakeUp_pm_resume,
251 .suspend = mbtkGpioWakeUp_pm_suspend,
252 .runtime_resume = mbtkGpioWakeUp_pm_runtime_resume,
253 .runtime_suspend = mbtkGpioWakeUp_pm_runtime_suspend,
254 .runtime_idle = mbtkGpioWakeUp_pm_runtime_idle
255};
256#endif
257
258
259static const struct of_device_id mbtkGpioWakeUp_match[] = {
260 { .compatible = "mbtk,GpioWakeUp", },
261 { }
262};
263
264static ssize_t mbtkGpioWakeUp_value_show(struct device *dev,
265 struct device_attribute *attr, char *buf)
266{
267 int gpio_value;
268 unsigned long flags;
269
270 struct mbtkGpioWakeUp_dev *GpioWakeUp_dev = &g_GpioWakeUp;
271 spin_lock_irqsave(&GpioWakeUp_dev->wk_lock, flags);
272 gpio_value = gpio_get_value_cansleep(GpioWakeUp_dev->wake_me_gpio) ;
273 spin_unlock_irqrestore(&GpioWakeUp_dev->wk_lock, flags);
274 currState = gpio_value;
275 input_event(GpioWakeUp_dev->input, EV_MSC, MSC_RAW, gpio_value);
276 input_sync(GpioWakeUp_dev->input);
277 sprintf(buf, "%d\n", gpio_value);
278 printk("gpio%d = %d \n",GpioWakeUp_dev->wake_me_gpio,gpio_value);
279 return strlen(buf) + 1;
280}
281
282static ssize_t mbtkGpioWakeUp_value_store(struct device *dev,
283 struct device_attribute *attr, const char *buf,
284 size_t size)
285{
286 int gpio_value=0;
287 struct mbtkGpioWakeUp_dev *GpioWakeUp_dev = &g_GpioWakeUp;
288 sscanf(buf, "%d", &gpio_value);
289 if (gpio_value != 0 && gpio_value != 1) {
290 pr_err("%s: invalid value %d, should be 0 or 1\n",
291 __func__, gpio_value);
292 return -EINVAL;
293 }
294 input_event(GpioWakeUp_dev->input, EV_MSC, MSC_RAW, gpio_value);
295 input_sync(GpioWakeUp_dev->input);
296
297 return size;
298}
299
300static DEVICE_ATTR(WakeUpValue, 0664, mbtkGpioWakeUp_value_show, mbtkGpioWakeUp_value_store);
301
302int mbtkGpioWakeUp_probe(struct platform_device *pdev)
303{
304 int gpio;
hj.shao403e7042025-08-07 21:10:27 -0700305 int hsm_en_gpio;
b.liub17525e2025-05-14 17:22:29 +0800306 int gpio_value;
307 unsigned long flags;
308 int ret = 0, error;
309
310 struct device_node *np = NULL;
311 struct input_dev *input;
312
313 g_GpioWakeUp.dev = &pdev->dev;
314 np = pdev->dev.of_node;
315
316 sema_init(&g_GpioWakeUp.wk_sem,0);
317 spin_lock_init(&g_GpioWakeUp.wk_lock);
318
319 device_init_wakeup(&pdev->dev, true);
320
321 g_GpioWakeUp.GpioWakeUp_ws = wakeup_source_register(g_GpioWakeUp.dev ,"GpioWakeUp");
322 if(g_GpioWakeUp.GpioWakeUp_ws == NULL){
323 printk("adb_setup wakeup_source_create fail\n");
324 goto wake_source_init_fail;
325 }
326
hj.shao403e7042025-08-07 21:10:27 -0700327 hsm_en_gpio = of_get_named_gpio(np, "hsm-en-out-gpio", 0);
328 if (unlikely(hsm_en_gpio < 0)) {
329 pr_err("%s. parse hsm-en-out-gpio failed\n", __func__);
330 ret = -EINVAL;
331 } else {
332 pr_err("%s. hsm-en-out-gpio=%d\n", __func__, hsm_en_gpio);
333 if (gpio_request(hsm_en_gpio, "hsm-en-out-gpio")) {
334 pr_err("Failed to request GPIO %d\n", hsm_en_gpio);
335 ret = -EBUSY;
336 }
337 if (gpio_direction_output(hsm_en_gpio, 1)) {
338 pr_err("Failed to set GPIO %d as output\n", hsm_en_gpio);
339 ret = -EIO;
340 }
341 pr_err("hsm-gpio config sucess\n");
342 gpio_free(hsm_en_gpio);
343 }
344
b.liub17525e2025-05-14 17:22:29 +0800345
346 gpio = of_get_named_gpio(np, "wakeup-in-gpio", 0);
347 if (unlikely(gpio < 0)) {
348 pr_err("%s. parse wakeup-in-gpio failed\n", __func__);
349 ret = -EINVAL;
350 } else {
351 pr_err("%s. wakeup-in-gpio=%d\n", __func__, gpio);
352 }
353
354 if(gpio >= 0)
355 {
hj.shaobbc35142025-08-26 23:30:26 -0700356 request_mfp_edge_wakeup(gpio, NULL, NULL, g_GpioWakeUp.dev);
hong.liuf2416882025-05-23 20:41:06 -0700357 /*LYNQ_MODFIY_START
b.liub17525e2025-05-14 17:22:29 +0800358 ret = gpio_request(gpio, "wakeup-in");
359 if(ret < 0)
360 {
hong.liuf2416882025-05-23 20:41:06 -0700361 pr_err("%s. gpio_request for wakeup-in-gpio=%d failed\n", __func__,gpio);
362 return ret;
b.liub17525e2025-05-14 17:22:29 +0800363 }
hong.liuf2416882025-05-23 20:41:06 -0700364 LYNQ_MODFIY_END*/
b.liub17525e2025-05-14 17:22:29 +0800365 g_GpioWakeUp.wake_me_gpio = gpio;
366
367 gpio_direction_input(g_GpioWakeUp.wake_me_gpio);
368
369 g_GpioWakeUp.eint_irq = gpio_to_irq(g_GpioWakeUp.wake_me_gpio);
370
371 if (g_GpioWakeUp.eint_irq < 0)
372 {
373 error = g_GpioWakeUp.eint_irq ;
374 printk("Unable to get irq number for GPIO %d, error %d\n",g_GpioWakeUp.wake_me_gpio, error);
375 goto wake_in_pin_init_fail;
376 }
377 else
378 {
379 printk("wake in gpio request irq %d sucess\n", g_GpioWakeUp.eint_irq);
380 }
381 }
382
383 input = input_allocate_device();;
384 if (!input) {
385 printk("failed to allocate state\n");
386 error = -ENOMEM;
387 goto input_fail;
388 }
389
390
391 g_GpioWakeUp.input = input;
392 input->name = "WAKE-in-GPIO";
393
394 /* 2. ?? */
395 /* 2.1 ??????? */
396 set_bit(EV_MSC, g_GpioWakeUp.input->evbit);
397 set_bit(EV_SYN, g_GpioWakeUp.input->evbit);
398 /* 2.2 ?????????????: L,S,ENTER,LEFTSHIT */
399
400 set_bit(MSC_RAW, g_GpioWakeUp.input->mscbit);
401 //set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);
402
403 /* 3. ?? */
404 input_set_capability(g_GpioWakeUp.input, EV_MSC, MSC_RAW);
405 error = input_register_device(input);
406 if (error)
407 {
408 pr_err("%s. input_register_device=%d failed\n", __func__,error);
409
410 goto input_fail;
411 }
412
413
414 spin_lock_irqsave(&g_GpioWakeUp.wk_lock, flags);
415
416 gpio_value = gpio_get_value(g_GpioWakeUp.wake_me_gpio) ;
417
418 spin_unlock_irqrestore(&g_GpioWakeUp.wk_lock, flags);
419 if(gpio_value < 0)
420 {
421 printk( "[%s-%d]: gpio get state failed\n",__func__,__LINE__);
422 }
423
424 //input_report_key(g_GpioWakeUp.input, KEY_1, !!gpio_value);
425
426 input_event(input, EV_MSC, MSC_RAW, !!gpio_value);
427 input_sync(input);
428
429#if HAS_WAKE_SOURCE_LOCK
430 if(WAKEUP_STATE_VALUE == gpio_value)
431 {
432 pm_stay_awake(g_GpioWakeUp.dev);
433 }
434 else
435 {
436
437 pm_relax(g_GpioWakeUp.dev);
438 }
439#endif
440
441 currState = gpio_value;
442
443 GPIO_WAKUP_debug("%s. devm_request_threaded_irqn", __func__);
444
445 ret = devm_request_threaded_irq(g_GpioWakeUp.dev, g_GpioWakeUp.eint_irq,NULL,GpioWakeUp_wkcp_thread_fn, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT),"GpioWakeUp_wake int", &g_GpioWakeUp);
446
447 if(ret<0){
448 panic("mbtkGpioWakeUp_probe request_irq fail, %d", ret);
449 }
450
451
452 enable_irq_wake(g_GpioWakeUp.eint_irq);
453
454 ret = device_create_file(g_GpioWakeUp.dev, &dev_attr_WakeUpValue);
455 if(ret)
456 {
457 printk("ERROR: mbtkGpioWakeUp device_create_file failed\n");
458 }
459
460#if HAS_WAKE_OUT_PIN
461 gpio = of_get_named_gpio(np, "wakeup-out-gpio", 0);
462 if (unlikely(gpio < 0)) {
463 pr_err("%s. parse wakeup-out-gpio failed\n", __func__);
464 } else
465 {
466 pr_err("%s. wakeup-out-gpio=%d\n", __func__, gpio);
467 }
468
469 if(gpio >= 0)
470 {
hong.liuf2416882025-05-23 20:41:06 -0700471 /*LYNQ_MODFIY_START
b.liub17525e2025-05-14 17:22:29 +0800472 ret = gpio_request(gpio, "wakeup-out");
473 if(ret < 0)
474 {
475 pr_err("%s. gpio_request for wakeup-out-gpio=%d failed\n", __func__,gpio);
476 goto wake_out_pin_init_fail;
477 }
hong.liuf2416882025-05-23 20:41:06 -0700478 LYNQ_MODFIY_END*/
b.liub17525e2025-05-14 17:22:29 +0800479 g_GpioWakeUp.wake_ap_gpio = gpio;
480 GPIO_WAKUP_debug("%s. gpio_request for wakeup-out-gpio=%d sucess\n", __func__,g_GpioWakeUp.wake_ap_gpio);
481 }
482
lichengzhange2da2ca2025-06-03 16:28:45 +0800483 gpio_direction_output(g_GpioWakeUp.wake_ap_gpio, CP_WAKE_STATUS);
b.liub17525e2025-05-14 17:22:29 +0800484
485#endif
486
487
488 g_GpioWakeUp.wake_cnt = 0;
489 g_GpioWakeUp.sleep_cnt = 0;
490
491#if HAS_WAKE_OUT_PIN
492wake_out_pin_init_fail:
493 if(ret){
494 pr_err("wakeup-out gpio%d init failed\n",gpio);
495 }
496#endif
497
498input_fail:
499 input_free_device(g_GpioWakeUp.input);
500
501wake_in_pin_init_fail:
502 if(ret){
503 pr_err("wakeup-in gpio%d init failed\n",gpio);
504 }
505
506//pinctrl_init_fail:
507// if(ret){
508// printk("pinctrl_init_fail\n");
509// }
510
511wake_source_init_fail:
512
513 //pm_relax(g_GpioWakeUp.dev);
514 return ret;
515}
516
517static struct platform_driver mbtkGpioWakeUp_driver = {
518 .probe = mbtkGpioWakeUp_probe,
519 .driver = {
520 .name = "mbtk_GpioWakeUp",
521#if HAL_GPIO_WAKUP_PM
522 .pm = &mbtkGpioWakeUp_pm,
523#endif
524 .of_match_table = mbtkGpioWakeUp_match,
525 },
526};
527
528
529/*******************************************************************************
530* Function: zDrvAp2cp_Initiate
531* Description:
532* Parameters:
533* Input:
534*
535* Output:
536*
537* Returns:
538*
539* Others:
540********************************************************************************/
541static int __init zDrvGpioWakeUp_Initiate(void)
542{
543 int ret=0;
544 //int errCode = -1;
545
546 GpioWakeUp_init_flag = 1;
547
548 ret = platform_driver_register(&mbtkGpioWakeUp_driver);
549 if (ret != 0){
550 printk("GPIO_WAKUP: platform_driver_register fail!\n");
551 return ret;
552 }
553
554 return 0;
555}
556
557int zDrvGpioWakeUp_Release(void)
558{
559
560 gpio_free(g_GpioWakeUp.wake_me_gpio);
561#if HAS_WAKE_OUT_PIN
562 gpio_free(g_GpioWakeUp.wake_ap_gpio);
563#endif
564
565 return 0;
566}
567
568
569late_initcall(zDrvGpioWakeUp_Initiate);
570
571//module_exit(zDrvGpioWakeUp_Release);
572
573