1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /******************************************************************************
20 * @file dw_gpio.c
21 * @brief
22 * @version
23 * @date 2020-01-08
24 ******************************************************************************/
25
26 #include <string.h>
27
28 #include <csi_config.h>
29 #include <drv/gpio.h>
30 #include <drv/irq.h>
31 #include <drv/pin.h>
32
33 extern csi_error_t csi_pin_mode(pin_name_t pin_name, csi_gpio_mode_t mode);
34
dw_gpio_irqhandler(void * args)35 static void dw_gpio_irqhandler(void *args)
36 {
37
38 ///< TODO:获取GPIO中断的状态
39 ///< TODO:清除中断
40 ///< TODO:根据中断状态执行用户回调函数
41
42 }
43
csi_gpio_init(csi_gpio_t * gpio,uint32_t port_idx)44 csi_error_t csi_gpio_init(csi_gpio_t *gpio, uint32_t port_idx)
45 {
46 CSI_PARAM_CHK(gpio, CSI_ERROR);
47
48 csi_error_t ret = CSI_OK;
49
50 ///< 本函数初始化GPIO控制器,非单个GPIO PIN
51
52 ///< 获取中断号、基地址等相关信息
53 if (target_get(DEV_DW_GPIO_TAG, port_idx, &gpio->dev) != CSI_OK) {
54 ret = CSI_ERROR;
55 }
56
57 return ret;
58 }
59
csi_gpio_uninit(csi_gpio_t * gpio)60 void csi_gpio_uninit(csi_gpio_t *gpio)
61 {
62 CSI_PARAM_CHK_NORETVAL(gpio);
63
64 ///< TODO:重置GPIO相关寄存器
65
66 ///< 禁止中断控制器对应的中断和注销GPIO的中断服务函数
67 csi_irq_disable((uint32_t)gpio->dev.irq_num);
68 csi_irq_detach((uint32_t)gpio->dev.irq_num);
69
70 ///< 释放句柄
71 memset(gpio, 0, sizeof(csi_gpio_t));
72 }
73
csi_gpio_dir(csi_gpio_t * gpio,uint32_t pin_mask,csi_gpio_dir_t dir)74 csi_error_t csi_gpio_dir(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_dir_t dir)
75 {
76 CSI_PARAM_CHK(gpio, CSI_ERROR);
77 CSI_PARAM_CHK(pin_mask, CSI_ERROR);
78
79 csi_error_t ret = CSI_OK;
80
81 ///< 注意:pin_mask代表正在操作的GPIO PIN,例如pin_mask = 0x3,则代表正在操作GPIO PIN_0 和GPIO PIN_1
82
83 ///< TODO:根据dir和pin_mask设置相应GPIO口数据传输的方向
84
85 return ret;
86 }
87
csi_gpio_mode(csi_gpio_t * gpio,uint32_t pin_mask,csi_gpio_mode_t mode)88 csi_error_t csi_gpio_mode(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_mode_t mode)
89 {
90 CSI_PARAM_CHK(gpio, CSI_ERROR);
91 CSI_PARAM_CHK(pin_mask, CSI_ERROR);
92
93 csi_error_t ret = CSI_OK;
94 csi_error_t temp;
95 uint8_t offset = 0U;
96 pin_name_t pin_name;
97
98 /* set pin mode */
99 while (pin_mask) {
100 if (pin_mask & 0x01U) {
101 ///< 获取使用的GPIO口的引脚名称
102 pin_name = csi_pin_get_pinname_by_gpio(gpio->dev.idx, offset);
103
104 if ((uint8_t)pin_name != 0xFFU) {
105 ///< 设置GPIO的模式:GPIO_MODE_PULLNONE、GPIO_MODE_PULLUP、GPIO_MODE_PULLDOWN、GPIO_MODE_OPEN_DRAIN、GPIO_MODE_PUSH_PULL
106 temp = csi_pin_mode(pin_name, mode);
107
108 if (temp == CSI_ERROR) { /* return CSI_ERROR if csi_pin_mode return CSI_ERROR */
109 ret = CSI_ERROR;
110 break;
111 } else if (temp == CSI_UNSUPPORTED) { /* return CSI_UNSUPPORTED if csi_pin_mode return CSI_UNSUPPORTED */
112 ret = CSI_UNSUPPORTED;
113 }
114 }
115 }
116
117 pin_mask >>= 1U;
118 offset++;
119 }
120
121 return ret;
122 }
123
csi_gpio_irq_mode(csi_gpio_t * gpio,uint32_t pin_mask,csi_gpio_irq_mode_t mode)124 csi_error_t csi_gpio_irq_mode(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_irq_mode_t mode)
125 {
126 CSI_PARAM_CHK(gpio, CSI_ERROR);
127
128 csi_error_t ret = CSI_OK;
129
130 switch (mode) {
131 /* rising edge interrupt mode */
132 case GPIO_IRQ_MODE_RISING_EDGE:
133 ///< TODO:根据pin_mask和mode设置中断类型和中断极性
134 break;
135
136 /* falling edge interrupt mode */
137 case GPIO_IRQ_MODE_FALLING_EDGE:
138 ///< TODO:根据pin_mask和mode设置中断类型和中断极性
139 break;
140
141 /* low level interrupt mode */
142 case GPIO_IRQ_MODE_LOW_LEVEL:
143 ///< TODO:根据pin_mask和mode设置中断类型和中断极性
144 break;
145
146 /* high level interrupt mode */
147 case GPIO_IRQ_MODE_HIGH_LEVEL:
148 ///< TODO:根据pin_mask和mode设置中断类型和中断极性
149 break;
150
151 /* double edge interrupt mode */
152 case GPIO_IRQ_MODE_BOTH_EDGE:
153 default:
154 ret = CSI_UNSUPPORTED;
155 break;
156 }
157
158 return ret;
159 }
160
csi_gpio_irq_enable(csi_gpio_t * gpio,uint32_t pin_mask,bool enable)161 csi_error_t csi_gpio_irq_enable(csi_gpio_t *gpio, uint32_t pin_mask, bool enable)
162 {
163 CSI_PARAM_CHK(gpio, CSI_ERROR);
164 CSI_PARAM_CHK(pin_mask, CSI_ERROR);
165
166 ///< TODO:打开或者关闭GPIO
167
168 return CSI_OK;
169 }
170
csi_gpio_debonce(csi_gpio_t * gpio,uint32_t pin_mask,bool enable)171 csi_error_t csi_gpio_debonce(csi_gpio_t *gpio, uint32_t pin_mask, bool enable)
172 {
173 CSI_PARAM_CHK(gpio, CSI_ERROR);
174 CSI_PARAM_CHK(pin_mask, CSI_ERROR);
175
176 return CSI_UNSUPPORTED;
177 }
178
csi_gpio_toggle(csi_gpio_t * gpio,uint32_t pin_mask)179 void csi_gpio_toggle(csi_gpio_t *gpio, uint32_t pin_mask)
180 {
181 CSI_PARAM_CHK_NORETVAL(gpio);
182 CSI_PARAM_CHK_NORETVAL(pin_mask);
183
184 ///< TODO:翻转GPIO口输出状态,例如,当前GPIO的输出状态是高电平,翻转之后则为低电平
185 }
186
csi_gpio_write(csi_gpio_t * gpio,uint32_t pin_mask,csi_gpio_pin_state_t value)187 void csi_gpio_write(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_pin_state_t value)
188 {
189 CSI_PARAM_CHK_NORETVAL(gpio);
190 CSI_PARAM_CHK_NORETVAL(pin_mask);
191
192 ///< TODO:根据value写数据寄存器
193
194 }
195
csi_gpio_read(csi_gpio_t * gpio,uint32_t pin_mask)196 uint32_t csi_gpio_read(csi_gpio_t *gpio, uint32_t pin_mask)
197 {
198 CSI_PARAM_CHK(gpio, CSI_ERROR);
199 CSI_PARAM_CHK(pin_mask, CSI_ERROR);
200 uint32_t status = 0U;
201
202 ///< TODO:读取相应引脚的信号输入状态
203
204 return status;
205
206 }
207
csi_gpio_attach_callback(csi_gpio_t * gpio,void * callback,void * arg)208 csi_error_t csi_gpio_attach_callback(csi_gpio_t *gpio, void *callback, void *arg)
209 {
210 CSI_PARAM_CHK(gpio, CSI_ERROR);
211 CSI_PARAM_CHK(callback, CSI_ERROR);
212
213 ///< TODO:清除中断
214
215 gpio->callback = callback;
216 gpio->arg = arg;
217
218 ///< 注册GPIO的中断服务函数,使能中断控制器对应的中断
219 csi_irq_attach((uint32_t)gpio->dev.irq_num, &dw_gpio_irqhandler, &gpio->dev);
220 csi_irq_enable((uint32_t)gpio->dev.irq_num);
221
222 return CSI_OK;
223 }
224
csi_gpio_detach_callback(csi_gpio_t * gpio)225 void csi_gpio_detach_callback(csi_gpio_t *gpio)
226 {
227 CSI_PARAM_CHK_NORETVAL(gpio);
228
229 gpio->callback = NULL;
230 gpio->arg = NULL;
231
232 ///< 注销GPIO的中断服务函数,禁止中断控制器对应的中断
233 csi_irq_disable((uint32_t)gpio->dev.irq_num);
234 csi_irq_detach((uint32_t)gpio->dev.irq_num);
235 }
236
237 #ifdef CONFIG_PM
dw_gpio_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)238 csi_error_t dw_gpio_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
239 {
240 CSI_PARAM_CHK(dev, CSI_ERROR);
241
242 csi_error_t ret = CSI_OK;
243 csi_pm_dev_t *pm_dev = &dev->pm_dev;
244
245 switch (action) {
246 case PM_DEV_SUSPEND:
247 ///< TODO:恢复GPIO寄存器
248 break;
249
250 case PM_DEV_RESUME:
251 ///< TODO:保存GPIO寄存器
252 break;
253
254 default:
255 ret = CSI_ERROR;
256 break;
257 }
258
259 return ret;
260 }
261
csi_gpio_enable_pm(csi_gpio_t * gpio)262 csi_error_t csi_gpio_enable_pm(csi_gpio_t *gpio)
263 {
264 ///< TODO:注册GPIO低功耗处理函数dw_gpio_pm_action
265 }
266
csi_gpio_disable_pm(csi_gpio_t * gpio)267 void csi_gpio_disable_pm(csi_gpio_t *gpio)
268 {
269 csi_pm_dev_unregister(&gpio->dev);
270 }
271 #endif
272