1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <common/bk_include.h>
16 #include "icu_driver.h"
17 #include <os/mem.h>
18 #include "gpio_hal.h"
19 #include "gpio_driver_base.h"
20 #include "gpio_driver.h"
21 #include <driver/gpio_types.h>
22 #include <driver/int.h>
23 #include "amp_lock_api.h"
24 #if CONFIG_AON_PMU
25 #include "aon_pmu_driver.h"
26 #endif
27 #if (CONFIG_SYSTEM_CTRL)
28 #include "sys_driver.h"
29 #endif
30 #if CONFIG_GPIO_SIMULATE_UART_WRITE
31 #include "bk_misc.h"
32 #endif
33 gpio_driver_t s_gpio = {0};
34 static gpio_isr_t s_gpio_isr[SOC_GPIO_NUM] = {NULL};
35 static bool s_gpio_is_init = false;
36
37 #define GPIO_RETURN_ON_INVALID_ID(id) do {\
38 if ((id) >= SOC_GPIO_NUM) {\
39 return BK_ERR_GPIO_CHAN_ID;\
40 }\
41 } while(0)
42
43 #define GPIO_RETURN_ON_INVALID_INT_TYPE_MODE(mode) do {\
44 if ((mode) >= GPIO_INT_TYPE_MAX) {\
45 return BK_ERR_GPIO_INVALID_INT_TYPE;\
46 }\
47 } while(0)
48
49 #define GPIO_RETURN_ON_INVALID_IO_MODE(mode) do {\
50 if (((mode)) >= GPIO_IO_INVALID) {\
51 return BK_ERR_GPIO_INVALID_MODE;\
52 }\
53 } while(0)
54
55 #define GPIO_RETURN_ON_INVALID_PULL_MODE(mode) do {\
56 if (((mode)) >= GPIO_PULL_INVALID) {\
57 return BK_ERR_GPIO_INVALID_MODE;\
58 }\
59 } while(0)
60
61 #if CONFIG_GPIO_WAKEUP_SUPPORT
62 static uint16_t s_gpio_bak_regs[GPIO_NUM_MAX];
63 uint32_t s_gpio_bak_int_type_regs[3];
64 uint32_t s_gpio_bak_int_enable_regs[2];
65 uint64_t s_gpio_is_setted_wake_status;
66 static gpio_id_t s_gpio_wakeup_gpio_id = GPIO_NUM;
67
68 static void gpio_wakeup_default_isr(gpio_id_t gpio_id);
69
70 #if CONFIG_GPIO_DYNAMIC_WAKEUP_SUPPORT
71 #ifndef CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT
72 #define CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT (4)
73 #endif
74 #define GPIO_WAKE_SOURCE_IDLE_ID (GPIO_NUM) //
75 typedef struct
76 {
77 gpio_id_t id;
78 gpio_int_type_t int_type;
79 //gpio_isr_t isr;
80 }gpio_dynamic_wakeup_t;
81 static gpio_dynamic_wakeup_t s_gpio_dynamic_wakeup_source_map[CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT];
82 static void gpio_dynamic_wakeup_source_init(void);
83 static void bk_gpio_set_wakeup_gpio_id(gpio_id_t gpio_id);
84 static bool bk_gpio_get_aon_pmu_deepsleep_flag();
85 #endif
86 #endif
87
88 static void gpio_isr(void);
89
bk_gpio_driver_init(void)90 bk_err_t bk_gpio_driver_init(void)
91 {
92 //avoid re-init caused some info lost
93 if(s_gpio_is_init)
94 {
95 GPIO_LOGI("%s:has inited \r\n", __func__);
96 return BK_OK;
97 }
98
99 os_memset(&s_gpio, 0, sizeof(s_gpio));
100
101 gpio_hal_disable_jtag_mode(&s_gpio.hal);
102
103 gpio_hal_init(&s_gpio.hal);
104
105 #ifdef CONFIG_GPIO_DYNAMIC_WAKEUP_SUPPORT
106 gpio_dynamic_wakeup_source_init();
107 #endif
108
109 amp_res_init(AMP_RES_ID_GPIO);
110
111 //Move ISR to last to avoid other resouce doesn't finish but isr has came.
112 //F.E:GPIO wakeup deepsleep.
113 bk_int_isr_register(INT_SRC_GPIO, gpio_isr, NULL);
114 //interrupt to CPU enable
115 #if (CONFIG_SYSTEM_CTRL)
116 sys_drv_int_group2_enable(GPIO_INTERRUPT_CTRL_BIT);
117 #else
118 icu_enable_gpio_interrupt();
119 #endif
120
121 s_gpio_is_init = true;
122 return BK_OK;
123 }
124
bk_gpio_driver_deinit(void)125 bk_err_t bk_gpio_driver_deinit(void)
126 {
127 if(!s_gpio_is_init)
128 {
129 GPIO_LOGI("%s:isn't init \r\n", __func__);
130 return BK_OK;
131 }
132
133 //interrupt to CPU disable
134 #if (CONFIG_SYSTEM_CTRL)
135 sys_drv_int_group2_disable(GPIO_INTERRUPT_CTRL_BIT);
136 #else
137 icu_disable_gpio_interrupt();
138 #endif
139
140 s_gpio_is_init = false;
141
142 return BK_OK;
143 }
144
145
bk_gpio_enable_output(gpio_id_t gpio_id)146 bk_err_t bk_gpio_enable_output(gpio_id_t gpio_id)
147 {
148 GPIO_RETURN_ON_INVALID_ID(gpio_id);
149
150 return gpio_hal_output_enable(&s_gpio.hal, gpio_id, 1);
151 }
152
bk_gpio_disable_output(gpio_id_t gpio_id)153 bk_err_t bk_gpio_disable_output(gpio_id_t gpio_id)
154 {
155 GPIO_RETURN_ON_INVALID_ID(gpio_id);
156
157 return gpio_hal_output_enable(&s_gpio.hal, gpio_id, 0);
158 }
159
bk_gpio_enable_input(gpio_id_t gpio_id)160 bk_err_t bk_gpio_enable_input(gpio_id_t gpio_id)
161 {
162 GPIO_RETURN_ON_INVALID_ID(gpio_id);
163
164 return gpio_hal_input_enable(&s_gpio.hal, gpio_id, 1);
165 }
166
bk_gpio_disable_input(gpio_id_t gpio_id)167 bk_err_t bk_gpio_disable_input(gpio_id_t gpio_id)
168 {
169 GPIO_RETURN_ON_INVALID_ID(gpio_id);
170
171 return gpio_hal_input_enable(&s_gpio.hal, gpio_id, 0);
172 }
173
bk_gpio_enable_pull(gpio_id_t gpio_id)174 bk_err_t bk_gpio_enable_pull(gpio_id_t gpio_id )
175 {
176 GPIO_RETURN_ON_INVALID_ID(gpio_id);
177
178 return gpio_hal_pull_enable(&s_gpio.hal, gpio_id, 1);
179 }
180
bk_gpio_disable_pull(gpio_id_t gpio_id)181 bk_err_t bk_gpio_disable_pull(gpio_id_t gpio_id )
182 {
183 GPIO_RETURN_ON_INVALID_ID(gpio_id);
184
185 return gpio_hal_pull_enable(&s_gpio.hal, gpio_id, 0);
186 }
187
bk_gpio_pull_up(gpio_id_t gpio_id)188 bk_err_t bk_gpio_pull_up(gpio_id_t gpio_id)
189 {
190 GPIO_RETURN_ON_INVALID_ID(gpio_id);
191
192 gpio_hal_pull_enable(&s_gpio.hal, gpio_id, 1);
193 return gpio_hal_pull_up_enable(&s_gpio.hal, gpio_id, 1);
194 }
195
bk_gpio_pull_down(gpio_id_t gpio_id)196 bk_err_t bk_gpio_pull_down(gpio_id_t gpio_id)
197 {
198 GPIO_RETURN_ON_INVALID_ID(gpio_id);
199
200 gpio_hal_pull_enable(&s_gpio.hal, gpio_id, 1);
201 return gpio_hal_pull_up_enable(&s_gpio.hal, gpio_id, 0);
202 }
203
204
205
bk_gpio_set_output_high(gpio_id_t gpio_id)206 bk_err_t bk_gpio_set_output_high(gpio_id_t gpio_id)
207 {
208 GPIO_RETURN_ON_INVALID_ID(gpio_id);
209
210 return gpio_hal_set_output_value(&s_gpio.hal, gpio_id, 1);
211 }
212
bk_gpio_set_output_low(gpio_id_t gpio_id)213 bk_err_t bk_gpio_set_output_low(gpio_id_t gpio_id)
214 {
215 GPIO_RETURN_ON_INVALID_ID(gpio_id);
216
217 return gpio_hal_set_output_value(&s_gpio.hal, gpio_id, 0);
218 }
219
bk_gpio_get_input(gpio_id_t gpio_id)220 bool bk_gpio_get_input(gpio_id_t gpio_id)
221 {
222 GPIO_RETURN_ON_INVALID_ID(gpio_id);
223
224 return gpio_hal_get_input(&s_gpio.hal, gpio_id);
225 }
226
227 //MAX capactiy:3
bk_gpio_set_capacity(gpio_id_t gpio_id,uint32 capacity)228 bool bk_gpio_set_capacity(gpio_id_t gpio_id, uint32 capacity)
229 {
230 GPIO_RETURN_ON_INVALID_ID(gpio_id);
231
232 return gpio_hal_set_capacity(&s_gpio.hal, gpio_id, capacity);
233 }
234
bk_gpio_set_config(gpio_id_t gpio_id,const gpio_config_t * config)235 bk_err_t bk_gpio_set_config(gpio_id_t gpio_id, const gpio_config_t *config)
236 {
237 GPIO_RETURN_ON_INVALID_ID(gpio_id);
238 GPIO_RETURN_ON_INVALID_IO_MODE(config->io_mode);
239 GPIO_RETURN_ON_INVALID_PULL_MODE(config->pull_mode);
240
241 return gpio_hal_set_config(&s_gpio.hal, gpio_id, config);
242 }
243
244
245 /* Enable GPIO interrupt.
246 */
bk_gpio_register_isr(gpio_id_t gpio_id,gpio_isr_t isr)247 bk_err_t bk_gpio_register_isr(gpio_id_t gpio_id, gpio_isr_t isr)
248 {
249 GPIO_RETURN_ON_INVALID_ID(gpio_id);
250 s_gpio_isr[gpio_id] = isr;
251
252 return BK_OK;
253 }
254
255 //This function just enable the select GPIO can report IRQ to CPU
bk_gpio_enable_interrupt(gpio_id_t gpio_id)256 bk_err_t bk_gpio_enable_interrupt(gpio_id_t gpio_id)
257 {
258 GPIO_RETURN_ON_INVALID_ID(gpio_id);
259
260 return gpio_hal_enable_interrupt(&s_gpio.hal, gpio_id);
261 }
262
bk_gpio_disable_interrupt(gpio_id_t gpio_id)263 bk_err_t bk_gpio_disable_interrupt(gpio_id_t gpio_id)
264 {
265 GPIO_RETURN_ON_INVALID_ID(gpio_id);
266
267 //WARNING:We can't call icu_enable_gpio_interrupt/sys_drv_int_group2_disable in this function
268 //If more then one GPIO_ID enable interrupt, here disable the IRQ to CPU, it caused other GPIO ID can't work
269
270 gpio_hal_disable_interrupt(&s_gpio.hal, gpio_id);
271
272 return BK_OK;
273 }
274
bk_gpio_clear_interrupt(gpio_id_t gpio_id)275 bk_err_t bk_gpio_clear_interrupt(gpio_id_t gpio_id)
276 {
277 GPIO_RETURN_ON_INVALID_ID(gpio_id);
278
279 //WARNING:We can't call icu_enable_gpio_interrupt/sys_drv_int_group2_disable in this function
280 //If more then one GPIO_ID enable interrupt, here disable the IRQ to CPU, it caused other GPIO ID can't work
281
282 gpio_hal_clear_chan_interrupt_status(&s_gpio.hal, gpio_id);
283
284 return BK_OK;
285 }
bk_gpio_set_interrupt_type(gpio_id_t gpio_id,gpio_int_type_t type)286 bk_err_t bk_gpio_set_interrupt_type(gpio_id_t gpio_id, gpio_int_type_t type)
287 {
288 GPIO_RETURN_ON_INVALID_ID(gpio_id);
289 GPIO_RETURN_ON_INVALID_INT_TYPE_MODE(type);
290
291 return gpio_hal_set_int_type(&s_gpio.hal, gpio_id, type);
292 }
293
294
gpio_isr(void)295 static void gpio_isr(void)
296 {
297 gpio_hal_t *hal = &s_gpio.hal;
298 gpio_interrupt_status_t gpio_status;
299 int gpio_id;
300
301 gpio_hal_get_interrupt_status(hal, &gpio_status);
302
303 for (gpio_id = 0; gpio_id < GPIO_NUM; gpio_id++) {
304 if (gpio_hal_is_interrupt_triggered(hal, gpio_id, &gpio_status)) {
305 #if CONFIG_GPIO_WAKEUP_SUPPORT
306 /* Get the ID of the first interrupt wake up,
307 * which is not necessarily the registered ID.
308 */
309 if(bk_gpio_get_aon_pmu_deepsleep_flag())
310 bk_gpio_set_wakeup_gpio_id(gpio_id);
311
312 /* if many gpio wakeup at the same time, it will called many times */
313 if(s_gpio_is_setted_wake_status & ((uint64_t)0x1 << gpio_id))
314 {
315 gpio_wakeup_default_isr(gpio_id);
316 }
317 #endif
318 if (s_gpio_isr[gpio_id]) {
319 GPIO_LOGD("gpio int: index:%d \r\n",gpio_id);
320 s_gpio_isr[gpio_id](gpio_id);
321 }
322 }
323 }
324
325 //move it after callback:if isr is caused by level type,
326 //clear IRQ status and doesn't disable IRQ, then it causes a new ISR
327 gpio_hal_clear_interrupt_status(hal, &gpio_status);
328
329 }
330
331 #if CONFIG_GPIO_WAKEUP_SUPPORT
332
gpio_dump_baked_regs(bool configs,bool int_type_status,bool int_en_status)333 static void gpio_dump_baked_regs(bool configs, bool int_type_status, bool int_en_status)
334 {
335 #if CONFIG_GPIO_WAKEUP_DEBUG
336 gpio_id_t gpio_id = 0;
337
338 GPIO_LOGD("%s[+]\r\n", __func__);
339
340 GPIO_LOGD("is_setted_wake_status h= 0x%x, l=0x%x\r\n", (uint32_t)(s_gpio_is_setted_wake_status>>32), (uint32_t)s_gpio_is_setted_wake_status);
341
342 if(configs)
343 {
344 for(gpio_id = 0; gpio_id < GPIO_NUM; gpio_id++)
345 {
346 GPIO_LOGD("s_gpio_bak_regs[%d]=0x%x\r\n", gpio_id, s_gpio_bak_regs[gpio_id]);
347 }
348 }
349
350 if(int_type_status)
351 {
352 for(gpio_id = 0; gpio_id < sizeof(s_gpio_bak_int_type_regs)/sizeof(s_gpio_bak_int_type_regs[0]); gpio_id++)
353 {
354 GPIO_LOGD("int_type_regs[%d]=0x%x\r\n", gpio_id, s_gpio_bak_int_type_regs[gpio_id]);
355 }
356 }
357
358 if(int_en_status)
359 {
360 for(gpio_id = 0; gpio_id < sizeof(s_gpio_bak_int_enable_regs)/sizeof(s_gpio_bak_int_enable_regs[0]); gpio_id++)
361 {
362 GPIO_LOGD("int_enable_regs[%d]=0x%x\r\n", gpio_id, s_gpio_bak_int_enable_regs[gpio_id]);
363 }
364 }
365
366 GPIO_LOGD("%s[-]\r\n", __func__);
367 #endif
368 }
369
gpio_dump_regs(bool configs,bool int_status)370 static void gpio_dump_regs(bool configs, bool int_status)
371 {
372 #if CONFIG_GPIO_WAKEUP_DEBUG
373 gpio_id_t gpio_id = 0;
374
375 GPIO_LOGD("%s[+]\r\n", __func__);
376
377 if(configs)
378 {
379 for(gpio_id = 0; gpio_id < GPIO_NUM; gpio_id++)
380 {
381 ///gpio_struct_dump(gpio_id);
382 GPIO_LOGD("gpio[%d]=0x%x\r\n", gpio_id, *(volatile uint32_t*)(GPIO_LL_REG_BASE + 4*gpio_id));
383 }
384 }
385
386 //WARNING:BK7256 has this 9 regs, maybe other project doesn't has this 9 REGs
387 if(int_status)
388 {
389 for(gpio_id = 0; gpio_id < 9; gpio_id++)
390 {
391 ///gpio_struct_dump(gpio_id);
392 GPIO_LOGD("REG0x%x=0x%x\r\n", (GPIO_LL_REG_BASE + 4*(0x40+gpio_id)), *(volatile uint32_t*)(GPIO_LL_REG_BASE + 4*(0x40+gpio_id)));
393 }
394 }
395 GPIO_LOGD("%s[-]\r\n", __func__);
396 #endif
397 }
398
gpio_get_interrupt_status(uint32_t * h_status,uint32_t * l_status)399 void gpio_get_interrupt_status(uint32_t *h_status, uint32_t *l_status)
400 {
401 gpio_hal_t *hal = &s_gpio.hal;
402 gpio_interrupt_status_t gpio_status;
403
404 gpio_hal_get_interrupt_status(hal, &gpio_status);
405 if(h_status)
406 *h_status = gpio_status.gpio_32_64_int_status;
407 if(l_status)
408 *l_status = gpio_status.gpio_0_31_int_status;
409 }
410
gpio_wakeup_default_isr(gpio_id_t gpio_id)411 static void gpio_wakeup_default_isr(gpio_id_t gpio_id)
412 {
413 GPIO_LOGD("gpio int: index:%d \r\n", gpio_id);
414 }
415
416 /* Added fault tolerance for GPIO wakeup.
417 * The act of increasing the pull-down voltage to prevent jitter interference.
418 */
gpio_wakeup_set_pin_voltage_status(gpio_id_t gpio_id,gpio_int_type_t type)419 static void gpio_wakeup_set_pin_voltage_status(gpio_id_t gpio_id, gpio_int_type_t type)
420 {
421 GPIO_LOGD("%s[+]\r\n", __func__);
422
423 switch(type)
424 {
425 case GPIO_INT_TYPE_LOW_LEVEL:
426 bk_gpio_pull_up(gpio_id);
427 GPIO_LOGD("%s GPIO_INT_TYPE: LOW_LEVEL Pull_up!\r\n", __func__);
428 break;
429 case GPIO_INT_TYPE_HIGH_LEVEL:
430 bk_gpio_pull_down(gpio_id);
431 GPIO_LOGD("%s GPIO_INT_TYPE: HIGH_LEVEL Pull_down!\r\n", __func__);
432 break;
433 case GPIO_INT_TYPE_RISING_EDGE:
434 bk_gpio_pull_down(gpio_id);
435 GPIO_LOGD("%s GPIO_INT_TYPE: RISING_EDGE Pull_down!\r\n", __func__);
436 break;
437 case GPIO_INT_TYPE_FALLING_EDGE:
438 bk_gpio_pull_up(gpio_id);
439 GPIO_LOGD("%s GPIO_INT_TYPE: FALLING_EDGE Pull_up!\r\n", __func__);
440 break;
441 case GPIO_INT_TYPE_MAX:
442 GPIO_LOGI("%s Please set fill in the mode correctly!\r\n", __func__);
443 break;
444 default:
445 break;
446 }
447
448 GPIO_LOGD("%s[-]\r\n", __func__);
449 }
450
gpio_config_wakeup_function(void)451 static void gpio_config_wakeup_function(void)
452 {
453 uint32_t i = 0;
454 gpio_wakeup_t gpio_wakeup_map[] = GPIO_STATIC_WAKEUP_SOURCE_MAP;
455
456 GPIO_LOGD("%s[+]\r\n", __func__);
457
458 s_gpio_is_setted_wake_status = 0;
459 for(i = 0; i < sizeof(gpio_wakeup_map)/sizeof(gpio_wakeup_t); i++)
460 {
461 gpio_wakeup_set_pin_voltage_status(gpio_wakeup_map[i].id, gpio_wakeup_map[i].int_type);
462 bk_gpio_set_interrupt_type(gpio_wakeup_map[i].id, gpio_wakeup_map[i].int_type);
463 bk_gpio_enable_interrupt(gpio_wakeup_map[i].id);
464 s_gpio_is_setted_wake_status |= ((uint64_t)1 << gpio_wakeup_map[i].id);
465 }
466
467 #ifdef CONFIG_GPIO_DYNAMIC_WAKEUP_SUPPORT
468 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
469 {
470 if(s_gpio_dynamic_wakeup_source_map[i].id != GPIO_WAKE_SOURCE_IDLE_ID) {
471 gpio_wakeup_set_pin_voltage_status(s_gpio_dynamic_wakeup_source_map[i].id, s_gpio_dynamic_wakeup_source_map[i].int_type);
472 bk_gpio_set_interrupt_type(s_gpio_dynamic_wakeup_source_map[i].id, s_gpio_dynamic_wakeup_source_map[i].int_type);
473 bk_gpio_enable_interrupt(s_gpio_dynamic_wakeup_source_map[i].id);
474 s_gpio_is_setted_wake_status |= ((uint64_t)1 << s_gpio_dynamic_wakeup_source_map[i].id);
475 }
476 }
477 #endif
478
479 GPIO_LOGD("%s[-]set wake src h=0x%0x, l=0x%0x\r\n", __func__, (uint32_t)(s_gpio_is_setted_wake_status>>32), (uint32_t)s_gpio_is_setted_wake_status) ;
480 }
481
gpio_config_low_power_wakeup_pin(void)482 static void gpio_config_low_power_wakeup_pin(void)
483 {
484 uint32_t i = 0;
485
486 gpio_wakeup_t gpio_wakeup_map[] = GPIO_STATIC_WAKEUP_SOURCE_MAP;
487 for(i = 0; i < sizeof(gpio_wakeup_map)/sizeof(gpio_wakeup_t); i++)
488 {
489 bk_gpio_disable_output(gpio_wakeup_map[i].id);
490 bk_gpio_enable_input(gpio_wakeup_map[i].id);
491 }
492
493 #ifdef CONFIG_GPIO_DYNAMIC_WAKEUP_SUPPORT
494 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
495 {
496 if(s_gpio_dynamic_wakeup_source_map[i].id != GPIO_WAKE_SOURCE_IDLE_ID) {
497 bk_gpio_disable_output(s_gpio_dynamic_wakeup_source_map[i].id);
498 bk_gpio_enable_input(s_gpio_dynamic_wakeup_source_map[i].id);
499 }
500 }
501 #endif
502 }
503
gpio_clear_wakeup_function(void)504 static void gpio_clear_wakeup_function(void)
505 {
506 s_gpio_is_setted_wake_status = 0;
507 }
508
509 #ifdef CONFIG_GPIO_DYNAMIC_WAKEUP_SUPPORT
510
bk_gpio_get_wakeup_gpio_id()511 gpio_id_t bk_gpio_get_wakeup_gpio_id()
512 {
513 GPIO_LOGD("GET wakeup gpio_id: %d \r\n", s_gpio_wakeup_gpio_id);
514 return s_gpio_wakeup_gpio_id;
515 }
516
bk_gpio_set_wakeup_gpio_id(gpio_id_t gpio_id)517 static void bk_gpio_set_wakeup_gpio_id(gpio_id_t gpio_id)
518 {
519 /* Obatain the First wake source GPIO ID*/
520 if (s_gpio_wakeup_gpio_id == GPIO_NUM) {
521 s_gpio_wakeup_gpio_id = gpio_id;
522 bk_gpio_disable_interrupt(gpio_id);
523 }
524 GPIO_LOGD("SET wakeup gpio_id: %d \r\n", s_gpio_wakeup_gpio_id);
525 }
526
bk_gpio_get_aon_pmu_deepsleep_flag()527 static bool bk_gpio_get_aon_pmu_deepsleep_flag()
528 {
529 #if CONFIG_AON_PMU
530 return (aon_pmu_drv_reg_get(PMU_REG2) & BIT(BIT_SLEEP_FLAG_DEEP_SLEEP));
531 #endif
532 return false;
533 }
534
gpio_dynamic_wakeup_source_init(void)535 static void gpio_dynamic_wakeup_source_init(void)
536 {
537 uint32_t i = 0;
538
539 GPIO_LOGD("%s[+]gpio wakecnt=%d\r\n", __func__, CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT);
540 //search the same id and replace it.
541 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
542 {
543 s_gpio_dynamic_wakeup_source_map[i].id = GPIO_WAKE_SOURCE_IDLE_ID;
544 }
545
546 GPIO_LOGD("%s[-]\r\n", __func__);
547 }
548
bk_gpio_register_wakeup_source(gpio_id_t gpio_id,gpio_int_type_t int_type)549 bk_err_t bk_gpio_register_wakeup_source(gpio_id_t gpio_id,
550 gpio_int_type_t int_type)
551 {
552 uint32_t i = 0;
553
554 GPIO_RETURN_ON_INVALID_ID(gpio_id);
555 GPIO_RETURN_ON_INVALID_INT_TYPE_MODE(int_type);
556
557 //search the same id and replace it.
558 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
559 {
560 if(s_gpio_dynamic_wakeup_source_map[i].id == gpio_id)
561 {
562 s_gpio_dynamic_wakeup_source_map[i].int_type = int_type;
563 //s_gpio_dynamic_wakeup_source_map[i].isr = isr;
564
565 GPIO_LOGD("gpio=%d,int_type=%d replace previous wake src\r\n", gpio_id, int_type);
566 return BK_OK;
567 }
568 }
569
570 //serach the first idle id
571 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
572 {
573 if(s_gpio_dynamic_wakeup_source_map[i].id == GPIO_WAKE_SOURCE_IDLE_ID)
574 {
575 s_gpio_dynamic_wakeup_source_map[i].id = gpio_id;
576 s_gpio_dynamic_wakeup_source_map[i].int_type = int_type;
577 //s_gpio_dynamic_wakeup_source_map[i].isr = isr;
578 s_gpio_is_setted_wake_status |= ((uint64_t)1 << s_gpio_dynamic_wakeup_source_map[i].id);
579
580 GPIO_LOGD("gpio=%d,int_type=%d register wake src\r\n", gpio_id, int_type);
581
582 return BK_OK;
583 }
584 }
585
586 GPIO_LOGE("too much(%d) GPIO is setted wake src\r\n", CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT);
587 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
588 {
589 GPIO_LOGE("gpio id:%d is using \r\n", s_gpio_dynamic_wakeup_source_map[i].id);
590 }
591 return BK_FAIL;
592 }
593
bk_gpio_unregister_wakeup_source(gpio_id_t gpio_id)594 bk_err_t bk_gpio_unregister_wakeup_source(gpio_id_t gpio_id)
595 {
596 uint32_t i = 0;
597
598 GPIO_RETURN_ON_INVALID_ID(gpio_id);
599
600 /* search the same id and replace it.*/
601 for(i = 0; i < CONFIG_GPIO_DYNAMIC_WAKEUP_SOURCE_MAX_CNT; i++)
602 {
603 if(s_gpio_dynamic_wakeup_source_map[i].id == gpio_id)
604 {
605 s_gpio_dynamic_wakeup_source_map[i].id = GPIO_WAKE_SOURCE_IDLE_ID;
606 s_gpio_dynamic_wakeup_source_map[i].int_type = GPIO_INT_TYPE_MAX;
607 //s_gpio_dynamic_wakeup_source_map[i].isr = NULL;
608 s_gpio_is_setted_wake_status &= ~(((uint64_t)1 << s_gpio_dynamic_wakeup_source_map[i].id));
609
610 /* Clear the hardware status during deregister */
611 bk_gpio_disable_input(gpio_id);
612 bk_gpio_disable_interrupt(gpio_id);
613
614 GPIO_LOGD("%s[-]gpioid=%d\r\n", __func__, gpio_id);
615
616 return BK_OK;
617 }
618 }
619
620 GPIO_LOGE("gpio id:%d is not using \r\n", gpio_id);
621 return BK_FAIL;
622 }
623
624 #endif
625
gpio_enter_low_power(void * param)626 bk_err_t gpio_enter_low_power(void *param)
627 {
628 GPIO_LOGD("%s[+]\r\n", __func__);
629
630 gpio_dump_regs(true, true);
631
632 gpio_hal_bak_configs(&s_gpio_bak_regs[0], GPIO_NUM_MAX);
633 gpio_dump_baked_regs(true, false, false);
634 gpio_hal_bak_int_type_configs(&s_gpio_bak_int_type_regs[0], sizeof(s_gpio_bak_int_type_regs)/sizeof(s_gpio_bak_int_type_regs[0]));
635 gpio_hal_bak_int_enable_configs(&s_gpio_bak_int_enable_regs[0], sizeof(s_gpio_bak_int_enable_regs)/sizeof(s_gpio_bak_int_enable_regs[0]));
636
637 gpio_dump_baked_regs(false, true, true);
638
639 #if 1 //TODO:
640 if((uint32_t)param != 0x534b4950) //just debug:magic value == "SKIP"
641 {
642 GPIO_LOGD("switch to low power tatus\r\n");
643 gpio_hal_switch_to_low_power_status();
644 gpio_config_low_power_wakeup_pin();
645 GPIO_LOGD("exit switch to low power tatus\r\n");
646 gpio_dump_regs(true, false);
647 }
648 #endif
649
650 /*
651 * !!! NOTES NOTES !!!
652 * ASIC switch PIN function to GPIO Input mode,
653 * it takes 3 cycles(GPIO uses 32K clock) to be stable.
654 * If in the 3 cycles enable INPUT level/edge check, it will report an error status.
655 * so enable gpio input irq, should wait enough time.
656 */
657 delay_us(125); //125 == ((3+1)/32) * 1000 us
658
659 gpio_config_wakeup_function();
660 gpio_dump_regs(false, true);
661
662 GPIO_LOGD("%s[-]\r\n", __func__);
663
664 return BK_OK;
665 }
666
gpio_exit_low_power(void * param)667 bk_err_t gpio_exit_low_power(void *param)
668 {
669 gpio_hal_t *hal = &s_gpio.hal;
670 gpio_interrupt_status_t gpio_status;
671
672 GPIO_LOGD("%s[+]\r\n", __func__);
673
674 gpio_dump_regs(true, true);
675 gpio_dump_baked_regs(true, true, true);
676
677 gpio_hal_get_interrupt_status(hal, &gpio_status);
678
679 GPIO_LOGD("wakeup isn't by gpio\r\n");
680 GPIO_LOGD("%s[+]\r\n", __func__);
681
682 //wakeup not by gpio, should clear wakeup function,then GPIO wake ISR will not called.
683 if((gpio_status.gpio_0_31_int_status == 0) && (gpio_status.gpio_32_64_int_status == 0))
684 {
685 GPIO_LOGD("wakeup isn't by gpio\r\n");
686 gpio_clear_wakeup_function();
687 }
688
689 #if 1 //TODO:
690 if((uint32_t)param != 0x534b4950) //just debug:magic value == "SKIP"
691 {
692 gpio_hal_restore_configs(&s_gpio_bak_regs[0], GPIO_NUM_MAX);
693 gpio_hal_restore_int_type_configs(&s_gpio_bak_int_type_regs[0], sizeof(s_gpio_bak_int_type_regs)/sizeof(s_gpio_bak_int_type_regs[0]));
694 gpio_hal_restore_int_enable_configs(&s_gpio_bak_int_enable_regs[0], sizeof(s_gpio_bak_int_enable_regs)/sizeof(s_gpio_bak_int_enable_regs[0]));
695 }
696 #endif
697
698 gpio_dump_regs(true, true);
699 gpio_dump_baked_regs(true, true, true);
700
701 GPIO_LOGD("%s[-]\r\n", __func__);
702
703 return BK_OK;
704 }
705
706 #else
bk_gpio_reg_save(uint32_t * gpio_cfg)707 bk_err_t bk_gpio_reg_save(uint32_t* gpio_cfg)
708 {
709 return gpio_hal_reg_save(gpio_cfg);
710 }
711
bk_gpio_reg_restore(uint32_t * gpio_cfg)712 bk_err_t bk_gpio_reg_restore(uint32_t* gpio_cfg)
713 {
714 return gpio_hal_reg_restore(gpio_cfg);
715 }
716
bk_gpio_wakeup_enable(int64_t index,uint64_t type_l,uint64_t type_h)717 bk_err_t bk_gpio_wakeup_enable(int64_t index, uint64_t type_l, uint64_t type_h)
718 {
719 return gpio_hal_wakeup_enable( index, type_l, type_h);
720 }
721
bk_gpio_wakeup_interrupt_clear()722 bk_err_t bk_gpio_wakeup_interrupt_clear()
723 {
724 return gpio_hal_wakeup_interrupt_clear();
725 }
726 #endif
727
728 #if CONFIG_GPIO_SIMULATE_UART_WRITE
729 /**
730 * @brief Uses specifies GPIO to simulate UART write data
731 *
732 * This API Uses specifies GPIO to simulate UART write data:
733 * - Uses CPU poll wait to do delay, so it blocks CPU.
734 * - The caller should confirm the specifies GPIO is not used by other APP.
735 *
736 * @param *buff Which buffers will be write with GPIO.
737 * @param len How many bytes data will be wrote.
738 * @param gpio_id Which GPIO will be simulated as UART write data.
739 * @param div Baud rate == 1Mbps/(1+div)
740 *
741 * @attention 1. As this function just simulate uart write, it blocks the CPU,
742 * so please don't write too much data.
743 *
744 * @return
745 */
gpio_simulate_uart_write(unsigned char * buff,uint32_t len,gpio_id_t gpio_id,uint32_t div)746 void gpio_simulate_uart_write(unsigned char *buff, uint32_t len, gpio_id_t gpio_id, uint32_t div)
747 {
748 volatile unsigned char c, n;
749 UINT32 param;
750 uint32_t div_cnt = div+1;
751
752 BK_LOG_ON_ERR(bk_gpio_disable_input(gpio_id));
753 BK_LOG_ON_ERR(bk_gpio_enable_output(gpio_id));
754
755 bk_gpio_set_output_high(gpio_id);
756 delay_us(div_cnt);
757
758 while (len--) {
759 //in while loop, to avoid disable IRQ too much time, release it if finish one byte.
760 GLOBAL_INT_DECLARATION();
761 GLOBAL_INT_DISABLE();
762
763 //UART start bit
764 bk_gpio_set_output_low(gpio_id);
765 delay_us(div_cnt);
766
767 //char value
768 c = *buff++;
769 n = 8;
770 while (n--) {
771 param = c & 0x01;
772 if (param) {
773 bk_gpio_set_output_high(gpio_id);
774 } else {
775 bk_gpio_set_output_low(gpio_id);
776 }
777
778 delay_us(div_cnt);
779 c >>= 1;
780 }
781
782 //UART stop bit
783 bk_gpio_set_output_high(gpio_id);
784 delay_us(div_cnt);
785
786 GLOBAL_INT_RESTORE();
787 }
788 }
789 #endif
790
791