1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 * Description: Provides V150 HAL GPIO common code. \n
16 *
17 * History: \n
18 * 2023-06-01, Create file. \n
19 */
20 #include <stdint.h>
21 #include "common_def.h"
22 #include "soc_osal.h"
23 #include "hal_gpio.h"
24 #include "hal_gpio_v150_regs_op.h"
25 #include "hal_gpio_v150_comm.h"
26
27 /* GPIO 回调表, 注册每根GPIO管脚的中断回调, 通过 gpio_group_info_t 结构中的 start_callback_id 字段进行查询访问; */
28 static gpio_callback_t g_hal_gpio_callback_list[GPIO_PIN_NUM] = {NULL};
29
hal_gpio_v150_callback_list_get(void)30 gpio_callback_t *hal_gpio_v150_callback_list_get(void)
31 {
32 return g_hal_gpio_callback_list;
33 }
34
hal_gpio_v150_irq_handler(int irq_num,const void * tmp)35 STATIC int hal_gpio_v150_irq_handler(int irq_num, const void *tmp)
36 {
37 unused(tmp);
38
39 uint32_t channel, group, group_pin, intr_state;
40 hal_gpio_channel_info_t *channel_info;
41 hal_gpio_group_context_t *group_context;
42
43 // 清除中断
44 osal_irq_clear((uint32_t)irq_num);
45
46 // 根据中断号匹配channel
47 for (channel = GPIO_CHANNEL_0; channel < GPIO_CHANNEL_MAX_NUM; channel++) {
48 channel_info = gpio_porting_channel_info_get(channel);
49 if (channel_info->irq_num == (uint32_t)irq_num) {
50 break;
51 }
52 }
53
54 if (channel >= GPIO_CHANNEL_MAX_NUM) {
55 // 异常场景, 未找到对应的GPIO_CHANNEL
56 return 0;
57 }
58
59 for (group = 0; group < channel_info->group_num; group++) {
60 group_context = gpio_porting_group_context_get(channel, group);
61 if (group_context->cb_registered == 0) {
62 // 本组无已注册回调的GPIO, 跳过
63 hal_gpio_gpio_int_eoi_clr_all(channel, group);
64 continue;
65 }
66
67 // 记录该寄存器值并清除该组中断值
68 intr_state = hal_gpio_gpio_intr_get_data(channel, group);
69 hal_gpio_gpio_int_eoi_clr_all(channel, group);
70
71 // 遍历本组寄存器的中断状态
72 for (group_pin = 0; group_pin < channel_info->group_list[group].pin_num; group_pin++) {
73 if (intr_state == 0) {
74 break;
75 }
76 if ((intr_state & 0x1) != 0) {
77 // 调用回调
78 hal_gpio_v150_callback_get(channel, group, group_pin)(
79 (pin_t)hal_gpio_v150_pin_id_get(channel, group, group_pin), 0);
80 }
81 intr_state >>= 1;
82 }
83 }
84
85 return 0;
86 }
87
hal_gpio_v150_register_irq(uint32_t int_id)88 void hal_gpio_v150_register_irq(uint32_t int_id)
89 {
90 osal_irq_request(int_id, (osal_irq_handler)hal_gpio_v150_irq_handler, NULL, NULL, NULL);
91 }
92
hal_gpio_v150_unregister_irq(uint32_t int_id)93 void hal_gpio_v150_unregister_irq(uint32_t int_id)
94 {
95 osal_irq_free(int_id, NULL);
96 }
97
hal_gpio_v150_pin_info_get(pin_t pin,uint32_t * channel,uint32_t * group,uint32_t * group_pin)98 errcode_t hal_gpio_v150_pin_info_get(pin_t pin, uint32_t *channel, uint32_t *group, uint32_t *group_pin)
99 {
100 uint32_t channel_id, group_id;
101 uint32_t pin_id = (uint32_t)pin;
102 hal_gpio_channel_info_t *channel_info = NULL;
103 hal_gpio_group_info_t *group_info = NULL;
104
105 for (channel_id = GPIO_CHANNEL_0; channel_id < GPIO_CHANNEL_MAX_NUM; channel_id++) {
106 channel_info = gpio_porting_channel_info_get(channel_id);
107 if (pin_id >= channel_info->start_pin_id && pin_id < channel_info->start_pin_id + channel_info->pin_num) {
108 break;
109 }
110 }
111 if (channel_id >= GPIO_CHANNEL_MAX_NUM) {
112 return ERRCODE_INVALID_PARAM;
113 }
114
115 for (group_id = 0; group_id < channel_info->group_num; group_id++) {
116 group_info = hal_gpio_v150_group_info_get(channel_id, group_id);
117 if (pin_id >= group_info->start_pin_id && pin_id <= group_info->start_pin_id + group_info->pin_num) {
118 break;
119 }
120 }
121 if (group_id >= channel_info->group_num) {
122 return ERRCODE_INVALID_PARAM;
123 }
124
125 *channel = channel_id;
126 *group = group_id;
127 *group_pin = pin_id - group_info->start_pin_id;
128
129 return ERRCODE_SUCC;
130 }
131
hal_gpio_v150_pin_id_get(uint32_t channel,uint32_t group,uint32_t group_pin)132 uint32_t hal_gpio_v150_pin_id_get(uint32_t channel, uint32_t group, uint32_t group_pin)
133 {
134 return hal_gpio_v150_group_info_get(channel, group)->start_pin_id + group_pin;
135 }
136
hal_gpio_v150_register_cb(uint32_t channel,uint32_t group,uint32_t group_pin,gpio_callback_t cb)137 errcode_t hal_gpio_v150_register_cb(uint32_t channel, uint32_t group, uint32_t group_pin, gpio_callback_t cb)
138 {
139 if (hal_gpio_v150_callback_get(channel, group, group_pin) != NULL ||
140 (hal_gpio_v150_callback_registered_get(channel, group) & bit(group_pin)) != 0) {
141 return ERRCODE_GPIO_ALREADY_SET_CALLBACK;
142 }
143
144 hal_gpio_v150_callback_set(channel, group, group_pin, cb);
145 hal_gpio_v150_callback_registered_set_true(channel, group, group_pin);
146 return ERRCODE_SUCC;
147 }
148
hal_gpio_v150_unregister_cb(uint32_t channel,uint32_t group,uint32_t group_pin)149 void hal_gpio_v150_unregister_cb(uint32_t channel, uint32_t group, uint32_t group_pin)
150 {
151 hal_gpio_v150_callback_registered_set_false(channel, group, group_pin);
152 hal_gpio_v150_callback_set(channel, group, group_pin, NULL);
153 }