blob: 008327bece82c38d33ac9dbecdfb3029f0b4a7b7 [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
lichengzhange3717712025-06-19 10:43:51 +080065#define CP_WAKE_STATUS 1
b.liub17525e2025-05-14 17:22:29 +080066
lichengzhange3717712025-06-19 10:43:51 +080067#define CP_SLEEP_STATUS 0
b.liub17525e2025-05-14 17:22:29 +080068
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);
lichengzhangd4192112025-07-02 13:25:50 +0800215 //gpio_direction_output(g_GpioWakeUp.wake_ap_gpio, CP_WAKE_STATUS);
b.liub17525e2025-05-14 17:22:29 +0800216 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;
hj.shao403e7042025-08-07 21:10:27 -0700304 int hsm_en_gpio;
b.liub17525e2025-05-14 17:22:29 +0800305 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
hj.shao403e7042025-08-07 21:10:27 -0700326 hsm_en_gpio = of_get_named_gpio(np, "hsm-en-out-gpio", 0);
327 if (unlikely(hsm_en_gpio < 0)) {
328 pr_err("%s. parse hsm-en-out-gpio failed\n", __func__);
329 ret = -EINVAL;
330 } else {
331 pr_err("%s. hsm-en-out-gpio=%d\n", __func__, hsm_en_gpio);
332 if (gpio_request(hsm_en_gpio, "hsm-en-out-gpio")) {
333 pr_err("Failed to request GPIO %d\n", hsm_en_gpio);
334 ret = -EBUSY;
335 }
336 if (gpio_direction_output(hsm_en_gpio, 1)) {
337 pr_err("Failed to set GPIO %d as output\n", hsm_en_gpio);
338 ret = -EIO;
339 }
340 pr_err("hsm-gpio config sucess\n");
341 gpio_free(hsm_en_gpio);
342 }
343
b.liub17525e2025-05-14 17:22:29 +0800344
345 gpio = of_get_named_gpio(np, "wakeup-in-gpio", 0);
346 if (unlikely(gpio < 0)) {
347 pr_err("%s. parse wakeup-in-gpio failed\n", __func__);
348 ret = -EINVAL;
349 } else {
350 pr_err("%s. wakeup-in-gpio=%d\n", __func__, gpio);
351 }
352
353 if(gpio >= 0)
354 {
hong.liuf2416882025-05-23 20:41:06 -0700355 /*LYNQ_MODFIY_START
b.liub17525e2025-05-14 17:22:29 +0800356 ret = gpio_request(gpio, "wakeup-in");
357 if(ret < 0)
358 {
hong.liuf2416882025-05-23 20:41:06 -0700359 pr_err("%s. gpio_request for wakeup-in-gpio=%d failed\n", __func__,gpio);
360 return ret;
b.liub17525e2025-05-14 17:22:29 +0800361 }
hong.liuf2416882025-05-23 20:41:06 -0700362 LYNQ_MODFIY_END*/
b.liub17525e2025-05-14 17:22:29 +0800363 g_GpioWakeUp.wake_me_gpio = gpio;
364
365 gpio_direction_input(g_GpioWakeUp.wake_me_gpio);
366
367 g_GpioWakeUp.eint_irq = gpio_to_irq(g_GpioWakeUp.wake_me_gpio);
368
369 if (g_GpioWakeUp.eint_irq < 0)
370 {
371 error = g_GpioWakeUp.eint_irq ;
372 printk("Unable to get irq number for GPIO %d, error %d\n",g_GpioWakeUp.wake_me_gpio, error);
373 goto wake_in_pin_init_fail;
374 }
375 else
376 {
377 printk("wake in gpio request irq %d sucess\n", g_GpioWakeUp.eint_irq);
378 }
379 }
380
381 input = input_allocate_device();;
382 if (!input) {
383 printk("failed to allocate state\n");
384 error = -ENOMEM;
385 goto input_fail;
386 }
387
388
389 g_GpioWakeUp.input = input;
390 input->name = "WAKE-in-GPIO";
391
392 /* 2. ?? */
393 /* 2.1 ??????? */
394 set_bit(EV_MSC, g_GpioWakeUp.input->evbit);
395 set_bit(EV_SYN, g_GpioWakeUp.input->evbit);
396 /* 2.2 ?????????????: L,S,ENTER,LEFTSHIT */
397
398 set_bit(MSC_RAW, g_GpioWakeUp.input->mscbit);
399 //set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);
400
401 /* 3. ?? */
402 input_set_capability(g_GpioWakeUp.input, EV_MSC, MSC_RAW);
403 error = input_register_device(input);
404 if (error)
405 {
406 pr_err("%s. input_register_device=%d failed\n", __func__,error);
407
408 goto input_fail;
409 }
410
411
412 spin_lock_irqsave(&g_GpioWakeUp.wk_lock, flags);
413
414 gpio_value = gpio_get_value(g_GpioWakeUp.wake_me_gpio) ;
415
416 spin_unlock_irqrestore(&g_GpioWakeUp.wk_lock, flags);
417 if(gpio_value < 0)
418 {
419 printk( "[%s-%d]: gpio get state failed\n",__func__,__LINE__);
420 }
421
422 //input_report_key(g_GpioWakeUp.input, KEY_1, !!gpio_value);
423
424 input_event(input, EV_MSC, MSC_RAW, !!gpio_value);
425 input_sync(input);
426
427#if HAS_WAKE_SOURCE_LOCK
428 if(WAKEUP_STATE_VALUE == gpio_value)
429 {
430 pm_stay_awake(g_GpioWakeUp.dev);
431 }
432 else
433 {
434
435 pm_relax(g_GpioWakeUp.dev);
436 }
437#endif
438
439 currState = gpio_value;
440
441 GPIO_WAKUP_debug("%s. devm_request_threaded_irqn", __func__);
442
443 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);
444
445 if(ret<0){
446 panic("mbtkGpioWakeUp_probe request_irq fail, %d", ret);
447 }
448
449
450 enable_irq_wake(g_GpioWakeUp.eint_irq);
451
452 ret = device_create_file(g_GpioWakeUp.dev, &dev_attr_WakeUpValue);
453 if(ret)
454 {
455 printk("ERROR: mbtkGpioWakeUp device_create_file failed\n");
456 }
457
458#if HAS_WAKE_OUT_PIN
459 gpio = of_get_named_gpio(np, "wakeup-out-gpio", 0);
460 if (unlikely(gpio < 0)) {
461 pr_err("%s. parse wakeup-out-gpio failed\n", __func__);
462 } else
463 {
464 pr_err("%s. wakeup-out-gpio=%d\n", __func__, gpio);
465 }
466
467 if(gpio >= 0)
468 {
hong.liuf2416882025-05-23 20:41:06 -0700469 /*LYNQ_MODFIY_START
b.liub17525e2025-05-14 17:22:29 +0800470 ret = gpio_request(gpio, "wakeup-out");
471 if(ret < 0)
472 {
473 pr_err("%s. gpio_request for wakeup-out-gpio=%d failed\n", __func__,gpio);
474 goto wake_out_pin_init_fail;
475 }
hong.liuf2416882025-05-23 20:41:06 -0700476 LYNQ_MODFIY_END*/
b.liub17525e2025-05-14 17:22:29 +0800477 g_GpioWakeUp.wake_ap_gpio = gpio;
478 GPIO_WAKUP_debug("%s. gpio_request for wakeup-out-gpio=%d sucess\n", __func__,g_GpioWakeUp.wake_ap_gpio);
479 }
480
lichengzhange2da2ca2025-06-03 16:28:45 +0800481 gpio_direction_output(g_GpioWakeUp.wake_ap_gpio, CP_WAKE_STATUS);
b.liub17525e2025-05-14 17:22:29 +0800482
483#endif
484
485
486 g_GpioWakeUp.wake_cnt = 0;
487 g_GpioWakeUp.sleep_cnt = 0;
488
489#if HAS_WAKE_OUT_PIN
490wake_out_pin_init_fail:
491 if(ret){
492 pr_err("wakeup-out gpio%d init failed\n",gpio);
493 }
494#endif
495
496input_fail:
497 input_free_device(g_GpioWakeUp.input);
498
499wake_in_pin_init_fail:
500 if(ret){
501 pr_err("wakeup-in gpio%d init failed\n",gpio);
502 }
503
504//pinctrl_init_fail:
505// if(ret){
506// printk("pinctrl_init_fail\n");
507// }
508
509wake_source_init_fail:
510
511 //pm_relax(g_GpioWakeUp.dev);
512 return ret;
513}
514
515static struct platform_driver mbtkGpioWakeUp_driver = {
516 .probe = mbtkGpioWakeUp_probe,
517 .driver = {
518 .name = "mbtk_GpioWakeUp",
519#if HAL_GPIO_WAKUP_PM
520 .pm = &mbtkGpioWakeUp_pm,
521#endif
522 .of_match_table = mbtkGpioWakeUp_match,
523 },
524};
525
526
527/*******************************************************************************
528* Function: zDrvAp2cp_Initiate
529* Description:
530* Parameters:
531* Input:
532*
533* Output:
534*
535* Returns:
536*
537* Others:
538********************************************************************************/
539static int __init zDrvGpioWakeUp_Initiate(void)
540{
541 int ret=0;
542 //int errCode = -1;
543
544 GpioWakeUp_init_flag = 1;
545
546 ret = platform_driver_register(&mbtkGpioWakeUp_driver);
547 if (ret != 0){
548 printk("GPIO_WAKUP: platform_driver_register fail!\n");
549 return ret;
550 }
551
552 return 0;
553}
554
555int zDrvGpioWakeUp_Release(void)
556{
557
558 gpio_free(g_GpioWakeUp.wake_me_gpio);
559#if HAS_WAKE_OUT_PIN
560 gpio_free(g_GpioWakeUp.wake_ap_gpio);
561#endif
562
563 return 0;
564}
565
566
567late_initcall(zDrvGpioWakeUp_Initiate);
568
569//module_exit(zDrvGpioWakeUp_Release);
570
571