11bd4fe43Sopenharmony_ci/*
21bd4fe43Sopenharmony_ci * Copyright (c) 2020-2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
31bd4fe43Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41bd4fe43Sopenharmony_ci * you may not use this file except in compliance with the License.
51bd4fe43Sopenharmony_ci * You may obtain a copy of the License at
61bd4fe43Sopenharmony_ci *
71bd4fe43Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81bd4fe43Sopenharmony_ci *
91bd4fe43Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101bd4fe43Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111bd4fe43Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121bd4fe43Sopenharmony_ci * See the License for the specific language governing permissions and
131bd4fe43Sopenharmony_ci * limitations under the License.
141bd4fe43Sopenharmony_ci */
151bd4fe43Sopenharmony_ci
161bd4fe43Sopenharmony_ci#include "device_resource_if.h"
171bd4fe43Sopenharmony_ci#include "gpio/gpio_core.h"
181bd4fe43Sopenharmony_ci#ifdef PL061_GPIO_USER_SUPPORT
191bd4fe43Sopenharmony_ci#include "gpio_dev.h"
201bd4fe43Sopenharmony_ci#endif
211bd4fe43Sopenharmony_ci#include "hdf_device_desc.h"
221bd4fe43Sopenharmony_ci#include "hdf_log.h"
231bd4fe43Sopenharmony_ci#include "osal_io.h"
241bd4fe43Sopenharmony_ci#include "osal_irq.h"
251bd4fe43Sopenharmony_ci#include "osal_mem.h"
261bd4fe43Sopenharmony_ci#include "osal_spinlock.h"
271bd4fe43Sopenharmony_ci#include "platform_dumper.h"
281bd4fe43Sopenharmony_ci
291bd4fe43Sopenharmony_ci#define HDF_LOG_TAG gpio_hi35xx
301bd4fe43Sopenharmony_ci#define PL061_GROUP_MAX 32
311bd4fe43Sopenharmony_ci#define PL061_BIT_MAX   16
321bd4fe43Sopenharmony_ci#define GPIO_MAX_INFO_NUM 96
331bd4fe43Sopenharmony_ci
341bd4fe43Sopenharmony_ci#define GPIO_DUMPER_NAME_PREFIX "gpio_dumper_"
351bd4fe43Sopenharmony_ci#define GPIO_DUMPER_NAME_LEN 64
361bd4fe43Sopenharmony_ci#define GPIO_DUMPER_DATAS_REGISTER_SIZE 10
371bd4fe43Sopenharmony_ci
381bd4fe43Sopenharmony_ci#define PL061_GPIO_DATA_ALL(base)   ((base) + 0x3FC)
391bd4fe43Sopenharmony_ci#define PL061_GPIO_DATA(base, bit)  ((base) + 0x000 + (1 << ((bit) + 2)))
401bd4fe43Sopenharmony_ci#define PL061_GPIO_DIR(base)        ((base) + 0x400)
411bd4fe43Sopenharmony_ci#define PL061_GPIO_IS(base)         ((base) + 0x404)
421bd4fe43Sopenharmony_ci#define PL061_GPIO_IBE(base)        ((base) + 0x408)
431bd4fe43Sopenharmony_ci#define PL061_GPIO_IEV(base)        ((base) + 0x40C)
441bd4fe43Sopenharmony_ci#define PL061_GPIO_IE(base)         ((base) + 0x410)
451bd4fe43Sopenharmony_ci#define PL061_GPIO_RIS(base)        ((base) + 0x414)
461bd4fe43Sopenharmony_ci#define PL061_GPIO_MIS(base)        ((base) + 0x418)
471bd4fe43Sopenharmony_ci#define PL061_GPIO_IC(base)         ((base) + 0x41C)
481bd4fe43Sopenharmony_ci
491bd4fe43Sopenharmony_cistruct Pl061GpioGroup {
501bd4fe43Sopenharmony_ci    struct GpioCntlr cntlr;
511bd4fe43Sopenharmony_ci    volatile unsigned char *regBase;
521bd4fe43Sopenharmony_ci    unsigned int index;
531bd4fe43Sopenharmony_ci    unsigned int irq;
541bd4fe43Sopenharmony_ci    OsalIRQHandle irqFunc;
551bd4fe43Sopenharmony_ci    OsalSpinlock lock;
561bd4fe43Sopenharmony_ci    uint32_t irqSave;
571bd4fe43Sopenharmony_ci    bool irqShare;
581bd4fe43Sopenharmony_ci    struct PlatformDumper *dumper;
591bd4fe43Sopenharmony_ci    char *dumperName;
601bd4fe43Sopenharmony_ci};
611bd4fe43Sopenharmony_ci
621bd4fe43Sopenharmony_cistruct Pl061GpioData {
631bd4fe43Sopenharmony_ci    volatile unsigned char *regBase;
641bd4fe43Sopenharmony_ci    uint32_t phyBase;
651bd4fe43Sopenharmony_ci    uint32_t regStep;
661bd4fe43Sopenharmony_ci    uint32_t irqStart;
671bd4fe43Sopenharmony_ci    uint16_t groupNum;
681bd4fe43Sopenharmony_ci    uint16_t bitNum;
691bd4fe43Sopenharmony_ci    uint8_t irqShare;
701bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *groups;
711bd4fe43Sopenharmony_ci    struct GpioInfo *gpioInfo;
721bd4fe43Sopenharmony_ci    void *priv;
731bd4fe43Sopenharmony_ci};
741bd4fe43Sopenharmony_ci
751bd4fe43Sopenharmony_cistatic struct Pl061GpioData g_pl061 = {
761bd4fe43Sopenharmony_ci    .groups = NULL,
771bd4fe43Sopenharmony_ci    .groupNum = PL061_GROUP_MAX,
781bd4fe43Sopenharmony_ci    .bitNum = PL061_BIT_MAX,
791bd4fe43Sopenharmony_ci};
801bd4fe43Sopenharmony_ci
811bd4fe43Sopenharmony_cistatic int32_t GpioDumperCreate(struct Pl061GpioGroup *group)
821bd4fe43Sopenharmony_ci{
831bd4fe43Sopenharmony_ci    struct PlatformDumper *dumper = NULL;
841bd4fe43Sopenharmony_ci    char *name = NULL;
851bd4fe43Sopenharmony_ci
861bd4fe43Sopenharmony_ci    name = (char *)OsalMemCalloc(GPIO_DUMPER_NAME_LEN);
871bd4fe43Sopenharmony_ci    if (name == NULL) {
881bd4fe43Sopenharmony_ci        HDF_LOGE("%s: alloc name fail", __func__);
891bd4fe43Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
901bd4fe43Sopenharmony_ci    }
911bd4fe43Sopenharmony_ci
921bd4fe43Sopenharmony_ci    if (snprintf_s(name, GPIO_DUMPER_NAME_LEN, GPIO_DUMPER_NAME_LEN - 1, "%s%d",
931bd4fe43Sopenharmony_ci        GPIO_DUMPER_NAME_PREFIX, group->index) < 0) {
941bd4fe43Sopenharmony_ci        HDF_LOGE("%s: snprintf_s name fail!", __func__);
951bd4fe43Sopenharmony_ci        OsalMemFree(name);
961bd4fe43Sopenharmony_ci        return HDF_ERR_IO;
971bd4fe43Sopenharmony_ci    }
981bd4fe43Sopenharmony_ci    dumper = PlatformDumperCreate(name);
991bd4fe43Sopenharmony_ci    if (dumper == NULL) {
1001bd4fe43Sopenharmony_ci        HDF_LOGE("%s: get dumper for %s fail!", __func__, name);
1011bd4fe43Sopenharmony_ci        OsalMemFree(name);
1021bd4fe43Sopenharmony_ci        return HDF_ERR_IO;
1031bd4fe43Sopenharmony_ci    }
1041bd4fe43Sopenharmony_ci    group->dumper = dumper;
1051bd4fe43Sopenharmony_ci    group->dumperName = name;
1061bd4fe43Sopenharmony_ci
1071bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
1081bd4fe43Sopenharmony_ci}
1091bd4fe43Sopenharmony_ci
1101bd4fe43Sopenharmony_cistatic void GpioDumperDump(struct Pl061GpioGroup *group)
1111bd4fe43Sopenharmony_ci{
1121bd4fe43Sopenharmony_ci    int32_t ret;
1131bd4fe43Sopenharmony_ci    struct PlatformDumperData datas[] = {
1141bd4fe43Sopenharmony_ci        {"PL061_GPIO_DIR", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_DIR(group->regBase))},
1151bd4fe43Sopenharmony_ci        {"PL061_GPIO_IS", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_IS(group->regBase))},
1161bd4fe43Sopenharmony_ci        {"PL061_GPIO_IBE", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_IBE(group->regBase))},
1171bd4fe43Sopenharmony_ci        {"PL061_GPIO_IEV", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_IEV(group->regBase))},
1181bd4fe43Sopenharmony_ci        {"PL061_GPIO_IE", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_IE(group->regBase))},
1191bd4fe43Sopenharmony_ci        {"PL061_GPIO_RIS", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_RIS(group->regBase))},
1201bd4fe43Sopenharmony_ci        {"PL061_GPIO_MIS", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_MIS(group->regBase))},
1211bd4fe43Sopenharmony_ci        {"PL061_GPIO_IC", PLATFORM_DUMPER_REGISTERB, (void *)(PL061_GPIO_IC(group->regBase))},
1221bd4fe43Sopenharmony_ci    };
1231bd4fe43Sopenharmony_ci
1241bd4fe43Sopenharmony_ci    if (group->dumper == NULL) {
1251bd4fe43Sopenharmony_ci        HDF_LOGE("%s: group dumper is NULL!", __func__);
1261bd4fe43Sopenharmony_ci        return;
1271bd4fe43Sopenharmony_ci    }
1281bd4fe43Sopenharmony_ci    ret = PlatformDumperAddDatas(group->dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData));
1291bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1301bd4fe43Sopenharmony_ci        return;
1311bd4fe43Sopenharmony_ci    }
1321bd4fe43Sopenharmony_ci    (void)PlatformDumperDump(group->dumper);
1331bd4fe43Sopenharmony_ci    (void)PlatformDumperClearDatas(group->dumper);
1341bd4fe43Sopenharmony_ci}
1351bd4fe43Sopenharmony_ci
1361bd4fe43Sopenharmony_cistatic inline void GpioDumperDestroy(struct Pl061GpioGroup *group)
1371bd4fe43Sopenharmony_ci{
1381bd4fe43Sopenharmony_ci    PlatformDumperDestroy(group->dumper);
1391bd4fe43Sopenharmony_ci    OsalMemFree(group->dumperName);
1401bd4fe43Sopenharmony_ci}
1411bd4fe43Sopenharmony_ci
1421bd4fe43Sopenharmony_cistatic int32_t Pl061GpioSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir)
1431bd4fe43Sopenharmony_ci{
1441bd4fe43Sopenharmony_ci    unsigned int val;
1451bd4fe43Sopenharmony_ci    volatile unsigned char *addr = NULL;
1461bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
1471bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
1481bd4fe43Sopenharmony_ci
1491bd4fe43Sopenharmony_ci    HDF_LOGV("%s: local:%hu, dir:%hu", __func__, local, dir);
1501bd4fe43Sopenharmony_ci
1511bd4fe43Sopenharmony_ci    if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
1521bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
1531bd4fe43Sopenharmony_ci    }
1541bd4fe43Sopenharmony_ci    addr = PL061_GPIO_DIR(group->regBase);
1551bd4fe43Sopenharmony_ci    val = OSAL_READL(addr);
1561bd4fe43Sopenharmony_ci    if (dir == GPIO_DIR_IN) {
1571bd4fe43Sopenharmony_ci        val &= ~(1 << bitNum);
1581bd4fe43Sopenharmony_ci    } else if (dir == GPIO_DIR_OUT) {
1591bd4fe43Sopenharmony_ci        val |= 1 << bitNum;
1601bd4fe43Sopenharmony_ci    }
1611bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, addr);
1621bd4fe43Sopenharmony_ci    (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
1631bd4fe43Sopenharmony_ci
1641bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
1651bd4fe43Sopenharmony_ci}
1661bd4fe43Sopenharmony_ci
1671bd4fe43Sopenharmony_cistatic int32_t Pl061GpioGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir)
1681bd4fe43Sopenharmony_ci{
1691bd4fe43Sopenharmony_ci    unsigned int val;
1701bd4fe43Sopenharmony_ci    volatile unsigned char *addr = NULL;
1711bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
1721bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
1731bd4fe43Sopenharmony_ci
1741bd4fe43Sopenharmony_ci    HDF_LOGV("%s: local:%hu", __func__, local);
1751bd4fe43Sopenharmony_ci
1761bd4fe43Sopenharmony_ci    addr = PL061_GPIO_DIR(group->regBase);
1771bd4fe43Sopenharmony_ci    val = OSAL_READL(addr);
1781bd4fe43Sopenharmony_ci    if (val & (1 << bitNum)) {
1791bd4fe43Sopenharmony_ci        *dir = GPIO_DIR_OUT;
1801bd4fe43Sopenharmony_ci    } else {
1811bd4fe43Sopenharmony_ci        *dir = GPIO_DIR_IN;
1821bd4fe43Sopenharmony_ci    }
1831bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
1841bd4fe43Sopenharmony_ci}
1851bd4fe43Sopenharmony_ci
1861bd4fe43Sopenharmony_cistatic int32_t Pl061GpioWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val)
1871bd4fe43Sopenharmony_ci{
1881bd4fe43Sopenharmony_ci    unsigned int valCur;
1891bd4fe43Sopenharmony_ci    volatile unsigned char *addr = NULL;
1901bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
1911bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
1921bd4fe43Sopenharmony_ci
1931bd4fe43Sopenharmony_ci    if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
1941bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
1951bd4fe43Sopenharmony_ci    }
1961bd4fe43Sopenharmony_ci    addr = PL061_GPIO_DATA(group->regBase, bitNum);
1971bd4fe43Sopenharmony_ci    valCur = OSAL_READL(addr);
1981bd4fe43Sopenharmony_ci    if (val == GPIO_VAL_LOW) {
1991bd4fe43Sopenharmony_ci        valCur &= ~(1 << bitNum);
2001bd4fe43Sopenharmony_ci    } else {
2011bd4fe43Sopenharmony_ci        valCur |= (1 << bitNum);
2021bd4fe43Sopenharmony_ci    }
2031bd4fe43Sopenharmony_ci    OSAL_WRITEL(valCur, addr);
2041bd4fe43Sopenharmony_ci    (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
2051bd4fe43Sopenharmony_ci
2061bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
2071bd4fe43Sopenharmony_ci}
2081bd4fe43Sopenharmony_ci
2091bd4fe43Sopenharmony_cistatic int32_t Pl061GpioRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val)
2101bd4fe43Sopenharmony_ci{
2111bd4fe43Sopenharmony_ci    unsigned int valCur;
2121bd4fe43Sopenharmony_ci    volatile unsigned char *addr = NULL;
2131bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
2141bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
2151bd4fe43Sopenharmony_ci
2161bd4fe43Sopenharmony_ci    addr = PL061_GPIO_DATA(group->regBase, bitNum);
2171bd4fe43Sopenharmony_ci    valCur = OSAL_READL(addr);
2181bd4fe43Sopenharmony_ci    if (valCur & (1 << bitNum)) {
2191bd4fe43Sopenharmony_ci        *val = GPIO_VAL_HIGH;
2201bd4fe43Sopenharmony_ci    } else {
2211bd4fe43Sopenharmony_ci        *val = GPIO_VAL_LOW;
2221bd4fe43Sopenharmony_ci    }
2231bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
2241bd4fe43Sopenharmony_ci}
2251bd4fe43Sopenharmony_ci
2261bd4fe43Sopenharmony_cistatic uint32_t Pl061IrqHandleShare(uint32_t irq, void *data)
2271bd4fe43Sopenharmony_ci{
2281bd4fe43Sopenharmony_ci    (void)irq;
2291bd4fe43Sopenharmony_ci    (void)data;
2301bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
2311bd4fe43Sopenharmony_ci}
2321bd4fe43Sopenharmony_ci
2331bd4fe43Sopenharmony_cistatic uint32_t Pl061IrqHandleNoShare(uint32_t irq, void *data)
2341bd4fe43Sopenharmony_ci{
2351bd4fe43Sopenharmony_ci    unsigned int i;
2361bd4fe43Sopenharmony_ci    unsigned int val;
2371bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)data;
2381bd4fe43Sopenharmony_ci
2391bd4fe43Sopenharmony_ci    if (data == NULL) {
2401bd4fe43Sopenharmony_ci        HDF_LOGW("%s: data is NULL!", __func__);
2411bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
2421bd4fe43Sopenharmony_ci    }
2431bd4fe43Sopenharmony_ci    val = OSAL_READL(PL061_GPIO_MIS(group->regBase));
2441bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, PL061_GPIO_IC(group->regBase));
2451bd4fe43Sopenharmony_ci    if (val == 0) {
2461bd4fe43Sopenharmony_ci        HDF_LOGW("%s: share irq(%u) trigerred but not hit any, mis=%x", __func__, irq, val);
2471bd4fe43Sopenharmony_ci        GpioDumperDump(group);
2481bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2491bd4fe43Sopenharmony_ci    }
2501bd4fe43Sopenharmony_ci    for (i = 0; i < group->cntlr.count && val != 0; i++, val >>= 1) {
2511bd4fe43Sopenharmony_ci        if ((val & 0x1) != 0) {
2521bd4fe43Sopenharmony_ci            GpioCntlrIrqCallback(&group->cntlr, i);
2531bd4fe43Sopenharmony_ci        }
2541bd4fe43Sopenharmony_ci    }
2551bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
2561bd4fe43Sopenharmony_ci}
2571bd4fe43Sopenharmony_ci
2581bd4fe43Sopenharmony_cistatic int32_t Pl061GpioRegisterGroupIrqUnsafe(struct Pl061GpioGroup *group)
2591bd4fe43Sopenharmony_ci{
2601bd4fe43Sopenharmony_ci    int ret;
2611bd4fe43Sopenharmony_ci    if (group->irqShare == 1) {
2621bd4fe43Sopenharmony_ci        ret = OsalRegisterIrq(group->irq, 0, Pl061IrqHandleShare, "GPIO", NULL);
2631bd4fe43Sopenharmony_ci        if (ret != 0) {
2641bd4fe43Sopenharmony_ci            HDF_LOGE("%s: share irq:%u reg fail:%d!", __func__, group->irq, ret);
2651bd4fe43Sopenharmony_ci            return HDF_FAILURE;
2661bd4fe43Sopenharmony_ci        }
2671bd4fe43Sopenharmony_ci        group->irqFunc = Pl061IrqHandleShare;
2681bd4fe43Sopenharmony_ci    } else {
2691bd4fe43Sopenharmony_ci        ret = OsalRegisterIrq(group->irq, 0, Pl061IrqHandleNoShare, "GPIO", group);
2701bd4fe43Sopenharmony_ci        if (ret != 0) {
2711bd4fe43Sopenharmony_ci            (void)OsalUnregisterIrq(group->irq, group);
2721bd4fe43Sopenharmony_ci            ret = OsalRegisterIrq(group->irq, 0, Pl061IrqHandleNoShare, "GPIO", group);
2731bd4fe43Sopenharmony_ci        }
2741bd4fe43Sopenharmony_ci        if (ret != 0) {
2751bd4fe43Sopenharmony_ci            HDF_LOGE("%s: noshare irq:%u reg fail:%d!", __func__, group->irq, ret);
2761bd4fe43Sopenharmony_ci            GpioDumperDump(group);
2771bd4fe43Sopenharmony_ci            return HDF_FAILURE;
2781bd4fe43Sopenharmony_ci        }
2791bd4fe43Sopenharmony_ci        ret = OsalEnableIrq(group->irq);
2801bd4fe43Sopenharmony_ci        if (ret != 0) {
2811bd4fe43Sopenharmony_ci            HDF_LOGE("%s: noshare irq:%u enable fail:%d!", __func__, group->irq, ret);
2821bd4fe43Sopenharmony_ci            (void)OsalUnregisterIrq(group->irq, group);
2831bd4fe43Sopenharmony_ci            GpioDumperDump(group);
2841bd4fe43Sopenharmony_ci            return HDF_FAILURE;
2851bd4fe43Sopenharmony_ci        }
2861bd4fe43Sopenharmony_ci        group->irqFunc = Pl061IrqHandleNoShare;
2871bd4fe43Sopenharmony_ci    }
2881bd4fe43Sopenharmony_ci
2891bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
2901bd4fe43Sopenharmony_ci}
2911bd4fe43Sopenharmony_ci
2921bd4fe43Sopenharmony_cistatic void Pl061GpioClearIrqUnsafe(struct Pl061GpioGroup *group, uint16_t bitNum)
2931bd4fe43Sopenharmony_ci{
2941bd4fe43Sopenharmony_ci    unsigned int val;
2951bd4fe43Sopenharmony_ci
2961bd4fe43Sopenharmony_ci    val = OSAL_READL(PL061_GPIO_IC(group->regBase));
2971bd4fe43Sopenharmony_ci    val |= 1 << bitNum;
2981bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, PL061_GPIO_IC(group->regBase));
2991bd4fe43Sopenharmony_ci}
3001bd4fe43Sopenharmony_ci
3011bd4fe43Sopenharmony_cistatic void Pl061GpioSetIrqEnableUnsafe(struct Pl061GpioGroup *group, uint16_t bitNum, int flag)
3021bd4fe43Sopenharmony_ci{
3031bd4fe43Sopenharmony_ci    unsigned int val;
3041bd4fe43Sopenharmony_ci    volatile unsigned char *addr = NULL;
3051bd4fe43Sopenharmony_ci
3061bd4fe43Sopenharmony_ci    addr = PL061_GPIO_IE(group->regBase);
3071bd4fe43Sopenharmony_ci    val = OSAL_READL(addr);
3081bd4fe43Sopenharmony_ci    if (flag == 1) {
3091bd4fe43Sopenharmony_ci        val |= (1 << bitNum);
3101bd4fe43Sopenharmony_ci    } else {
3111bd4fe43Sopenharmony_ci        val &= ~(1 << bitNum);
3121bd4fe43Sopenharmony_ci    }
3131bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, addr);
3141bd4fe43Sopenharmony_ci}
3151bd4fe43Sopenharmony_ci
3161bd4fe43Sopenharmony_cistatic int32_t Pl061GpioEnableIrq(struct GpioCntlr *cntlr, uint16_t local)
3171bd4fe43Sopenharmony_ci{
3181bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
3191bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
3201bd4fe43Sopenharmony_ci
3211bd4fe43Sopenharmony_ci    if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
3221bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
3231bd4fe43Sopenharmony_ci    }
3241bd4fe43Sopenharmony_ci    Pl061GpioSetIrqEnableUnsafe(group, bitNum, 1);
3251bd4fe43Sopenharmony_ci    (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
3261bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
3271bd4fe43Sopenharmony_ci}
3281bd4fe43Sopenharmony_ci
3291bd4fe43Sopenharmony_cistatic int32_t Pl061GpioDisableIrq(struct GpioCntlr *cntlr, uint16_t local)
3301bd4fe43Sopenharmony_ci{
3311bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
3321bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
3331bd4fe43Sopenharmony_ci
3341bd4fe43Sopenharmony_ci    if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
3351bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
3361bd4fe43Sopenharmony_ci    }
3371bd4fe43Sopenharmony_ci    Pl061GpioSetIrqEnableUnsafe(group, bitNum, 0);
3381bd4fe43Sopenharmony_ci    (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
3391bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
3401bd4fe43Sopenharmony_ci}
3411bd4fe43Sopenharmony_ci
3421bd4fe43Sopenharmony_cistatic void Pl061GpioSetIrqTypeUnsafe(struct Pl061GpioGroup *group, uint16_t bitNum, uint16_t mode)
3431bd4fe43Sopenharmony_ci{
3441bd4fe43Sopenharmony_ci    unsigned int gpioIbe;
3451bd4fe43Sopenharmony_ci    unsigned int gpioIs;
3461bd4fe43Sopenharmony_ci    unsigned int gpioIev;
3471bd4fe43Sopenharmony_ci
3481bd4fe43Sopenharmony_ci    if (mode == 0) {
3491bd4fe43Sopenharmony_ci        return;
3501bd4fe43Sopenharmony_ci    }
3511bd4fe43Sopenharmony_ci
3521bd4fe43Sopenharmony_ci    gpioIs = OSAL_READL(PL061_GPIO_IS(group->regBase));
3531bd4fe43Sopenharmony_ci    gpioIev = OSAL_READL(PL061_GPIO_IEV(group->regBase));
3541bd4fe43Sopenharmony_ci
3551bd4fe43Sopenharmony_ci    if ((mode & (OSAL_IRQF_TRIGGER_LOW | OSAL_IRQF_TRIGGER_HIGH)) != 0) {
3561bd4fe43Sopenharmony_ci        gpioIs |= 1 << bitNum;
3571bd4fe43Sopenharmony_ci        if ((mode & OSAL_IRQF_TRIGGER_HIGH) != 0) {
3581bd4fe43Sopenharmony_ci            gpioIev |= 1 << bitNum;
3591bd4fe43Sopenharmony_ci        } else {
3601bd4fe43Sopenharmony_ci            gpioIev &= ~(1 << bitNum);
3611bd4fe43Sopenharmony_ci        }
3621bd4fe43Sopenharmony_ci    } else {
3631bd4fe43Sopenharmony_ci        gpioIbe = OSAL_READL(PL061_GPIO_IBE(group->regBase));
3641bd4fe43Sopenharmony_ci        gpioIs &= ~(1 << bitNum);
3651bd4fe43Sopenharmony_ci        if (((mode & OSAL_IRQF_TRIGGER_RISING) != 0) && ((mode & OSAL_IRQF_TRIGGER_FALLING) != 0)) {
3661bd4fe43Sopenharmony_ci            gpioIbe |= 1 << bitNum;
3671bd4fe43Sopenharmony_ci        } else if ((mode & OSAL_IRQF_TRIGGER_RISING) != 0) {
3681bd4fe43Sopenharmony_ci            gpioIbe &= ~(1 << bitNum);
3691bd4fe43Sopenharmony_ci            gpioIev |= 1 << bitNum;
3701bd4fe43Sopenharmony_ci        } else if ((mode & OSAL_IRQF_TRIGGER_FALLING) != 0) {
3711bd4fe43Sopenharmony_ci            gpioIbe &= ~(1 << bitNum);
3721bd4fe43Sopenharmony_ci            gpioIev &= ~(1 << bitNum);
3731bd4fe43Sopenharmony_ci        }
3741bd4fe43Sopenharmony_ci        OSAL_WRITEL(gpioIbe, PL061_GPIO_IBE(group->regBase));
3751bd4fe43Sopenharmony_ci    }
3761bd4fe43Sopenharmony_ci    OSAL_WRITEL(gpioIs, PL061_GPIO_IS(group->regBase));
3771bd4fe43Sopenharmony_ci    OSAL_WRITEL(gpioIev, PL061_GPIO_IEV(group->regBase));
3781bd4fe43Sopenharmony_ci}
3791bd4fe43Sopenharmony_ci
3801bd4fe43Sopenharmony_cistatic int32_t Pl061GpioSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode)
3811bd4fe43Sopenharmony_ci{
3821bd4fe43Sopenharmony_ci    int32_t ret;
3831bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
3841bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
3851bd4fe43Sopenharmony_ci
3861bd4fe43Sopenharmony_ci    if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
3871bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
3881bd4fe43Sopenharmony_ci    }
3891bd4fe43Sopenharmony_ci    Pl061GpioSetIrqTypeUnsafe(group, bitNum, mode);
3901bd4fe43Sopenharmony_ci    Pl061GpioSetIrqEnableUnsafe(group, bitNum, 0); // disable irq on set
3911bd4fe43Sopenharmony_ci    Pl061GpioClearIrqUnsafe(group, bitNum);        // clear irq on set
3921bd4fe43Sopenharmony_ci
3931bd4fe43Sopenharmony_ci    if (group->irqFunc != NULL) {
3941bd4fe43Sopenharmony_ci        (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
3951bd4fe43Sopenharmony_ci        HDF_LOGI("%s: group irq(%u) already registered!", __func__, group->irq);
3961bd4fe43Sopenharmony_ci        return HDF_SUCCESS;
3971bd4fe43Sopenharmony_ci    }
3981bd4fe43Sopenharmony_ci    ret = Pl061GpioRegisterGroupIrqUnsafe(group);
3991bd4fe43Sopenharmony_ci    (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
4001bd4fe43Sopenharmony_ci    HDF_LOGI("%s: group irq(%u) registered!", __func__, group->irq);
4011bd4fe43Sopenharmony_ci    return ret;
4021bd4fe43Sopenharmony_ci}
4031bd4fe43Sopenharmony_ci
4041bd4fe43Sopenharmony_cistatic int32_t Pl061GpioUnsetIrq(struct GpioCntlr *cntlr, uint16_t local)
4051bd4fe43Sopenharmony_ci{
4061bd4fe43Sopenharmony_ci    unsigned int bitNum = local;
4071bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = (struct Pl061GpioGroup *)cntlr;
4081bd4fe43Sopenharmony_ci
4091bd4fe43Sopenharmony_ci    if (OsalSpinLockIrqSave(&group->lock, &group->irqSave) != HDF_SUCCESS) {
4101bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
4111bd4fe43Sopenharmony_ci    }
4121bd4fe43Sopenharmony_ci    Pl061GpioSetIrqEnableUnsafe(group, bitNum, 0); // disable irq when unset
4131bd4fe43Sopenharmony_ci    Pl061GpioClearIrqUnsafe(group, bitNum);        // clear irq when unset
4141bd4fe43Sopenharmony_ci    (void)OsalSpinUnlockIrqRestore(&group->lock, &group->irqSave);
4151bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4161bd4fe43Sopenharmony_ci}
4171bd4fe43Sopenharmony_ci
4181bd4fe43Sopenharmony_cistatic struct GpioMethod g_method = {
4191bd4fe43Sopenharmony_ci    .request = NULL,
4201bd4fe43Sopenharmony_ci    .release = NULL,
4211bd4fe43Sopenharmony_ci    .write = Pl061GpioWrite,
4221bd4fe43Sopenharmony_ci    .read = Pl061GpioRead,
4231bd4fe43Sopenharmony_ci    .setDir = Pl061GpioSetDir,
4241bd4fe43Sopenharmony_ci    .getDir = Pl061GpioGetDir,
4251bd4fe43Sopenharmony_ci    .toIrq = NULL,
4261bd4fe43Sopenharmony_ci    .setIrq = Pl061GpioSetIrq,
4271bd4fe43Sopenharmony_ci    .unsetIrq = Pl061GpioUnsetIrq,
4281bd4fe43Sopenharmony_ci    .enableIrq = Pl061GpioEnableIrq,
4291bd4fe43Sopenharmony_ci    .disableIrq = Pl061GpioDisableIrq,
4301bd4fe43Sopenharmony_ci};
4311bd4fe43Sopenharmony_ci
4321bd4fe43Sopenharmony_cistatic int32_t Pl061GpioInitGroups(struct Pl061GpioData *pl061)
4331bd4fe43Sopenharmony_ci{
4341bd4fe43Sopenharmony_ci    int32_t ret;
4351bd4fe43Sopenharmony_ci    uint16_t i;
4361bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *groups = NULL;
4371bd4fe43Sopenharmony_ci
4381bd4fe43Sopenharmony_ci    if (pl061 == NULL) {
4391bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
4401bd4fe43Sopenharmony_ci    }
4411bd4fe43Sopenharmony_ci
4421bd4fe43Sopenharmony_ci    groups = (struct Pl061GpioGroup *)OsalMemCalloc(sizeof(*groups) * pl061->groupNum);
4431bd4fe43Sopenharmony_ci    if (groups == NULL) {
4441bd4fe43Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
4451bd4fe43Sopenharmony_ci    }
4461bd4fe43Sopenharmony_ci    pl061->groups = groups;
4471bd4fe43Sopenharmony_ci
4481bd4fe43Sopenharmony_ci    for (i = 0; i < pl061->groupNum; i++) {
4491bd4fe43Sopenharmony_ci        groups[i].index = i;
4501bd4fe43Sopenharmony_ci        groups[i].regBase = pl061->regBase + i * pl061->regStep;
4511bd4fe43Sopenharmony_ci        groups[i].irq = pl061->irqStart + i;
4521bd4fe43Sopenharmony_ci        groups[i].irqShare = pl061->irqShare;
4531bd4fe43Sopenharmony_ci        groups[i].cntlr.start = i * pl061->bitNum;
4541bd4fe43Sopenharmony_ci        groups[i].cntlr.count = pl061->bitNum;
4551bd4fe43Sopenharmony_ci        groups[i].cntlr.ops = &g_method;
4561bd4fe43Sopenharmony_ci        groups[i].cntlr.ginfos = &pl061->gpioInfo[i * pl061->bitNum];
4571bd4fe43Sopenharmony_ci
4581bd4fe43Sopenharmony_ci        if ((ret = OsalSpinInit(&groups[i].lock)) != HDF_SUCCESS) {
4591bd4fe43Sopenharmony_ci            goto ERR_EXIT;
4601bd4fe43Sopenharmony_ci        }
4611bd4fe43Sopenharmony_ci
4621bd4fe43Sopenharmony_ci        ret =  GpioCntlrAdd(&groups[i].cntlr);
4631bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
4641bd4fe43Sopenharmony_ci            HDF_LOGE("%s: err add controller(%hu:%hu):%d", __func__,
4651bd4fe43Sopenharmony_ci                groups[i].cntlr.start, groups[i].cntlr.count, ret);
4661bd4fe43Sopenharmony_ci            (void)OsalSpinDestroy(&groups[i].lock);
4671bd4fe43Sopenharmony_ci            goto ERR_EXIT;
4681bd4fe43Sopenharmony_ci        }
4691bd4fe43Sopenharmony_ci        ret = GpioDumperCreate(&pl061->groups[i]);
4701bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
4711bd4fe43Sopenharmony_ci            HDF_LOGE("%s: create dumper failed:%d", __func__, ret);
4721bd4fe43Sopenharmony_ci            return ret;
4731bd4fe43Sopenharmony_ci        }
4741bd4fe43Sopenharmony_ci    }
4751bd4fe43Sopenharmony_ci
4761bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4771bd4fe43Sopenharmony_ci
4781bd4fe43Sopenharmony_ciERR_EXIT:
4791bd4fe43Sopenharmony_ci    while (i-- > 0) {
4801bd4fe43Sopenharmony_ci        GpioCntlrRemove(&groups[i].cntlr);
4811bd4fe43Sopenharmony_ci        (void)OsalSpinDestroy(&groups[i].lock);
4821bd4fe43Sopenharmony_ci    }
4831bd4fe43Sopenharmony_ci    pl061->groups = NULL;
4841bd4fe43Sopenharmony_ci    OsalMemFree(groups);
4851bd4fe43Sopenharmony_ci    return ret;
4861bd4fe43Sopenharmony_ci}
4871bd4fe43Sopenharmony_ci
4881bd4fe43Sopenharmony_cistatic void Pl061GpioUninitGroups(struct Pl061GpioData *pl061)
4891bd4fe43Sopenharmony_ci{
4901bd4fe43Sopenharmony_ci    uint16_t i;
4911bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = NULL;
4921bd4fe43Sopenharmony_ci
4931bd4fe43Sopenharmony_ci    for (i = 0; i < pl061->groupNum; i++) {
4941bd4fe43Sopenharmony_ci        group = &pl061->groups[i];
4951bd4fe43Sopenharmony_ci        GpioDumperDestroy(&pl061->groups[i]);
4961bd4fe43Sopenharmony_ci        GpioCntlrRemove(&group->cntlr);
4971bd4fe43Sopenharmony_ci    }
4981bd4fe43Sopenharmony_ci
4991bd4fe43Sopenharmony_ci    OsalMemFree(pl061->groups);
5001bd4fe43Sopenharmony_ci    pl061->groups = NULL;
5011bd4fe43Sopenharmony_ci}
5021bd4fe43Sopenharmony_ci
5031bd4fe43Sopenharmony_cistatic int32_t Pl061GpioReadInfo(struct Pl061GpioData *pl061, const struct DeviceResourceNode *node,
5041bd4fe43Sopenharmony_ci    struct DeviceResourceIface *drsOps)
5051bd4fe43Sopenharmony_ci{
5061bd4fe43Sopenharmony_ci    int32_t ret;
5071bd4fe43Sopenharmony_ci    uint32_t gpioIndex = 0;
5081bd4fe43Sopenharmony_ci    const struct DeviceResourceNode *childNode = NULL;
5091bd4fe43Sopenharmony_ci    const char *tempName = NULL;
5101bd4fe43Sopenharmony_ci
5111bd4fe43Sopenharmony_ci    DEV_RES_NODE_FOR_EACH_CHILD_NODE(node, childNode) {
5121bd4fe43Sopenharmony_ci        if (gpioIndex >= GPIO_MAX_INFO_NUM) {
5131bd4fe43Sopenharmony_ci            break;
5141bd4fe43Sopenharmony_ci        }
5151bd4fe43Sopenharmony_ci        ret = drsOps->GetString(childNode, "gpioCustomName", &tempName, "");
5161bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
5171bd4fe43Sopenharmony_ci            HDF_LOGW("%s: failed to read gpioCustomName!", __func__);
5181bd4fe43Sopenharmony_ci        }
5191bd4fe43Sopenharmony_ci        ret = strcpy_s(pl061->gpioInfo[gpioIndex].name, GPIO_NAME_LEN, tempName);
5201bd4fe43Sopenharmony_ci        if (ret != EOK) {
5211bd4fe43Sopenharmony_ci            HDF_LOGE("%s: failed to copy name for gpioInfo name:%d", __func__, ret);
5221bd4fe43Sopenharmony_ci            return HDF_ERR_IO;
5231bd4fe43Sopenharmony_ci        }
5241bd4fe43Sopenharmony_ci
5251bd4fe43Sopenharmony_ci        gpioIndex++;
5261bd4fe43Sopenharmony_ci    }
5271bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
5281bd4fe43Sopenharmony_ci}
5291bd4fe43Sopenharmony_ci
5301bd4fe43Sopenharmony_cistatic int32_t Pl061GpioReadDrs(struct Pl061GpioData *pl061, const struct DeviceResourceNode *node)
5311bd4fe43Sopenharmony_ci{
5321bd4fe43Sopenharmony_ci    int32_t ret;
5331bd4fe43Sopenharmony_ci    struct DeviceResourceIface *drsOps = NULL;
5341bd4fe43Sopenharmony_ci
5351bd4fe43Sopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
5361bd4fe43Sopenharmony_ci    if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL ||
5371bd4fe43Sopenharmony_ci        drsOps->GetUint8 == NULL || drsOps->GetUint8 == NULL || drsOps->GetString == NULL) {
5381bd4fe43Sopenharmony_ci        HDF_LOGE("%s: invalid drs ops!", __func__);
5391bd4fe43Sopenharmony_ci        return HDF_FAILURE;
5401bd4fe43Sopenharmony_ci    }
5411bd4fe43Sopenharmony_ci
5421bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "regBase", &pl061->phyBase, 0);
5431bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5441bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read regBase!", __func__);
5451bd4fe43Sopenharmony_ci        return ret;
5461bd4fe43Sopenharmony_ci    }
5471bd4fe43Sopenharmony_ci
5481bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "regStep", &pl061->regStep, 0);
5491bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5501bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read regStep!", __func__);
5511bd4fe43Sopenharmony_ci        return ret;
5521bd4fe43Sopenharmony_ci    }
5531bd4fe43Sopenharmony_ci
5541bd4fe43Sopenharmony_ci    ret = drsOps->GetUint16(node, "groupNum", &pl061->groupNum, 0);
5551bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5561bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read groupNum!", __func__);
5571bd4fe43Sopenharmony_ci        return ret;
5581bd4fe43Sopenharmony_ci    }
5591bd4fe43Sopenharmony_ci
5601bd4fe43Sopenharmony_ci    ret = drsOps->GetUint16(node, "bitNum", &pl061->bitNum, 0);
5611bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5621bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read bitNum!", __func__);
5631bd4fe43Sopenharmony_ci        return ret;
5641bd4fe43Sopenharmony_ci    }
5651bd4fe43Sopenharmony_ci
5661bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "irqStart", &pl061->irqStart, 0);
5671bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5681bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read irqStart!", __func__);
5691bd4fe43Sopenharmony_ci        return ret;
5701bd4fe43Sopenharmony_ci    }
5711bd4fe43Sopenharmony_ci
5721bd4fe43Sopenharmony_ci    ret = drsOps->GetUint8(node, "irqShare", &pl061->irqShare, 0);
5731bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5741bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read irqShare!", __func__);
5751bd4fe43Sopenharmony_ci        return ret;
5761bd4fe43Sopenharmony_ci    }
5771bd4fe43Sopenharmony_ci
5781bd4fe43Sopenharmony_ci    ret = Pl061GpioReadInfo(pl061, node, drsOps);
5791bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5801bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read info!", __func__);
5811bd4fe43Sopenharmony_ci        return ret;
5821bd4fe43Sopenharmony_ci    }
5831bd4fe43Sopenharmony_ci
5841bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
5851bd4fe43Sopenharmony_ci}
5861bd4fe43Sopenharmony_ci
5871bd4fe43Sopenharmony_cistatic void Pl061GpioDebug(const struct Pl061GpioData *pl061)
5881bd4fe43Sopenharmony_ci{
5891bd4fe43Sopenharmony_ci#ifdef PL061_GPIO_DEBUG
5901bd4fe43Sopenharmony_ci    uint16_t i;
5911bd4fe43Sopenharmony_ci    struct Pl061GpioGroup *group = NULL;
5921bd4fe43Sopenharmony_ci
5931bd4fe43Sopenharmony_ci    HDF_LOGI("%s:groupNum:%hu, bitNum:%hu", __func__, pl061->groupNum, pl061->bitNum);
5941bd4fe43Sopenharmony_ci    for (i = 0; i < pl061->groupNum; i++) {
5951bd4fe43Sopenharmony_ci        group = &pl061->groups[i];
5961bd4fe43Sopenharmony_ci        HDF_LOGI("group[%hu]: index:%u, regBase:0x%x, irq:%u(cntlr:%hu:%hu)",
5971bd4fe43Sopenharmony_ci            i, group->index, group->regBase, group->irq, group->cntlr.start, group->cntlr.count);
5981bd4fe43Sopenharmony_ci    }
5991bd4fe43Sopenharmony_ci#else
6001bd4fe43Sopenharmony_ci    (void)pl061;
6011bd4fe43Sopenharmony_ci#endif
6021bd4fe43Sopenharmony_ci}
6031bd4fe43Sopenharmony_ci
6041bd4fe43Sopenharmony_cistatic int32_t Pl061GpioBind(struct HdfDeviceObject *device)
6051bd4fe43Sopenharmony_ci{
6061bd4fe43Sopenharmony_ci    (void)device;
6071bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6081bd4fe43Sopenharmony_ci}
6091bd4fe43Sopenharmony_ci
6101bd4fe43Sopenharmony_cistatic int32_t Pl061GpioInit(struct HdfDeviceObject *device)
6111bd4fe43Sopenharmony_ci{
6121bd4fe43Sopenharmony_ci    int32_t ret;
6131bd4fe43Sopenharmony_ci    struct Pl061GpioData *pl061 = &g_pl061;
6141bd4fe43Sopenharmony_ci
6151bd4fe43Sopenharmony_ci    if (device == NULL || device->property == NULL) {
6161bd4fe43Sopenharmony_ci        HDF_LOGE("%s: device or property null!", __func__);
6171bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
6181bd4fe43Sopenharmony_ci    }
6191bd4fe43Sopenharmony_ci
6201bd4fe43Sopenharmony_ci    pl061->gpioInfo = OsalMemCalloc(sizeof(struct GpioInfo) * GPIO_MAX_INFO_NUM);
6211bd4fe43Sopenharmony_ci    if (pl061->gpioInfo == NULL) {
6221bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to calloc gpioInfo!", __func__);
6231bd4fe43Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
6241bd4fe43Sopenharmony_ci    }
6251bd4fe43Sopenharmony_ci
6261bd4fe43Sopenharmony_ci    ret = Pl061GpioReadDrs(pl061, device->property);
6271bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6281bd4fe43Sopenharmony_ci        HDF_LOGE("%s: failed to read drs:%d", __func__, ret);
6291bd4fe43Sopenharmony_ci        return ret;
6301bd4fe43Sopenharmony_ci    }
6311bd4fe43Sopenharmony_ci
6321bd4fe43Sopenharmony_ci    if (pl061->groupNum > PL061_GROUP_MAX || pl061->groupNum <= 0 ||
6331bd4fe43Sopenharmony_ci        pl061->bitNum > PL061_BIT_MAX || pl061->bitNum <= 0) {
6341bd4fe43Sopenharmony_ci        HDF_LOGE("%s: err groupNum:%hu, bitNum:%hu", __func__, pl061->groupNum, pl061->bitNum);
6351bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
6361bd4fe43Sopenharmony_ci    }
6371bd4fe43Sopenharmony_ci
6381bd4fe43Sopenharmony_ci    pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);
6391bd4fe43Sopenharmony_ci    if (pl061->regBase == NULL) {
6401bd4fe43Sopenharmony_ci        HDF_LOGE("%s: err remap phy:0x%x", __func__, pl061->phyBase);
6411bd4fe43Sopenharmony_ci        return HDF_ERR_IO;
6421bd4fe43Sopenharmony_ci    }
6431bd4fe43Sopenharmony_ci
6441bd4fe43Sopenharmony_ci    ret = Pl061GpioInitGroups(pl061);
6451bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6461bd4fe43Sopenharmony_ci        HDF_LOGE("%s: err init groups:%d", __func__, ret);
6471bd4fe43Sopenharmony_ci        OsalIoUnmap((void *)pl061->regBase);
6481bd4fe43Sopenharmony_ci        pl061->regBase = NULL;
6491bd4fe43Sopenharmony_ci        return ret;
6501bd4fe43Sopenharmony_ci    }
6511bd4fe43Sopenharmony_ci    pl061->priv = (void *)device->property;
6521bd4fe43Sopenharmony_ci    device->priv = (void *)pl061;
6531bd4fe43Sopenharmony_ci    Pl061GpioDebug(pl061);
6541bd4fe43Sopenharmony_ci
6551bd4fe43Sopenharmony_ci#ifdef PL061_GPIO_USER_SUPPORT
6561bd4fe43Sopenharmony_ci    if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) {
6571bd4fe43Sopenharmony_ci        HDF_LOGE("%s: add vfs fail!", __func__);
6581bd4fe43Sopenharmony_ci    }
6591bd4fe43Sopenharmony_ci#endif
6601bd4fe43Sopenharmony_ci    HDF_LOGI("%s: dev service:%s init success!", __func__, HdfDeviceGetServiceName(device));
6611bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6621bd4fe43Sopenharmony_ci}
6631bd4fe43Sopenharmony_ci
6641bd4fe43Sopenharmony_cistatic void Pl061GpioRelease(struct HdfDeviceObject *device)
6651bd4fe43Sopenharmony_ci{
6661bd4fe43Sopenharmony_ci    struct Pl061GpioData *pl061 = NULL;
6671bd4fe43Sopenharmony_ci
6681bd4fe43Sopenharmony_ci    HDF_LOGI("%s: enter", __func__);
6691bd4fe43Sopenharmony_ci    if (device == NULL) {
6701bd4fe43Sopenharmony_ci        HDF_LOGE("%s: device is null!", __func__);
6711bd4fe43Sopenharmony_ci        return;
6721bd4fe43Sopenharmony_ci    }
6731bd4fe43Sopenharmony_ci
6741bd4fe43Sopenharmony_ci#ifdef PL061_GPIO_USER_SUPPORT
6751bd4fe43Sopenharmony_ci    GpioRemoveVfs();
6761bd4fe43Sopenharmony_ci#endif
6771bd4fe43Sopenharmony_ci
6781bd4fe43Sopenharmony_ci    pl061 = (struct Pl061GpioData *)device->priv;
6791bd4fe43Sopenharmony_ci    if (pl061 == NULL) {
6801bd4fe43Sopenharmony_ci        HDF_LOGE("%s: device priv is null", __func__);
6811bd4fe43Sopenharmony_ci        return;
6821bd4fe43Sopenharmony_ci    }
6831bd4fe43Sopenharmony_ci
6841bd4fe43Sopenharmony_ci    Pl061GpioUninitGroups(pl061);
6851bd4fe43Sopenharmony_ci    OsalMemFree(pl061->gpioInfo);
6861bd4fe43Sopenharmony_ci    pl061->gpioInfo = NULL;
6871bd4fe43Sopenharmony_ci    OsalIoUnmap((void *)pl061->regBase);
6881bd4fe43Sopenharmony_ci    pl061->regBase = NULL;
6891bd4fe43Sopenharmony_ci}
6901bd4fe43Sopenharmony_ci
6911bd4fe43Sopenharmony_cistruct HdfDriverEntry g_gpioDriverEntry = {
6921bd4fe43Sopenharmony_ci    .moduleVersion = 1,
6931bd4fe43Sopenharmony_ci    .Bind = Pl061GpioBind,
6941bd4fe43Sopenharmony_ci    .Init = Pl061GpioInit,
6951bd4fe43Sopenharmony_ci    .Release = Pl061GpioRelease,
6961bd4fe43Sopenharmony_ci    .moduleName = "hisi_pl061_driver",
6971bd4fe43Sopenharmony_ci};
6981bd4fe43Sopenharmony_ciHDF_INIT(g_gpioDriverEntry);
699