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