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