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