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