• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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