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