• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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