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