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