1 /*
2 * Copyright (c) 2021 Nanjing Xiaoxiongpai Intelligent Technology 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 #include "stm32mp1_gpio.h"
17
18
ToMp1xxGpioCntlr(struct GpioCntlr * cntlr)19 static inline struct Mp1xxGpioCntlr *ToMp1xxGpioCntlr(struct GpioCntlr *cntlr)
20 {
21 return (struct Mp1xxGpioCntlr *)cntlr;
22 }
23
Mp1xxToGroupNum(uint16_t gpio)24 static inline uint16_t Mp1xxToGroupNum(uint16_t gpio)
25 {
26 return (uint16_t)(gpio / g_Mp1xxGpioCntlr.bitNum);
27 }
28
Mp1xxToBitNum(uint16_t gpio)29 static inline uint16_t Mp1xxToBitNum(uint16_t gpio)
30 {
31 return (uint16_t)(gpio % g_Mp1xxGpioCntlr.bitNum);
32 }
Mp1xxToGpioNum(uint16_t group,uint16_t bit)33 static inline uint16_t Mp1xxToGpioNum(uint16_t group, uint16_t bit)
34 {
35 return (uint16_t)(group * g_Mp1xxGpioCntlr.bitNum + bit);
36 }
37
Mp1xxGetGroupByGpioNum(struct GpioCntlr * cntlr,uint16_t gpio,struct GpioGroup ** group)38 static int32_t Mp1xxGetGroupByGpioNum(struct GpioCntlr *cntlr, uint16_t gpio, struct GpioGroup **group)
39 {
40 struct Mp1xxGpioCntlr *stm32gpio = NULL;
41 uint16_t groupIndex = Mp1xxToGroupNum(gpio);
42
43 if (cntlr == NULL || cntlr->priv == NULL) {
44 HDF_LOGE("%s: cntlr or priv is NULL", __func__);
45 return HDF_ERR_INVALID_OBJECT;
46 }
47 stm32gpio = ToMp1xxGpioCntlr(cntlr);
48 if (groupIndex >= stm32gpio->groupNum) {
49 HDF_LOGE("%s: err group index:%u", __func__, groupIndex);
50 return HDF_ERR_INVALID_PARAM;
51 }
52 *group = &stm32gpio->groups[groupIndex];
53 return HDF_SUCCESS;
54 }
55
56
Mp1xxGpioSetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t dir)57 static int32_t Mp1xxGpioSetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t dir)
58 {
59 int32_t ret;
60
61 unsigned int val;
62 volatile unsigned char *addr = NULL;
63
64 unsigned int bitNum = Mp1xxToBitNum(gpio);
65 struct GpioGroup *group = NULL;
66
67 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
68 if (ret != HDF_SUCCESS) {
69 HDF_LOGE("Mp1xxGetGroupByGpioNum failed\n");
70 return ret;
71 }
72
73 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
74 HDF_LOGE("OsalSpinLockIrqSave failed\n");
75 return HDF_ERR_DEVICE_BUSY;
76 }
77 addr = STM32MP1XX_GPIO_MODER(group->regBase);
78 val = OSAL_READL(addr);
79 if (dir == GPIO_DIR_IN) {
80 val &= ~(0X3 << (bitNum * 2)); /* bit0:1 清零 */
81 } else if (dir == GPIO_DIR_OUT) {
82 val &= ~(0X3 << (bitNum * 2)); /* bit0:1 清零 */
83 val |= (0X1 << (bitNum * 2)); /* bit0:1 设置 01 */
84 }
85 OSAL_WRITEL(val, addr);
86 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
87 return HDF_SUCCESS;
88 }
Mp1xxGpioGetDir(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * dir)89 static int32_t Mp1xxGpioGetDir(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *dir)
90 {
91 int32_t ret;
92 unsigned int val;
93 volatile unsigned char *addr = NULL;
94 unsigned int bitNum = Mp1xxToBitNum(gpio);
95 struct GpioGroup *group = NULL;
96
97 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
98 if (ret != HDF_SUCCESS) {
99 return ret;
100 }
101
102 addr = STM32MP1XX_GPIO_MODER(group->regBase);
103 val = OSAL_READL(addr);
104 if (val & (1 << (bitNum * 2))) {
105 *dir = GPIO_DIR_OUT;
106 } else {
107 *dir = GPIO_DIR_IN;
108 }
109 return HDF_SUCCESS;
110 }
Mp1xxGpioWrite(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t val)111 static int32_t Mp1xxGpioWrite(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t val)
112 {
113 int32_t ret;
114
115 unsigned int valCur;
116 unsigned int bitNum = Mp1xxToBitNum(gpio);
117 volatile unsigned char *addr = NULL;
118 struct GpioGroup *group = NULL;
119
120 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
121 if (ret != HDF_SUCCESS) {
122 return ret;
123 }
124 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
125 return HDF_ERR_DEVICE_BUSY;
126 }
127 addr = STM32MP1XX_GPIO_BSRR(group->regBase);
128 valCur = OSAL_READL(addr);
129 if (val == GPIO_VAL_LOW) {
130 valCur &= ~(0x1 << bitNum);
131 valCur |= (0x1 << (bitNum + 16));
132 } else {
133 valCur |= (0x1 << bitNum);
134 }
135 OSAL_WRITEL(valCur, addr);
136 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
137
138 return HDF_SUCCESS;
139 }
140
Mp1xxGpioRead(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t * val)141 static int32_t Mp1xxGpioRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
142 {
143 int32_t ret;
144 unsigned int valCur;
145 volatile unsigned char *addr = NULL;
146 unsigned int bitNum = Mp1xxToBitNum(gpio);
147 struct GpioGroup *group = NULL;
148
149 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
150 if (ret != HDF_SUCCESS) {
151 return ret;
152 }
153
154 addr = STM32MP1XX_GPIO_IDR(group->regBase);
155 valCur = OSAL_READL(addr);
156 if (valCur & (1 << bitNum)) {
157 *val = GPIO_VAL_HIGH;
158 } else {
159 *val = GPIO_VAL_LOW;
160 }
161 return HDF_SUCCESS;
162 }
163
IrqHandleNoShare(uint32_t irq,void * data)164 static uint32_t IrqHandleNoShare(uint32_t irq, void *data)
165 {
166 unsigned int i;
167 (void)irq;
168 struct GpioGroup *group = (struct GpioGroup *)data;
169
170 if (data == NULL) {
171 HDF_LOGW("%s: data is NULL!", __func__);
172 return HDF_ERR_INVALID_PARAM;
173 }
174 for (i = 0; i < g_Mp1xxGpioCntlr.bitNum; i++) {
175 if (__HAL_GPIO_EXTI_GET_IT(1 << i, group->exitBase) != 0) {
176 __HAL_GPIO_EXTI_CLEAR_IT(1 << i, group->exitBase);
177 GpioCntlrIrqCallback(&g_Mp1xxGpioCntlr.cntlr, Mp1xxToGpioNum(group->index, i));
178 }
179 }
180 return HDF_SUCCESS;
181 }
182
GetGpioIrqNum(uint16_t pinNum)183 static uint32_t GetGpioIrqNum(uint16_t pinNum)
184 {
185 if (pinNum > PIN_15) {
186 HDF_LOGE("%s: get gpio irq num fail!", __func__);
187 return 0;
188 }
189 switch (pinNum) {
190 case PIN_0:
191 return EXTI0_IRQn;
192 break;
193 case PIN_1:
194 return EXTI1_IRQn;
195 break;
196 case PIN_2:
197 return EXTI2_IRQn;
198 break;
199 case PIN_3:
200 return EXTI3_IRQn;
201 break;
202 case PIN_4:
203 return EXTI4_IRQn;
204 break;
205 case PIN_5:
206 return EXTI5_IRQn;
207 break;
208 case PIN_6:
209 return EXTI6_IRQn;
210 break;
211 case PIN_7:
212 return EXTI7_IRQn;
213 break;
214 case PIN_8:
215 return EXTI8_IRQn;
216 break;
217 case PIN_9:
218 return EXTI9_IRQn;
219 break;
220 case PIN_10:
221 return EXTI10_IRQn;
222 break;
223 case PIN_11:
224 return EXTI11_IRQn;
225 break;
226 case PIN_12:
227 return EXTI12_IRQn;
228 break;
229 case PIN_13:
230 return EXTI13_IRQn;
231 break;
232 case PIN_14:
233 return EXTI14_IRQn;
234 break;
235 case PIN_15:
236 return EXTI15_IRQn;
237 break;
238 default:
239 break;
240 }
241 return 0;
242 }
243
GpioRegisterGroupIrqUnsafe(uint16_t pinNum,struct GpioGroup * group)244 static int32_t GpioRegisterGroupIrqUnsafe(uint16_t pinNum, struct GpioGroup *group)
245 {
246 int ret;
247
248 ret = OsalRegisterIrq(GetGpioIrqNum(pinNum), 0, IrqHandleNoShare, "GPIO", group);
249 if (ret != 0) {
250 (void)OsalUnregisterIrq(GetGpioIrqNum(pinNum), group);
251 ret = OsalRegisterIrq(GetGpioIrqNum(pinNum), 0, IrqHandleNoShare, "GPIO", group);
252 }
253
254 if (ret != 0) {
255 HDF_LOGE("%s: irq reg fail:%d!", __func__, ret);
256 return HDF_FAILURE;
257 }
258
259 ret = OsalEnableIrq(GetGpioIrqNum(pinNum));
260 if (ret != 0) {
261 HDF_LOGE("%s: irq enable fail:%d!", __func__, ret);
262 (void)OsalUnregisterIrq(GetGpioIrqNum(pinNum), group);
263 return HDF_FAILURE;
264 }
265
266 group->irqFunc = IrqHandleNoShare;
267
268 return HDF_SUCCESS;
269 }
GpioClearIrqUnsafe(struct GpioGroup * group,uint16_t bitNum)270 static void GpioClearIrqUnsafe(struct GpioGroup *group, uint16_t bitNum)
271 {
272 __HAL_GPIO_EXTI_CLEAR_IT(bitNum, group->exitBase);
273 }
Mp1xxGpioSetIrq(struct GpioCntlr * cntlr,uint16_t gpio,uint16_t mode)274 static int32_t Mp1xxGpioSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)
275 {
276 int32_t ret = HDF_SUCCESS;
277 struct GpioGroup *group = NULL;
278 unsigned int bitNum = Mp1xxToBitNum(gpio);
279
280 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
281 if (ret != HDF_SUCCESS) {
282 return ret;
283 }
284 Mp1xxGpioSetDir(cntlr, gpio, GPIO_DIR_IN);
285
286 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
287 return HDF_ERR_DEVICE_BUSY;
288 }
289
290 EXTI_ConfigTypeDef EXTI_ConfigStructure;
291 EXTI_HandleTypeDef hexti;
292
293 EXTI_ConfigStructure.Line = EXTI_GPIO | EXTI_EVENT | EXTI_REG1 | bitNum;
294 EXTI_ConfigStructure.Trigger = mode;
295 EXTI_ConfigStructure.GPIOSel = Mp1xxToGroupNum(gpio);
296 EXTI_ConfigStructure.Mode = EXTI_MODE_C1_INTERRUPT;
297
298 HAL_EXTI_SetConfigLine(&hexti, &EXTI_ConfigStructure);
299 GpioClearIrqUnsafe(group, bitNum); // clear irq on set
300 if (group->irqFunc != NULL) {
301 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
302 HDF_LOGI("%s: group irq(%p) already registered!", __func__, group->irqFunc);
303 return HDF_SUCCESS;
304 }
305 ret = GpioRegisterGroupIrqUnsafe(bitNum, group);
306 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
307 HDF_LOGI("%s: group irq(%p) registered!", __func__, group->irqFunc);
308 return ret;
309 }
310
Mp1xxGpioUnsetIrq(struct GpioCntlr * cntlr,uint16_t gpio)311 static int32_t Mp1xxGpioUnsetIrq(struct GpioCntlr *cntlr, uint16_t gpio)
312 {
313 int32_t ret = HDF_SUCCESS;
314 (void)gpio;
315
316 if (cntlr == NULL || cntlr->priv == NULL) {
317 HDF_LOGE("%s: GpioCntlr or cntlr.priv null!", __func__);
318 return HDF_ERR_INVALID_OBJECT;
319 }
320
321 return ret;
322 }
323
Mp1xxGpioEnableIrq(struct GpioCntlr * cntlr,uint16_t gpio)324 static int32_t Mp1xxGpioEnableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
325 {
326 int32_t ret = HDF_SUCCESS;
327 struct GpioGroup *group = NULL;
328 unsigned int bitNum = Mp1xxToBitNum(gpio);
329
330 if (cntlr == NULL || cntlr->priv == NULL) {
331 HDF_LOGE("%s: GpioCntlr or cntlr.priv null!", __func__);
332 return HDF_ERR_INVALID_OBJECT;
333 }
334
335 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
336 if (ret != HDF_SUCCESS) {
337 HDF_LOGE("Mp1xxGetGroupByGpioNum failed\n");
338 return ret;
339 }
340
341 EXTI_ConfigTypeDef EXTI_ConfigStructure;
342 EXTI_HandleTypeDef hexti;
343
344 Mp1xxGpioSetDir(cntlr, gpio, GPIO_DIR_IN);
345
346 EXTI_ConfigStructure.Line = EXTI_GPIO | EXTI_EVENT | EXTI_REG1 | bitNum;
347 EXTI_ConfigStructure.Trigger = EXTI_TRIGGER_FALLING;
348 EXTI_ConfigStructure.GPIOSel = Mp1xxToGroupNum(gpio);
349 EXTI_ConfigStructure.Mode = EXTI_MODE_C1_INTERRUPT;
350
351 HAL_EXTI_SetConfigLine(&hexti, &EXTI_ConfigStructure);
352
353 return ret;
354 }
355
Mp1xxGpioDisableIrq(struct GpioCntlr * cntlr,uint16_t gpio)356 static int32_t Mp1xxGpioDisableIrq(struct GpioCntlr *cntlr, uint16_t gpio)
357 {
358 int32_t ret = HDF_SUCCESS;
359
360 if (cntlr == NULL || cntlr->priv == NULL) {
361 HDF_LOGE("%s: GpioCntlr or cntlr.priv null!", __func__);
362 return HDF_ERR_INVALID_OBJECT;
363 }
364 struct GpioGroup *group = NULL;
365
366 ret = Mp1xxGetGroupByGpioNum(cntlr, gpio, &group);
367 if (ret != HDF_SUCCESS) {
368 HDF_LOGE("Mp1xxGetGroupByGpioNum failed\n");
369 return ret;
370 }
371
372 EXTI_HandleTypeDef hexti;
373 HAL_EXTI_ClearConfigLine(&hexti);
374
375 return ret;
376 }
377 /* GpioMethod definition */
378 struct GpioMethod g_GpioMethod = {
379 .request = NULL,
380 .release = NULL,
381 .write = Mp1xxGpioWrite,
382 .read = Mp1xxGpioRead,
383 .setDir = Mp1xxGpioSetDir,
384 .getDir = Mp1xxGpioGetDir,
385 .toIrq = NULL,
386 .setIrq = Mp1xxGpioSetIrq,
387 .unsetIrq = Mp1xxGpioUnsetIrq,
388 .enableIrq = Mp1xxGpioEnableIrq,
389 .disableIrq = Mp1xxGpioDisableIrq,
390 };
391
Mp1xxGpioReadDrs(struct Mp1xxGpioCntlr * stm32gpio,const struct DeviceResourceNode * node)392 static int32_t Mp1xxGpioReadDrs(struct Mp1xxGpioCntlr *stm32gpio, const struct DeviceResourceNode *node)
393 {
394 int32_t ret;
395 struct DeviceResourceIface *drsOps = NULL;
396
397 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
398 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
399 HDF_LOGE("%s: invalid drs ops fail!", __func__);
400 return HDF_FAILURE;
401 }
402
403 ret = drsOps->GetUint32(node, "gpioRegBase", &stm32gpio->gpioPhyBase, 0);
404 if (ret != HDF_SUCCESS) {
405 HDF_LOGE("%s: read regBase fail!", __func__);
406 return ret;
407 }
408
409 ret = drsOps->GetUint32(node, "gpioRegStep", &stm32gpio->gpioRegStep, 0);
410 if (ret != HDF_SUCCESS) {
411 HDF_LOGE("%s: read gpioRegStep fail!", __func__);
412 return ret;
413 }
414
415 ret = drsOps->GetUint16(node, "groupNum", &stm32gpio->groupNum, 0);
416 if (ret != HDF_SUCCESS) {
417 HDF_LOGE("%s: read groupNum fail!", __func__);
418 return ret;
419 }
420
421 ret = drsOps->GetUint16(node, "bitNum", &stm32gpio->bitNum, 0);
422 if (ret != HDF_SUCCESS) {
423 HDF_LOGE("%s: read bitNum fail!", __func__);
424 return ret;
425 }
426
427 ret = drsOps->GetUint32(node, "irqRegBase", &stm32gpio->irqPhyBase, 0);
428 if (ret != HDF_SUCCESS) {
429 HDF_LOGE("%s: read regBase fail!", __func__);
430 return ret;
431 }
432
433 ret = drsOps->GetUint32(node, "irqRegStep", &stm32gpio->iqrRegStep, 0);
434 if (ret != HDF_SUCCESS) {
435 HDF_LOGE("%s: read gpioRegStep fail!", __func__);
436 return ret;
437 }
438 return HDF_SUCCESS;
439 }
440
InitGpioCntlrMem(struct Mp1xxGpioCntlr * cntlr)441 static int32_t InitGpioCntlrMem(struct Mp1xxGpioCntlr *cntlr)
442 {
443 size_t groupMemSize;
444 struct GpioGroup *groups = NULL;
445
446 if (cntlr == NULL) {
447 return HDF_ERR_INVALID_PARAM;
448 }
449
450 groupMemSize = sizeof(struct GpioGroup) * cntlr->groupNum;
451 groups = (struct GpioGroup *)OsalMemCalloc(groupMemSize);
452 if (groups == NULL) {
453 return HDF_ERR_MALLOC_FAIL;
454 }
455 cntlr->groups = groups;
456
457 for (uint16_t i = 0; i < cntlr->groupNum; i++) {
458 groups[i].index = i;
459 groups[i].regBase = cntlr->regBase + (i * cntlr->gpioRegStep);
460 groups[i].exitBase = cntlr->exitBase;
461 if (OsalSpinInit(&groups[i].lock) != HDF_SUCCESS) {
462 for (; i > 0; i--) {
463 (void)OsalSpinDestroy(&groups[i - 1].lock);
464 }
465 OsalMemFree(groups);
466 return HDF_FAILURE;
467 }
468 }
469 return HDF_SUCCESS;
470 }
471
ReleaseGpioCntlrMem(struct Mp1xxGpioCntlr * cntlr)472 static void ReleaseGpioCntlrMem(struct Mp1xxGpioCntlr *cntlr)
473 {
474 if (cntlr == NULL) {
475 return;
476 }
477 if (cntlr->groups != NULL) {
478 for (uint16_t i = 0; i < cntlr->groupNum; i++) {
479 (void)OsalSpinDestroy(&cntlr->groups[i].lock);
480 }
481 OsalMemFree(cntlr->groups);
482 cntlr->groups = NULL;
483 }
484 }
485
486 /* HdfDriverEntry hook function implementations */
GpioDriverBind(struct HdfDeviceObject * device)487 static int32_t GpioDriverBind(struct HdfDeviceObject *device)
488 {
489 (void)device;
490 return HDF_SUCCESS;
491 }
492
GpioDriverInit(struct HdfDeviceObject * device)493 static int32_t GpioDriverInit(struct HdfDeviceObject *device)
494 {
495 int32_t ret;
496 struct Mp1xxGpioCntlr *stm32gpio = &g_Mp1xxGpioCntlr;
497
498 dprintf("%s: Enter", __func__);
499 if (device == NULL || device->property == NULL) {
500 HDF_LOGE("%s: device or property NULL!", __func__);
501 return HDF_ERR_INVALID_OBJECT;
502 }
503 // 获取属性数据
504 ret = Mp1xxGpioReadDrs(stm32gpio, device->property);
505 if (ret != HDF_SUCCESS) {
506 HDF_LOGE("%s: get gpio device resource fail:%d", __func__, ret);
507 return ret;
508 }
509
510 if (stm32gpio->groupNum > GROUP_MAX || stm32gpio->groupNum <= 0 || stm32gpio->bitNum > BIT_MAX ||
511 stm32gpio->bitNum <= 0) {
512 HDF_LOGE("%s: invalid groupNum:%u or bitNum:%u", __func__, stm32gpio->groupNum,
513 stm32gpio->bitNum);
514 return HDF_ERR_INVALID_PARAM;
515 }
516 // 寄存器地址映射
517 stm32gpio->regBase = OsalIoRemap(stm32gpio->gpioPhyBase, stm32gpio->groupNum * stm32gpio->gpioRegStep);
518 if (stm32gpio->regBase == NULL) {
519 HDF_LOGE("%s: err remap phy:0x%x", __func__, stm32gpio->gpioPhyBase);
520 return HDF_ERR_IO;
521 }
522 /* OsalIoRemap: remap registers */
523 stm32gpio->exitBase = OsalIoRemap(stm32gpio->irqPhyBase, stm32gpio->iqrRegStep);
524 if (stm32gpio->exitBase == NULL) {
525 dprintf("%s: OsalIoRemap fail!", __func__);
526 return -1;
527 }
528
529 ret = InitGpioCntlrMem(stm32gpio);
530 if (ret != HDF_SUCCESS) {
531 HDF_LOGE("%s: err init cntlr mem:%d", __func__, ret);
532 OsalIoUnmap((void *)stm32gpio->regBase);
533 stm32gpio->regBase = NULL;
534 return ret;
535 }
536 stm32gpio->cntlr.count = stm32gpio->groupNum * stm32gpio->bitNum;
537 stm32gpio->cntlr.priv = (void *)device->property;
538 stm32gpio->cntlr.ops = &g_GpioMethod;
539 ret = GpioCntlrAdd(&stm32gpio->cntlr);
540 if (ret != HDF_SUCCESS) {
541 HDF_LOGE("%s: err add controller: %d", __func__, ret);
542 return ret;
543 }
544 HDF_LOGE("%s: dev service:%s init success!", __func__, HdfDeviceGetServiceName(device));
545 return ret;
546 }
547
GpioDriverRelease(struct HdfDeviceObject * device)548 static void GpioDriverRelease(struct HdfDeviceObject *device)
549 {
550 struct GpioCntlr *gpioCntlr = NULL;
551 struct Mp1xxGpioCntlr *stm32gpioGpioCntlr = NULL;
552
553 HDF_LOGD("%s: Enter", __func__);
554 if (device == NULL) {
555 HDF_LOGE("%s: device is null!", __func__);
556 return;
557 }
558
559 GpioCntlrRemove(gpioCntlr);
560
561 stm32gpioGpioCntlr = (struct Mp1xxGpioCntlr *)gpioCntlr;
562 ReleaseGpioCntlrMem(stm32gpioGpioCntlr);
563 OsalIoUnmap((void *)stm32gpioGpioCntlr->regBase);
564 stm32gpioGpioCntlr->regBase = NULL;
565 }
566
567 /* HdfDriverEntry definition */
568 struct HdfDriverEntry g_GpioDriverEntry = {
569 .moduleVersion = 1,
570 .moduleName = "HDF_PLATFORM_GPIO",
571 .Bind = GpioDriverBind,
572 .Init = GpioDriverInit,
573 .Release = GpioDriverRelease,
574 };
575
576 /* Init HdfDriverEntry */
577 HDF_INIT(g_GpioDriverEntry);