• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
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 
16 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
17 #include "hcs_macro.h"
18 #include "hdf_config_macro.h"
19 #else
20 #include "device_resource_if.h"
21 #endif
22 #include "hdf_log.h"
23 #include "los_interrupt.h"
24 #include "gpio_core.h"
25 #include "gd32f4xx.h"
26 
27 #define HDF_LOG_TAG gpio_gd32f450
28 
29 #define GPIO_PIN_TOTAL 140
30 #define GPIO_REG_BASE 0x40020000
31 #define GPIO_REG_STEP 0x00000400
32 #define GPIO_BIT_PER_GROUP 16
33 
34 #define DEFAULT_PRE_PRIORITY 2U
35 #define DEFAULT_SUB_PRIORITY 0U
36 #define EXIT_PIN_SOURCE_MAX GPIO_BIT_PER_GROUP
37 #define GPIO_MODE_DATA_LENGTH 2
38 #define EXTI5_9_IRQ_START_NUM 5
39 #define EXTI5_9_IRQ_END_NUM 9
40 #define EXTI10_15_IRQ_START_NUM 10
41 #define EXTI10_15_IRQ_END_NUM 15
42 #define EXTI5_9_IRQ_PARAM_NUM 5
43 #define EXTI10_15_IRQ_PARAM_NUM 6
44 
45 typedef enum {
46     PIN_EXTI0 = 0,
47     PIN_EXTI1 = 1,
48     PIN_EXTI2 = 2,
49     PIN_EXTI3 = 3,
50     PIN_EXTI4 = 4,
51     PIN_EXTI5 = 5,
52     PIN_EXTI6 = 6,
53     PIN_EXTI7 = 7,
54     PIN_EXTI8 = 8,
55     PIN_EXTI9 = 9,
56     PIN_EXTI10 = 10,
57     PIN_EXTI11 = 11,
58     PIN_EXTI12 = 12,
59     PIN_EXTI13 = 13,
60     PIN_EXTI14 = 14,
61     PIN_EXTI15 = 15,
62 } EXTI0_NUM;
63 
64 typedef enum {
65     PIN_NUM0 = 0,
66     PIN_NUM1 = 1,
67     PIN_NUM2 = 2,
68     PIN_NUM3 = 3,
69     PIN_NUM4 = 4,
70     PIN_NUM5 = 5,
71     PIN_NUM6 = 6,
72     PIN_NUM7 = 7,
73     PIN_NUM8 = 8,
74     PIN_NUM9 = 9,
75     PIN_NUM10 = 10,
76     PIN_NUM11 = 11,
77     PIN_NUM12 = 12,
78     PIN_NUM13 = 13,
79     PIN_NUM14 = 14,
80     PIN_NUM15 = 15,
81 } PIN_NUM;
82 /* GPIO 分组 */
83 // PA0 ~ PA15, 0-15
84 // PB0 ~ PB15, 16-31
85 // PC0 ~ PC15, 32-47
86 // PD0 ~ PD15, 48-63
87 // PE0 ~ PE15, 64-79
88 // PF0 ~ PF15, 80-95
89 // PG0 ~ PG15, 96-111
90 // PH0 ~ PH15, 112-117
91 // PI0 ~ PI11. 118-139
92 
93 /* 一个中断线仅支持一个端口触发 */
94 // EXTILineNumber  Source
95 // 0                PA0/PB0/PC0/PD0/PE0/PF0/PG0/PH0/PI0
96 // 1                PA1/PB1/PC1/PD1/PE1/PF1/PG1/PH1/PI1
97 // 2                PA2/PB2/PC2/PD2/PE2/PF2/PG2/PH2/PI2
98 // 3                PA3/PB3/PC3/PD3/PE3/PF3/PG3/PH3/PI3
99 // 4                PA4/PB4/PC4/PD4/PE4/PF4/PG4/PH4/PI4
100 // 5                PA5/PB5/PC5/PD5/PE5/PF5/PG5/PH5/PI5
101 // 6                PA6/PB6/PC6/PD6/PE6/PF6/PG6/PH6/PI6
102 // 7                PA7/PB7/PC7/PD7/PE7/PF7/PG7/PH7/PI7
103 // 8                PA8/PB8/PC8/PD8/PE8/PF8/PG8/PH8/PI8
104 // 9                PA9/PB9/PC9/PD9/PE9/PF9/PG9/PH9/PI9
105 // 10               PA10/PB10/PC10/PD10/PE10/PF10/PG10/PH10/PI10
106 // 11               PA11/PB11/PC11/PD11/PE11/PF11/PG11/PH11/PI11
107 // 12               PA12/PB12/PC12/PD12/PE12/PF12/PG12/PH12
108 // 13               PA13/PB13/PC13/PD13/PE13/PF13/PG13/PH13
109 // 14               PA14/PB14/PC14/PD14/PE14/PF14/PG14/PH14
110 // 15               PA15/PB15/PC15/PD15/PE15/PF15/PG15/PH15
111 
112 struct GpioDevCntlr {
113     struct GpioCntlr cntlr;
114 
115     uint32_t irqSave;
116     OsalSpinlock lock;
117 
118     uint32_t start;
119     uint32_t count;
120 };
121 
122 struct DevIrqInfo {
123     uint8_t isRegistered;
124     struct GpioCntlr *cntlr;
125     uint16_t sourceLocal;
126 };
127 static struct DevIrqInfo g_DevIrqInfo[EXIT_PIN_SOURCE_MAX] = {0};
128 
129 struct IrqFuncParam {
130     uint8_t startExti;
131     uint8_t endExti;
132     uint8_t irqRcu;
133 };
134 static struct IrqFuncParam g_Exti[7];
135 
ToGpioDevCntlr(struct GpioCntlr * cntlr)136 static inline struct GpioDevCntlr *ToGpioDevCntlr(struct GpioCntlr *cntlr)
137 {
138     if (cntlr == NULL) {
139         HDF_LOGE("%s, cntlr is NULL", __func__);
140         return NULL;
141     }
142     return (struct GpioDevCntlr *)cntlr;
143 }
144 
ToGpioPeriph(struct GpioCntlr * cntlr,uint16_t local)145 static inline uint32_t ToGpioPeriph(struct GpioCntlr *cntlr, uint16_t local)
146 {
147     uint32_t gpioPeriph = 0;
148 
149     gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP;
150 
151     return gpioPeriph;
152 }
153 
ToGpioPin(struct GpioCntlr * cntlr,uint16_t local)154 static inline uint32_t ToGpioPin(struct GpioCntlr *cntlr, uint16_t local)
155 {
156     uint32_t pinNum = 0;
157 
158     pinNum = local % GPIO_BIT_PER_GROUP;
159 
160     return (BIT(pinNum));
161 }
162 
ToGpioExitSourceIndex(struct GpioCntlr * cntlr,uint16_t local)163 static inline uint8_t ToGpioExitSourceIndex(struct GpioCntlr *cntlr, uint16_t local)
164 {
165     return (local % GPIO_BIT_PER_GROUP);
166 }
167 
ToGpioExtiLineNum(struct GpioCntlr * cntlr,uint16_t local)168 static inline exti_line_enum ToGpioExtiLineNum(struct GpioCntlr *cntlr, uint16_t local)
169 {
170     uint32_t pinNum = 0;
171 
172     pinNum = local % GPIO_BIT_PER_GROUP;
173 
174     return (BIT(pinNum));
175 }
176 
ToGpioRcuPeriphNum(struct GpioCntlr * cntlr,uint16_t local)177 static inline rcu_periph_enum ToGpioRcuPeriphNum(struct GpioCntlr *cntlr, uint16_t local)
178 {
179     rcu_periph_enum rcuPeriph;
180 
181     rcuPeriph = (rcu_periph_enum)(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, local / GPIO_BIT_PER_GROUP));
182 
183     return rcuPeriph;
184 }
185 
ToGpioRcuIndex(uint16_t local)186 static uint8_t ToGpioRcuIndex(uint16_t local)
187 {
188     uint16_t pinNum = 0;
189     uint8_t index = 0;
190     pinNum = local % GPIO_BIT_PER_GROUP;
191     if (pinNum < EXTI5_9_IRQ_START_NUM) {
192         index = pinNum;
193     } else if (pinNum < EXTI10_15_IRQ_START_NUM) {
194         index = EXTI5_9_IRQ_PARAM_NUM;
195     } else {
196         index = EXTI10_15_IRQ_PARAM_NUM;
197     }
198     return index;
199 }
InitExti(void)200 static void InitExti(void)
201 {
202     static uint8_t single = 0;
203     if (single == 0) {
204         for (int i = 0; i < EXTI5_9_IRQ_PARAM_NUM; i++) {
205             g_Exti[i].startExti = i;
206             g_Exti[i].endExti = i;
207             g_Exti[i].irqRcu = EXTI0_IRQn + i;
208         }
209         g_Exti[EXTI5_9_IRQ_PARAM_NUM].startExti = EXTI5_9_IRQ_START_NUM;
210         g_Exti[EXTI5_9_IRQ_PARAM_NUM].endExti = EXTI5_9_IRQ_END_NUM;
211         g_Exti[EXTI5_9_IRQ_PARAM_NUM].irqRcu = EXTI5_9_IRQn;
212         g_Exti[EXTI10_15_IRQ_PARAM_NUM].startExti = EXTI10_15_IRQ_START_NUM;
213         g_Exti[EXTI10_15_IRQ_PARAM_NUM].endExti = EXTI10_15_IRQ_END_NUM;
214         g_Exti[EXTI10_15_IRQ_PARAM_NUM].irqRcu = EXTI10_15_IRQn;
215         single = 1;
216     }
217 }
218 
ToGpioIrqNum(struct GpioCntlr * cntlr,uint16_t local)219 static inline uint8_t ToGpioIrqNum(struct GpioCntlr *cntlr, uint16_t local)
220 {
221     uint8_t index;
222     index = ToGpioRcuIndex(local);
223     return g_Exti[index].irqRcu;
224 }
225 
ToGpioExtiSourcePort(struct GpioCntlr * cntlr,uint16_t local)226 static inline uint8_t ToGpioExtiSourcePort(struct GpioCntlr *cntlr, uint16_t local)
227 {
228     uint8_t groupNum = 0;
229 
230     groupNum = local / GPIO_BIT_PER_GROUP;
231 
232     return ((uint8_t)groupNum);
233 }
234 
ToGpioExtiSourcePin(struct GpioCntlr * cntlr,uint16_t local)235 static inline uint8_t ToGpioExtiSourcePin(struct GpioCntlr *cntlr, uint16_t local)
236 {
237     uint8_t pinNum = 0;
238 
239     pinNum = local % GPIO_BIT_PER_GROUP;
240 
241     return ((uint8_t)pinNum);
242 }
243 
GpioDevSetDir(struct GpioCntlr * cntlr,uint16_t local,uint16_t dir)244 static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir)
245 {
246     uint32_t gpioPeriph;
247     uint32_t mode;
248     uint32_t pull;
249     uint32_t pin;
250     struct GpioDevCntlr *p = NULL;
251 
252     if (cntlr == NULL) {
253         HDF_LOGE("%s, cntlr is NULL", __func__);
254         return HDF_ERR_INVALID_PARAM;
255     }
256 
257     if (local >= GPIO_PIN_TOTAL) {
258         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
259         return HDF_ERR_INVALID_PARAM;
260     }
261 
262     if ((dir != GPIO_DIR_IN) && (dir != GPIO_DIR_OUT)) {
263         HDF_LOGE("%s, dir(%d) is not right", __func__, dir);
264         return HDF_ERR_INVALID_PARAM;
265     }
266 
267     p = ToGpioDevCntlr(cntlr);
268     gpioPeriph = ToGpioPeriph(cntlr, local);
269     if (dir == GPIO_DIR_IN) {
270         mode = GPIO_MODE_INPUT;
271     } else {
272         mode = GPIO_MODE_OUTPUT;
273     }
274     pull = GPIO_PUPD_NONE;
275     pin = ToGpioPin(cntlr, local);
276 
277     if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) {
278         HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__);
279         return HDF_ERR_DEVICE_BUSY;
280     }
281 
282     gpio_mode_set(gpioPeriph, mode, pull, pin);
283 
284     (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
285 
286     return HDF_SUCCESS;
287 }
288 
GpioDevGetDir(struct GpioCntlr * cntlr,uint16_t local,uint16_t * dir)289 static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir)
290 {
291     uint32_t gpioPeriph;
292     uint32_t ctl;
293     uint32_t pin;
294     uint32_t readDir;
295 
296     if (cntlr == NULL) {
297         HDF_LOGE("%s, cntlr is NULL", __func__);
298         return HDF_ERR_INVALID_PARAM;
299     }
300 
301     if (local >= GPIO_PIN_TOTAL) {
302         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
303         return HDF_ERR_INVALID_PARAM;
304     }
305 
306     if (dir == NULL) {
307         HDF_LOGE("%s, dir is NULL", __func__);
308         return HDF_ERR_INVALID_PARAM;
309     }
310 
311     gpioPeriph = ToGpioPeriph(cntlr, local);
312     pin = ToGpioPin(cntlr, local);
313     ctl = GPIO_CTL(gpioPeriph);
314     readDir = (ctl >> (GPIO_MODE_DATA_LENGTH * pin)) & 0x03;
315 
316     if (readDir == GPIO_MODE_OUTPUT) {
317         *dir = GPIO_DIR_OUT;
318     } else if (readDir == GPIO_MODE_INPUT) {
319         *dir = GPIO_DIR_IN;
320     } else { // default direction
321         HDF_LOGE("invalid gpio mode input/output!");
322         return HDF_ERR_INVALID_PARAM;
323     }
324 
325     return HDF_SUCCESS;
326 }
327 
GpioDevWrite(struct GpioCntlr * cntlr,uint16_t local,uint16_t val)328 static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val)
329 {
330     uint32_t gpioPeriph;
331     uint32_t pin;
332     bit_status bitValue;
333     struct GpioDevCntlr *p = NULL;
334 
335     if (cntlr == NULL) {
336         HDF_LOGE("%s, cntlr is NULL", __func__);
337         return HDF_ERR_INVALID_PARAM;
338     }
339 
340     if (local >= GPIO_PIN_TOTAL) {
341         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
342         return HDF_ERR_INVALID_PARAM;
343     }
344     p = ToGpioDevCntlr(cntlr);
345     gpioPeriph = ToGpioPeriph(cntlr, local);
346     pin = ToGpioPin(cntlr, local);
347     if (val == 1) {
348         bitValue = SET;
349     } else {
350         bitValue = RESET;
351     }
352 
353     if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) {
354         HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__);
355         return HDF_ERR_DEVICE_BUSY;
356     }
357 
358     gpio_bit_write(gpioPeriph, pin, bitValue);
359 
360     (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
361 
362     return HDF_SUCCESS;
363 }
364 
GpioDevRead(struct GpioCntlr * cntlr,uint16_t local,uint16_t * val)365 static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val)
366 {
367     uint32_t gpioPeriph;
368     uint32_t pin;
369     bit_status bitValue;
370 
371     if (cntlr == NULL) {
372         HDF_LOGE("%s, cntlr is NULL", __func__);
373         return HDF_ERR_INVALID_PARAM;
374     }
375 
376     if (local >= GPIO_PIN_TOTAL) {
377         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
378         return HDF_ERR_INVALID_PARAM;
379     }
380 
381     gpioPeriph = ToGpioPeriph(cntlr, local);
382     pin = ToGpioPin(cntlr, local);
383 
384     bitValue = gpio_input_bit_get(gpioPeriph, pin);
385     if (bitValue == SET) {
386         *val = GPIO_VAL_HIGH;
387     } else {
388         *val = GPIO_VAL_LOW;
389     }
390 
391     return HDF_SUCCESS;
392 }
393 
GpioDevClearIrqUnsafe(struct GpioCntlr * cntlr,uint16_t local)394 static void GpioDevClearIrqUnsafe(struct GpioCntlr *cntlr, uint16_t local)
395 {
396     exti_line_enum lineX;
397     lineX = ToGpioExtiLineNum(cntlr, local);
398 
399     exti_interrupt_flag_clear(lineX);
400 }
401 
GpioDevSetIrqEnableUnsafe(struct GpioCntlr * cntlr,uint16_t local,int flag)402 static void GpioDevSetIrqEnableUnsafe(struct GpioCntlr *cntlr, uint16_t local, int flag)
403 {
404     exti_line_enum lineX;
405 
406     lineX = ToGpioExtiLineNum(cntlr, local);
407 
408     if (flag == 0) {
409         exti_interrupt_disable(lineX);
410     } else {
411         exti_interrupt_enable(lineX);
412     }
413 }
414 
GpioDevEnableIrq(struct GpioCntlr * cntlr,uint16_t local)415 static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t local)
416 {
417     struct GpioDevCntlr *p = NULL;
418 
419     static int isFirstEnterFlag = 1;
420     if (isFirstEnterFlag == 1) {
421         rcu_periph_clock_enable(RCU_SYSCFG);
422         isFirstEnterFlag = 0;
423     }
424 
425     if (cntlr == NULL) {
426         HDF_LOGE("%s, cntlr is NULL", __func__);
427         return HDF_ERR_INVALID_PARAM;
428     }
429 
430     if (local >= GPIO_PIN_TOTAL) {
431         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
432         return HDF_ERR_INVALID_PARAM;
433     }
434 
435     p = ToGpioDevCntlr(cntlr);
436     if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) {
437         HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__);
438         return HDF_ERR_DEVICE_BUSY;
439     }
440 
441     GpioDevSetIrqEnableUnsafe(cntlr, local, 1);
442 
443     nvic_irq_enable(ToGpioIrqNum(cntlr, local), DEFAULT_PRE_PRIORITY, DEFAULT_SUB_PRIORITY);
444     syscfg_exti_line_config(ToGpioExtiSourcePort(cntlr, local), ToGpioExtiSourcePin(cntlr, local));
445 
446     (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
447     return HDF_SUCCESS;
448 }
449 
GpioDevDisableIrq(struct GpioCntlr * cntlr,uint16_t local)450 static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t local)
451 {
452     struct GpioDevCntlr *p = NULL;
453 
454     if (cntlr == NULL) {
455         HDF_LOGE("%s, cntlr is NULL", __func__);
456         return HDF_ERR_INVALID_PARAM;
457     }
458 
459     if (local >= GPIO_PIN_TOTAL) {
460         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
461         return HDF_ERR_INVALID_PARAM;
462     }
463 
464     p = ToGpioDevCntlr(cntlr);
465     if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) {
466         HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__);
467         return HDF_ERR_DEVICE_BUSY;
468     }
469 
470     GpioDevSetIrqEnableUnsafe(cntlr, local, 0);
471 
472     (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
473     return HDF_SUCCESS;
474 }
475 
476 /* 中断处理方式仅支持沿触发 */
GpioDevSetIrqTypeUnsafe(struct GpioCntlr * cntlr,uint16_t local,uint16_t mode)477 static int32_t GpioDevSetIrqTypeUnsafe(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode)
478 {
479     exti_line_enum lineNum;
480     exti_trig_type_enum trigType;
481 
482     lineNum = ToGpioExtiLineNum(cntlr, local);
483 
484     switch (mode) {
485         case OSAL_IRQF_TRIGGER_RISING:
486             trigType = EXTI_TRIG_RISING;
487             break;
488         case OSAL_IRQF_TRIGGER_FALLING:
489             trigType = EXTI_TRIG_FALLING;
490             break;
491         case OSAL_IRQF_TRIGGER_HIGH:
492         case OSAL_IRQF_TRIGGER_LOW:
493         case OSAL_IRQF_TRIGGER_NONE:
494         default:
495             HDF_LOGE("%s:irq mode(%x) not support", __func__, mode);
496             return HDF_ERR_INVALID_PARAM;
497     }
498 
499     exti_init(lineNum, EXTI_INTERRUPT, trigType);
500     exti_interrupt_flag_clear(lineNum);
501 
502     return HDF_SUCCESS;
503 }
504 
DevExitIrqHandler(struct IrqFuncParam * para)505 static void DevExitIrqHandler(struct IrqFuncParam *para)
506 {
507     HDF_LOGI("===================== INTERRUPT:%s %d id addr=%0x para add=%0x", __FUNCTION__, __LINE__, para);
508     struct DevIrqInfo *p_info;
509     for (uint8_t i = para->startExti; i <= para->endExti; i++) {
510         exti_line_enum linex = BIT(i);
511         if (RESET != exti_interrupt_flag_get(linex)) {
512             exti_interrupt_flag_clear(linex);
513             p_info = &g_DevIrqInfo[i];
514             if (p_info->isRegistered == 1) {
515                 GpioCntlrIrqCallback(p_info->cntlr, p_info->sourceLocal);
516             }
517         }
518     }
519 }
520 
DevHwiCreate(struct GpioCntlr * cntlr,uint16_t local)521 static UINT32 DevHwiCreate(struct GpioCntlr *cntlr, uint16_t local)
522 {
523     HwiIrqParam irqParam;
524     uint8_t index;
525 
526     index = ToGpioRcuIndex(local);
527     irqParam.pDevId = &g_Exti[index];
528     return LOS_HwiCreate(ToGpioIrqNum(cntlr, local), 0, 0, (HWI_PROC_FUNC)DevExitIrqHandler, &irqParam);
529 }
530 
DevHwiDelete(struct GpioCntlr * cntlr,uint16_t local)531 static UINT32 DevHwiDelete(struct GpioCntlr *cntlr, uint16_t local)
532 {
533     uint8_t i;
534     uint8_t index;
535 
536     index = ToGpioRcuIndex(local);
537     for (i = g_Exti[index].startExti; i <= g_Exti[index].endExti; i++) {
538         if (g_DevIrqInfo[index].isRegistered == 1) {
539             break;
540         }
541     }
542 
543     if (i > g_Exti[index].endExti) {
544         return LOS_HwiDelete(ToGpioIrqNum(cntlr, local), NULL);
545     }
546 
547     return HDF_SUCCESS;
548 }
549 
GpioDevSetIrq(struct GpioCntlr * cntlr,uint16_t local,uint16_t mode)550 static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode)
551 {
552     struct GpioDevCntlr *p = NULL;
553     uint8_t index;
554 
555     if (cntlr == NULL) {
556         HDF_LOGE("%s, cntlr is NULL", __func__);
557         return HDF_ERR_INVALID_PARAM;
558     }
559 
560     if (local >= GPIO_PIN_TOTAL) {
561         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
562         return HDF_ERR_INVALID_PARAM;
563     }
564 
565     p = ToGpioDevCntlr(cntlr);
566     if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) {
567         HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__);
568         return HDF_ERR_DEVICE_BUSY;
569     }
570 
571     InitExti();
572     gpio_mode_set(ToGpioPeriph(cntlr, local), GPIO_MODE_INPUT, GPIO_PUPD_NONE, ToGpioPin(cntlr, local));
573     GpioDevSetIrqTypeUnsafe(cntlr, local, mode);
574     GpioDevSetIrqEnableUnsafe(cntlr, local, 0); // disable irq when set
575     GpioDevClearIrqUnsafe(cntlr, local);
576 
577     index = ToGpioExitSourceIndex(cntlr, local);
578     if (g_DevIrqInfo[index].isRegistered == 1) {
579         HDF_LOGE("%s: exitSourceIndex [%d] has already been registered! You need to unset it", index);
580         (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
581         return HDF_FAILURE;
582     }
583 
584     g_DevIrqInfo[index].isRegistered = 1;
585     g_DevIrqInfo[index].cntlr = cntlr;
586     g_DevIrqInfo[index].sourceLocal = local;
587 
588     (void)DevHwiCreate(cntlr, local);
589 
590     (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
591 
592     return HDF_SUCCESS;
593 }
594 
GpioDevUnsetIrq(struct GpioCntlr * cntlr,uint16_t local)595 static int32_t GpioDevUnsetIrq(struct GpioCntlr *cntlr, uint16_t local)
596 {
597     struct GpioDevCntlr *p = NULL;
598     uint8_t index;
599     if (cntlr == NULL) {
600         HDF_LOGE("%s, cntlr is NULL", __func__);
601         return HDF_ERR_INVALID_PARAM;
602     }
603 
604     if (local >= GPIO_PIN_TOTAL) {
605         HDF_LOGE("%s, local(%d) is out of range", __func__, local);
606         return HDF_ERR_INVALID_PARAM;
607     }
608 
609     p = ToGpioDevCntlr(cntlr);
610     if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) {
611         HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__);
612         return HDF_ERR_DEVICE_BUSY;
613     }
614 
615     index = ToGpioExitSourceIndex(cntlr, local);
616     g_DevIrqInfo[index].isRegistered = 0;
617 
618     GpioDevSetIrqEnableUnsafe(cntlr, local, 0);
619     GpioDevClearIrqUnsafe(cntlr, local);
620     (void)DevHwiDelete(cntlr, local);
621 
622     (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave);
623 
624     return HDF_SUCCESS;
625 }
626 
627 static struct GpioMethod g_Method = {
628     .request = NULL,
629     .release = NULL,
630     .write = GpioDevWrite,
631     .read = GpioDevRead,
632     .setDir = GpioDevSetDir,
633     .getDir = GpioDevGetDir,
634     .toIrq = NULL,
635     .setIrq = GpioDevSetIrq,
636     .unsetIrq = GpioDevUnsetIrq,
637     .enableIrq = GpioDevEnableIrq,
638     .disableIrq = GpioDevDisableIrq,
639 };
640 
641 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
642 #define GPIO_FIND_CONFIG(node, name, resource)                                                                         \
643     do {                                                                                                               \
644         if (strcmp(HCS_PROP(node, match_attr), name) == 0) {                                                           \
645             uint32_t start = HCS_PROP(node, start);                                                                    \
646             uint32_t count = HCS_PROP(node, count);                                                                    \
647             resource->start = start;                                                                                   \
648             resource->count = count;                                                                                   \
649             result = HDF_SUCCESS;                                                                                      \
650         }                                                                                                              \
651     } while (0)
652 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
653 #define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config)
DevGetGpioDeviceResource(struct GpioDevCntlr * resource,const char * deviceMatchAttr)654 static int32_t DevGetGpioDeviceResource(struct GpioDevCntlr *resource, const char *deviceMatchAttr)
655 {
656     int32_t result = HDF_FAILURE;
657     if (resource == NULL || deviceMatchAttr == NULL) {
658         HDF_LOGE("%s: resource or deviceMatchAttr is NULL", __func__);
659         return HDF_ERR_INVALID_PARAM;
660     }
661 
662 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, gpio_config)
663     HCS_FOREACH_CHILD_VARGS(PLATFORM_GPIO_CONFIG, GPIO_FIND_CONFIG, deviceMatchAttr, resource);
664 #endif
665     if (result != HDF_SUCCESS) {
666         HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
667     }
668 
669     return result;
670 }
671 #else
DevGetGpioDeviceResource(struct GpioDevCntlr * p,const struct DeviceResourceNode * node)672 static int32_t DevGetGpioDeviceResource(struct GpioDevCntlr *p, const struct DeviceResourceNode *node)
673 {
674     int32_t ret = 0;
675 
676     if (node == NULL) {
677         HDF_LOGE("%s, device resource node is NULL", __func__);
678         return HDF_ERR_INVALID_PARAM;
679     }
680 
681     struct DeviceResourceIface *drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
682     if (drsOps == NULL || drsOps->GetUint16 == NULL || drsOps->GetUint32 == NULL) {
683         HDF_LOGE("%s: invalid drs ops fail!", __func__);
684         return HDF_FAILURE;
685     }
686 
687     ret = drsOps->GetUint32(node, "start", &p->start, 0);
688     if (ret != HDF_SUCCESS) {
689         HDF_LOGE("%s: read regBase fail!", __func__);
690         return ret;
691     }
692 
693     ret = drsOps->GetUint32(node, "count", &p->count, 0);
694     if (ret != HDF_SUCCESS) {
695         HDF_LOGE("%s: read regStep fail!", __func__);
696         return ret;
697     }
698 
699     if ((p->start < 0) || (p->start >= GPIO_PIN_TOTAL)) {
700         HDF_LOGE("%s: start(%d) is out of range", __func__, p->start);
701         return HDF_ERR_INVALID_PARAM;
702     }
703 
704     if ((p->count <= 0) || ((p->start + p->count - 1) >= GPIO_PIN_TOTAL)) {
705         HDF_LOGE("%s start(%d): count(%d) is out of range", __func__, p->start, p->count);
706         return HDF_ERR_INVALID_PARAM;
707     }
708 
709     return HDF_SUCCESS;
710 }
711 #endif
712 
GpioDevBind(struct HdfDeviceObject * device)713 static int32_t GpioDevBind(struct HdfDeviceObject *device)
714 {
715     HDF_LOGI("%s: Enter %d", __FILE__, __FUNCTION__, __LINE__);
716     (void)device;
717     return HDF_SUCCESS;
718 }
GpioRcuInit(struct GpioDevCntlr * p)719 static void GpioRcuInit(struct GpioDevCntlr *p)
720 {
721     rcu_periph_enum rcuPeriph = RCU_GPIOA;
722     if (p == NULL) {
723         HDF_LOGE("%s: GpioDevCntlr null!", __func__);
724         return;
725     }
726     rcu_periph_clock_enable(RCU_SYSCFG);
727     for (int32_t i = 0; i < p->count; i++) {
728         rcuPeriph = ToGpioRcuPeriphNum(&p->cntlr, (p->start + i));
729         rcu_periph_clock_enable(rcuPeriph);
730     }
731 }
GpioDevInit(struct HdfDeviceObject * device)732 static int32_t GpioDevInit(struct HdfDeviceObject *device)
733 {
734     int32_t ret;
735     struct GpioDevCntlr *p = NULL;
736 
737     HDF_LOGI("%s: Enter", __FUNCTION__);
738 
739 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
740     if (device == NULL)
741 #else
742     if (device == NULL || device->property == NULL)
743 #endif
744     {
745         HDF_LOGE("%s: device or property null!", __func__);
746         return HDF_ERR_INVALID_OBJECT;
747     }
748 
749     p = (struct GpioDevCntlr *)OsalMemCalloc(sizeof(struct GpioDevCntlr));
750     if (p == NULL) {
751         HDF_LOGE("%s: malloc memory failed", __func__);
752         return HDF_ERR_MALLOC_FAIL;
753     }
754     memset_s(p, sizeof(struct GpioDevCntlr), 0, sizeof(struct GpioDevCntlr));
755 
756     if (OsalSpinInit(&p->lock) != HDF_SUCCESS) {
757         HDF_LOGE("%s: OsalSpinInit failed!", __func__);
758         OsalSpinDestroy(&p->lock);
759         return HDF_FAILURE;
760     }
761 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
762     ret = DevGetGpioDeviceResource(p, device->deviceMatchAttr);
763 #else
764     ret = DevGetGpioDeviceResource(p, device->property);
765 #endif
766     if (ret != HDF_SUCCESS) {
767         HDF_LOGE("%s: read drs fail:%x", __func__, ret);
768         return ret;
769     }
770 
771     p->cntlr.start = p->start;
772     p->cntlr.count = p->count;
773 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
774     p->cntlr.priv = NULL;
775 #else
776     p->cntlr.priv = (void *)device->property;
777 #endif
778     p->cntlr.ops = &g_Method;
779 
780     GpioRcuInit(p);
781 
782     ret = GpioCntlrAdd(&p->cntlr);
783     if (ret != HDF_SUCCESS) {
784         HDF_LOGE("%s: err add controller: %x", __func__, ret);
785         return ret;
786     }
787 
788     device->priv = p;
789     HDF_LOGI("%s: gpio init success", __func__);
790     return HDF_SUCCESS;
791 }
792 
GpioDevRelease(struct HdfDeviceObject * device)793 static void GpioDevRelease(struct HdfDeviceObject *device)
794 {
795     struct GpioDevCntlr *p = NULL;
796 
797     if (device->priv != NULL) {
798         p = (struct GpioDevCntlr *)device->priv;
799         OsalMemFree(p);
800 
801         device->priv = NULL;
802     }
803 
804     return;
805 }
806 
807 struct HdfDriverEntry g_gpioDriverEntry = {
808     .moduleVersion = 1,
809     .Bind = GpioDevBind,
810     .Init = GpioDevInit,
811     .Release = GpioDevRelease,
812     .moduleName = "GD_GPIO_MODULE_HDF",
813 };
814 HDF_INIT(g_gpioDriverEntry);
815