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