1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 "device_resource_if.h"
17 #include "gpio/gpio_core.h"
18 #ifdef PL061_GPIO_USER_SUPPORT
19 #include "gpio_dev.h"
20 #endif
21 #include "hdf_device_desc.h"
22 #include "hdf_log.h"
23 #include "osal_io.h"
24 #include "osal_irq.h"
25 #include "osal_mem.h"
26 #include "osal_spinlock.h"
27
28 #define HDF_LOG_TAG gpio_hi35xx
29 #define PL061_GROUP_MAX 32
30 #define PL061_BIT_MAX 16
31
32 #define PL061_GPIO_DATA_ALL(base) ((base) + 0x3FC)
33 #define PL061_GPIO_DATA(base, bit) ((base) + 0x000 + (1 << ((bit) + 2)))
34 #define PL061_GPIO_DIR(base) ((base) + 0x400)
35 #define PL061_GPIO_IS(base) ((base) + 0x404)
36 #define PL061_GPIO_IBE(base) ((base) + 0x408)
37 #define PL061_GPIO_IEV(base) ((base) + 0x40C)
38 #define PL061_GPIO_IE(base) ((base) + 0x410)
39 #define PL061_GPIO_RIS(base) ((base) + 0x414)
40 #define PL061_GPIO_MIS(base) ((base) + 0x418)
41 #define PL061_GPIO_IC(base) ((base) + 0x41C)
42
43 struct Pl061GpioGroup {
44 struct GpioCntlr cntlr;
45 volatile unsigned char *regBase;
46 unsigned int index;
47 unsigned int irq;
48 OsalIRQHandle irqFunc;
49 OsalSpinlock lock;
50 uint32_t irqSave;
51 bool irqShare;
52 };
53
54 struct Pl061GpioData {
55 volatile unsigned char *regBase;
56 uint32_t phyBase;
57 uint32_t regStep;
58 uint32_t irqStart;
59 uint16_t groupNum;
60 uint16_t bitNum;
61 uint8_t irqShare;
62 struct Pl061GpioGroup *groups;
63 void *priv;
64 };
65
66 static struct Pl061GpioData g_pl061 = {
67 .groups = NULL,
68 .groupNum = PL061_GROUP_MAX,
69 .bitNum = PL061_BIT_MAX,
70 };
71
Pl061GpioRegDump(struct Pl061GpioGroup * group)72 static void Pl061GpioRegDump(struct Pl061GpioGroup *group)
73 {
74 PLAT_LOGI("%s: GROUP-%u: DATA-%x DIR-%x, IS-%x, IBE-%x, IEV-%x, IE-%x, RIS-%x, MIS-%x, IC-%x",
75 __func__, group->index,
76 OSAL_READL(PL061_GPIO_DATA_ALL(group->regBase)),
77 OSAL_READL(PL061_GPIO_DIR(group->regBase)),
78 OSAL_READL(PL061_GPIO_IS(group->regBase)),
79 OSAL_READL(PL061_GPIO_IBE(group->regBase)),
80 OSAL_READL(PL061_GPIO_IEV(group->regBase)),
81 OSAL_READL(PL061_GPIO_IE(group->regBase)),
82 OSAL_READL(PL061_GPIO_RIS(group->regBase)),
83 OSAL_READL(PL061_GPIO_MIS(group->regBase)),
84 OSAL_READL(PL061_GPIO_IC(group->regBase))
85 );
86 }
87
Pl061GpioSetDir(struct GpioCntlr * cntlr,uint16_t local,uint16_t dir)88 static int32_t Pl061GpioSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir)
89 {
90 unsigned int val;
91 volatile unsigned char *addr = NULL;
92 unsigned int bitNum = local;
93 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
94
95 PLAT_LOGV("%s: local:%u, dir:%u", __func__, local, dir);
96
97 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
98 return HDF_ERR_DEVICE_BUSY;
99 }
100 addr = PL061_GPIO_DIR(group->regBase);
101 val = OSAL_READL(addr);
102 if (dir == GPIO_DIR_IN) {
103 val &= ~(1 << bitNum);
104 } else if (dir == GPIO_DIR_OUT) {
105 val |= 1 << bitNum;
106 }
107 OSAL_WRITEL(val, addr);
108 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
109
110 return HDF_SUCCESS;
111 }
112
Pl061GpioGetDir(struct GpioCntlr * cntlr,uint16_t local,uint16_t * dir)113 static int32_t Pl061GpioGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir)
114 {
115 unsigned int val;
116 volatile unsigned char *addr = NULL;
117 unsigned int bitNum = local;
118 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
119
120 PLAT_LOGV("%s: local:%u", __func__, local);
121
122 addr = PL061_GPIO_DIR(group->regBase);
123 val = OSAL_READL(addr);
124 if (val & (1 << bitNum)) {
125 *dir = GPIO_DIR_OUT;
126 } else {
127 *dir = GPIO_DIR_IN;
128 }
129 return HDF_SUCCESS;
130 }
131
Pl061GpioWrite(struct GpioCntlr * cntlr,uint16_t local,uint16_t val)132 static int32_t Pl061GpioWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val)
133 {
134 unsigned int valCur;
135 volatile unsigned char *addr = NULL;
136 unsigned int bitNum = local;
137 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
138
139 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
140 return HDF_ERR_DEVICE_BUSY;
141 }
142 addr = PL061_GPIO_DATA(group->regBase, bitNum);
143 valCur = OSAL_READL(addr);
144 if (val == GPIO_VAL_LOW) {
145 valCur &= ~(1 << bitNum);
146 } else {
147 valCur |= (1 << bitNum);
148 }
149 OSAL_WRITEL(valCur, addr);
150 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
151
152 return HDF_SUCCESS;
153 }
154
Pl061GpioRead(struct GpioCntlr * cntlr,uint16_t local,uint16_t * val)155 static int32_t Pl061GpioRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val)
156 {
157 unsigned int valCur;
158 volatile unsigned char *addr = NULL;
159 unsigned int bitNum = local;
160 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
161
162 addr = PL061_GPIO_DATA(group->regBase, bitNum);
163 valCur = OSAL_READL(addr);
164 if (valCur & (1 << bitNum)) {
165 *val = GPIO_VAL_HIGH;
166 } else {
167 *val = GPIO_VAL_LOW;
168 }
169 return HDF_SUCCESS;
170 }
171
Pl061IrqHandleShare(uint32_t irq,void * data)172 static uint32_t Pl061IrqHandleShare(uint32_t irq, void *data)
173 {
174 (void)irq;
175 (void)data;
176 return HDF_SUCCESS;
177 }
178
Pl061IrqHandleNoShare(uint32_t irq,void * data)179 static uint32_t Pl061IrqHandleNoShare(uint32_t irq, void *data)
180 {
181 unsigned int i;
182 unsigned int val;
183 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)data;
184
185 PLAT_LOGV("%s: >>>>>>>>>>>>enter irq-%u<<<<<<<<<<<<<<<", __func__, irq);
186 if (data == NULL) {
187 PLAT_LOGW("%s: data is NULL!", __func__);
188 return HDF_ERR_INVALID_PARAM;
189 }
190 val = OSAL_READL(PL061_GPIO_MIS(group->regBase));
191 OSAL_WRITEL(val, PL061_GPIO_IC(group->regBase));
192 if (val == 0) {
193 PLAT_LOGW("%s: share irq(%u) trigerred but not hit any, mis=%x", __func__, irq, val);
194 Pl061GpioRegDump(group);
195 return HDF_FAILURE;
196 }
197 for (i = 0; i < group->cntlr.count && val != 0; i++, val >>= 1) {
198 if ((val & 0x1) != 0) {
199 GpioCntlrIrqCallback(&group->cntlr, i);
200 }
201 }
202 return HDF_SUCCESS;
203 }
204
Pl061GpioRegisterGroupIrqUnsafe(struct Pl061GpioGroup * group)205 static int32_t Pl061GpioRegisterGroupIrqUnsafe(struct Pl061GpioGroup *group)
206 {
207 int ret;
208 if (group->irqShare == 1) {
209 ret = OsalRegisterIrq(group->irq, 0, Pl061IrqHandleShare, "GPIO", NULL);
210 if (ret != 0) {
211 PLAT_LOGE("%s: share irq:%u reg fail:%d!", __func__, group->irq, ret);
212 return HDF_FAILURE;
213 }
214 group->irqFunc = Pl061IrqHandleShare;
215 } else {
216 ret = OsalRegisterIrq(group->irq, 0, Pl061IrqHandleNoShare, "GPIO", group);
217 if (ret != 0) {
218 (void)OsalUnregisterIrq(group->irq, group);
219 ret = OsalRegisterIrq(group->irq, 0, Pl061IrqHandleNoShare, "GPIO", group);
220 }
221 if (ret != 0) {
222 PLAT_LOGE("%s: noshare irq:%u reg fail:%d!", __func__, group->irq, ret);
223 return HDF_FAILURE;
224 }
225 ret = OsalEnableIrq(group->irq);
226 if (ret != 0) {
227 PLAT_LOGE("%s: noshare irq:%u enable fail:%d!", __func__, group->irq, ret);
228 (void)OsalUnregisterIrq(group->irq, group);
229 return HDF_FAILURE;
230 }
231 group->irqFunc = Pl061IrqHandleNoShare;
232 }
233
234 return HDF_SUCCESS;
235 }
236
Pl061GpioClearIrqUnsafe(struct Pl061GpioGroup * group,uint16_t bitNum)237 static void Pl061GpioClearIrqUnsafe(struct Pl061GpioGroup *group, uint16_t bitNum)
238 {
239 unsigned int val;
240
241 val = OSAL_READL(PL061_GPIO_IC(group->regBase));
242 val |= 1 << bitNum;
243 OSAL_WRITEL(val, PL061_GPIO_IC(group->regBase));
244 }
245
Pl061GpioSetIrqEnableUnsafe(struct Pl061GpioGroup * group,uint16_t bitNum,int flag)246 static void Pl061GpioSetIrqEnableUnsafe(struct Pl061GpioGroup *group, uint16_t bitNum, int flag)
247 {
248 unsigned int val;
249 volatile unsigned char *addr = NULL;
250
251 addr = PL061_GPIO_IE(group->regBase);
252 val = OSAL_READL(addr);
253 if (flag == 1) {
254 val |= (1 << bitNum);
255 } else {
256 val &= ~(1 << bitNum);
257 }
258 OSAL_WRITEL(val, addr);
259 }
260
Pl061GpioEnableIrq(struct GpioCntlr * cntlr,uint16_t local)261 static int32_t Pl061GpioEnableIrq(struct GpioCntlr *cntlr, uint16_t local)
262 {
263 unsigned int bitNum = local;
264 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
265
266 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
267 return HDF_ERR_DEVICE_BUSY;
268 }
269 Pl061GpioSetIrqEnableUnsafe(group, bitNum, 1);
270 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
271 return HDF_SUCCESS;
272 }
273
Pl061GpioDisableIrq(struct GpioCntlr * cntlr,uint16_t local)274 static int32_t Pl061GpioDisableIrq(struct GpioCntlr *cntlr, uint16_t local)
275 {
276 unsigned int bitNum = local;
277 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
278
279 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
280 return HDF_ERR_DEVICE_BUSY;
281 }
282 Pl061GpioSetIrqEnableUnsafe(group, bitNum, 0);
283 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
284 return HDF_SUCCESS;
285 }
286
Pl061GpioSetIrqTypeUnsafe(struct Pl061GpioGroup * group,uint16_t bitNum,uint16_t mode)287 static void Pl061GpioSetIrqTypeUnsafe(struct Pl061GpioGroup *group, uint16_t bitNum, uint16_t mode)
288 {
289 unsigned int gpioIbe;
290 unsigned int gpioIs;
291 unsigned int gpioIev;
292
293 if (mode == 0) {
294 return;
295 }
296
297 gpioIs = OSAL_READL(PL061_GPIO_IS(group->regBase));
298 gpioIev = OSAL_READL(PL061_GPIO_IEV(group->regBase));
299
300 if ((mode & (OSAL_IRQF_TRIGGER_LOW | OSAL_IRQF_TRIGGER_HIGH)) != 0) {
301 gpioIs |= 1 << bitNum;
302 if ((mode & OSAL_IRQF_TRIGGER_HIGH) != 0) {
303 gpioIev |= 1 << bitNum;
304 } else {
305 gpioIev &= ~(1 << bitNum);
306 }
307 } else {
308 gpioIbe = OSAL_READL(PL061_GPIO_IBE(group->regBase));
309 gpioIs &= ~(1 << bitNum);
310 if (((mode & OSAL_IRQF_TRIGGER_RISING) != 0) && ((mode & OSAL_IRQF_TRIGGER_FALLING) != 0)) {
311 gpioIbe |= 1 << bitNum;
312 } else if ((mode & OSAL_IRQF_TRIGGER_RISING) != 0) {
313 gpioIbe &= ~(1 << bitNum);
314 gpioIev |= 1 << bitNum;
315 } else if ((mode & OSAL_IRQF_TRIGGER_FALLING) != 0) {
316 gpioIbe &= ~(1 << bitNum);
317 gpioIev &= ~(1 << bitNum);
318 }
319 OSAL_WRITEL(gpioIbe, PL061_GPIO_IBE(group->regBase));
320 }
321 OSAL_WRITEL(gpioIs, PL061_GPIO_IS(group->regBase));
322 OSAL_WRITEL(gpioIev, PL061_GPIO_IEV(group->regBase));
323 }
324
Pl061GpioSetIrq(struct GpioCntlr * cntlr,uint16_t local,uint16_t mode)325 static int32_t Pl061GpioSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode)
326 {
327 int32_t ret;
328 unsigned int bitNum = local;
329 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
330
331 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
332 return HDF_ERR_DEVICE_BUSY;
333 }
334 Pl061GpioSetIrqTypeUnsafe(group, bitNum, mode);
335 Pl061GpioSetIrqEnableUnsafe(group, bitNum, 0); // disable irq on set
336 Pl061GpioClearIrqUnsafe(group, bitNum); // clear irq on set
337
338 if (group->irqFunc != NULL) {
339 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
340 PLAT_LOGI("%s: group irq(%u@%p) already registered!", __func__, group->irq, group->irqFunc);
341 return HDF_SUCCESS;
342 }
343 ret = Pl061GpioRegisterGroupIrqUnsafe(group);
344 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
345 PLAT_LOGI("%s: group irq(%u@%p) registered!", __func__, group->irq, group->irqFunc);
346 return ret;
347 }
348
Pl061GpioUnsetIrq(struct GpioCntlr * cntlr,uint16_t local)349 static int32_t Pl061GpioUnsetIrq(struct GpioCntlr *cntlr, uint16_t local)
350 {
351 unsigned int bitNum = local;
352 struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
353
354 if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
355 return HDF_ERR_DEVICE_BUSY;
356 }
357 Pl061GpioSetIrqEnableUnsafe(group, bitNum, 0); // disable irq when unset
358 Pl061GpioClearIrqUnsafe(group, bitNum); // clear irq when unset
359 (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
360 return HDF_SUCCESS;
361 }
362
363 static struct GpioMethod g_method = {
364 .request = NULL,
365 .release = NULL,
366 .write = Pl061GpioWrite,
367 .read = Pl061GpioRead,
368 .setDir = Pl061GpioSetDir,
369 .getDir = Pl061GpioGetDir,
370 .toIrq = NULL,
371 .setIrq = Pl061GpioSetIrq,
372 .unsetIrq = Pl061GpioUnsetIrq,
373 .enableIrq = Pl061GpioEnableIrq,
374 .disableIrq = Pl061GpioDisableIrq,
375 };
376
Pl061GpioInitGroups(struct Pl061GpioData * pl061)377 static int32_t Pl061GpioInitGroups(struct Pl061GpioData *pl061)
378 {
379 int32_t ret;
380 uint16_t i;
381 struct Pl061GpioGroup *groups = NULL;
382
383 if (pl061 == NULL) {
384 return HDF_ERR_INVALID_PARAM;
385 }
386
387 groups = (struct Pl061GpioGroup *)OsalMemCalloc(sizeof(*groups) * pl061->groupNum);
388 if (groups == NULL) {
389 return HDF_ERR_MALLOC_FAIL;
390 }
391 pl061->groups = groups;
392
393 for (i = 0; i < pl061->groupNum; i++) {
394 groups[i].index = i;
395 groups[i].regBase = pl061->regBase + i * pl061->regStep;
396 groups[i].irq = pl061->irqStart + i;
397 groups[i].irqShare = pl061->irqShare;
398 groups[i].cntlr.start = i * pl061->bitNum;
399 groups[i].cntlr.count = pl061->bitNum;
400 groups[i].cntlr.ops = &g_method;
401 if ((ret = OsalSpinInit(&groups[i].lock)) != HDF_SUCCESS) {
402 goto ERR_EXIT;
403 }
404 if ((ret = GpioCntlrAdd(&groups[i].cntlr)) != HDF_SUCCESS) {
405 PLAT_LOGE("%s: err add controller(%u:%u):%d", __func__,
406 groups[i].cntlr.start, groups[i].cntlr.count, ret);
407 (void)OsalSpinDestroy(&groups[i].lock);
408 goto ERR_EXIT;
409 }
410 }
411
412 return HDF_SUCCESS;
413
414 ERR_EXIT:
415 while (i-- > 0) {
416 GpioCntlrRemove(&groups[i].cntlr);
417 (void)OsalSpinDestroy(&groups[i].lock);
418 }
419 pl061->groups = NULL;
420 OsalMemFree(groups);
421
422 return ret;
423 }
424
Pl061GpioUninitGroups(struct Pl061GpioData * pl061)425 static void Pl061GpioUninitGroups(struct Pl061GpioData *pl061)
426 {
427 uint16_t i;
428 struct Pl061GpioGroup *group = NULL;
429
430 for (i = 0; i < pl061->groupNum; i++) {
431 group = &pl061->groups[i];
432 GpioCntlrRemove(&group->cntlr);
433 }
434 OsalMemFree(pl061->groups);
435 pl061->groups = NULL;
436 }
437
Pl061GpioReadDrs(struct Pl061GpioData * pl061,const struct DeviceResourceNode * node)438 static int32_t Pl061GpioReadDrs(struct Pl061GpioData *pl061, const struct DeviceResourceNode *node)
439 {
440 int32_t ret;
441 struct DeviceResourceIface *drsOps = NULL;
442
443 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
444 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
445 PLAT_LOGE("%s: invalid drs ops fail!", __func__);
446 return HDF_FAILURE;
447 }
448
449 ret = drsOps->GetUint32(node, "regBase", &pl061->phyBase, 0);
450 if (ret != HDF_SUCCESS) {
451 PLAT_LOGE("%s: read regBase fail!", __func__);
452 return ret;
453 }
454
455 ret = drsOps->GetUint32(node, "regStep", &pl061->regStep, 0);
456 if (ret != HDF_SUCCESS) {
457 PLAT_LOGE("%s: read regStep fail!", __func__);
458 return ret;
459 }
460
461 ret = drsOps->GetUint16(node, "groupNum", &pl061->groupNum, 0);
462 if (ret != HDF_SUCCESS) {
463 PLAT_LOGE("%s: read groupNum fail!", __func__);
464 return ret;
465 }
466
467 ret = drsOps->GetUint16(node, "bitNum", &pl061->bitNum, 0);
468 if (ret != HDF_SUCCESS) {
469 PLAT_LOGE("%s: read bitNum fail!", __func__);
470 return ret;
471 }
472
473 ret = drsOps->GetUint32(node, "irqStart", &pl061->irqStart, 0);
474 if (ret != HDF_SUCCESS) {
475 PLAT_LOGE("%s: read irqStart fail!", __func__);
476 return ret;
477 }
478
479 ret = drsOps->GetUint8(node, "irqShare", &pl061->irqShare, 0);
480 if (ret != HDF_SUCCESS) {
481 PLAT_LOGE("%s: read irqShare fail!", __func__);
482 return ret;
483 }
484
485 return HDF_SUCCESS;
486 }
487
Pl061GpioDebug(const struct Pl061GpioData * pl061)488 static void Pl061GpioDebug(const struct Pl061GpioData *pl061)
489 {
490 #ifdef PL061_GPIO_DEBUG
491 uint16_t i;
492 struct Pl061GpioGroup *group = NULL;
493
494 PLAT_LOGI("%s:pl061:%p, groupNum:%u, bitNum:%u", __func__,
495 pl061, pl061->groupNum, pl061->bitNum);
496 for (i = 0; i < pl061->groupNum; i++) {
497 group = &pl061->groups[i];
498 PLAT_LOGD("group[%u]: index:%u, regBase:0x%x, irq:%u(cntlr:%u:%u)",
499 i, group->index, group->regBase, group->irq, group->cntlr.start, group->cntlr.count);
500 }
501 #else
502 (void)pl061;
503 #endif
504 }
505
Pl061GpioBind(struct HdfDeviceObject * device)506 static int32_t Pl061GpioBind(struct HdfDeviceObject *device)
507 {
508 (void)device;
509 return HDF_SUCCESS;
510 }
511
Pl061GpioInit(struct HdfDeviceObject * device)512 static int32_t Pl061GpioInit(struct HdfDeviceObject *device)
513 {
514 int32_t ret;
515 struct Pl061GpioData *pl061 = &g_pl061;
516
517 PLAT_LOGI("%s: Enter", __func__);
518 if (device == NULL || device->property == NULL) {
519 PLAT_LOGE("%s: device or property null!", __func__);
520 return HDF_ERR_INVALID_OBJECT;
521 }
522
523 ret = Pl061GpioReadDrs(pl061, device->property);
524 if (ret != HDF_SUCCESS) {
525 PLAT_LOGE("%s: read drs fail:%d", __func__, ret);
526 return ret;
527 }
528
529 if (pl061->groupNum > PL061_GROUP_MAX || pl061->groupNum <= 0 ||
530 pl061->bitNum > PL061_BIT_MAX || pl061->bitNum <= 0) {
531 PLAT_LOGE("%s: err groupNum:%u, bitNum:%u", __func__, pl061->groupNum, pl061->bitNum);
532 return HDF_ERR_INVALID_PARAM;
533 }
534
535 pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);
536 if (pl061->regBase == NULL) {
537 PLAT_LOGE("%s: err remap phy:0x%x", __func__, pl061->phyBase);
538 return HDF_ERR_IO;
539 }
540
541 ret = Pl061GpioInitGroups(pl061);
542 if (ret != HDF_SUCCESS) {
543 PLAT_LOGE("%s: err init groups:%d", __func__, ret);
544 OsalIoUnmap((void *)pl061->regBase);
545 pl061->regBase = NULL;
546 return ret;
547 }
548 pl061->priv = (void *)device->property;
549 device->priv = (void *)pl061;
550 Pl061GpioDebug(pl061);
551
552 #ifdef PL061_GPIO_USER_SUPPORT
553 if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) {
554 PLAT_LOGE("%s: add vfs fail!", __func__);
555 }
556 #endif
557 PLAT_LOGI("%s: dev service:%s init success!", __func__, HdfDeviceGetServiceName(device));
558 return HDF_SUCCESS;
559 }
560
Pl061GpioRelease(struct HdfDeviceObject * device)561 static void Pl061GpioRelease(struct HdfDeviceObject *device)
562 {
563 struct Pl061GpioData *pl061 = NULL;
564
565 if (device == NULL) {
566 PLAT_LOGE("%s: device is null!", __func__);
567 return;
568 }
569
570 #ifdef PL061_GPIO_USER_SUPPORT
571 GpioRemoveVfs();
572 #endif
573
574 pl061 = (struct Pl061GpioData *)device->priv;
575 if (pl061 == NULL) {
576 PLAT_LOGE("%s: device priv is null", __func__);
577 return;
578 }
579
580 Pl061GpioUninitGroups(pl061);
581 OsalIoUnmap((void *)pl061->regBase);
582 pl061->regBase = NULL;
583 }
584
585 struct HdfDriverEntry g_gpioDriverEntry = {
586 .moduleVersion = 1,
587 .Bind = Pl061GpioBind,
588 .Init = Pl061GpioInit,
589 .Release = Pl061GpioRelease,
590 .moduleName = "hisi_pl061_driver",
591 };
592 HDF_INIT(g_gpioDriverEntry);
593