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