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