11bd4fe43Sopenharmony_ci/* 21bd4fe43Sopenharmony_ci * Copyright (c) 2021 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 "dmac_hi35xx.h" 171bd4fe43Sopenharmony_ci#include "device_resource_if.h" 181bd4fe43Sopenharmony_ci#include "dmac_core.h" 191bd4fe43Sopenharmony_ci#include "hdf_device_desc.h" 201bd4fe43Sopenharmony_ci#include "hdf_dlist.h" 211bd4fe43Sopenharmony_ci#include "hdf_log.h" 221bd4fe43Sopenharmony_ci#include "los_hw.h" 231bd4fe43Sopenharmony_ci#include "los_hwi.h" 241bd4fe43Sopenharmony_ci#include "los_vm_phys.h" 251bd4fe43Sopenharmony_ci#include "osal_io.h" 261bd4fe43Sopenharmony_ci#include "osal_mem.h" 271bd4fe43Sopenharmony_ci#include "osal_time.h" 281bd4fe43Sopenharmony_ci 291bd4fe43Sopenharmony_ci#define HDF_LOG_TAG dmac_hi35xx 301bd4fe43Sopenharmony_ci 311bd4fe43Sopenharmony_ci#ifdef __cplusplus 321bd4fe43Sopenharmony_ci#if __cplusplus 331bd4fe43Sopenharmony_ciextern "C" { 341bd4fe43Sopenharmony_ci#endif /* __cplusplus */ 351bd4fe43Sopenharmony_ci#endif /* __cplusplus */ 361bd4fe43Sopenharmony_ci 371bd4fe43Sopenharmony_cistatic struct HiDmacPeripheral g_peripheral[HIDMAC_MAX_PERIPHERALS] = { 381bd4fe43Sopenharmony_ci { 0, I2C0_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 0 }, 391bd4fe43Sopenharmony_ci { 1, I2C0_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 1 }, 401bd4fe43Sopenharmony_ci { 2, I2C1_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 2 }, 411bd4fe43Sopenharmony_ci { 3, I2C1_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 3 }, 421bd4fe43Sopenharmony_ci { 4, I2C2_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 4 }, 431bd4fe43Sopenharmony_ci { 5, I2C2_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 5 }, 441bd4fe43Sopenharmony_ci { 6, 0, HIDMAC_NOT_USE, 0, 0, 6 }, 451bd4fe43Sopenharmony_ci { 7, 0, HIDMAC_NOT_USE, 0, 0, 7 }, 461bd4fe43Sopenharmony_ci { 8, 0, HIDMAC_NOT_USE, 0, 0, 8 }, 471bd4fe43Sopenharmony_ci { 9, 0, HIDMAC_NOT_USE, 0, 0, 9 }, 481bd4fe43Sopenharmony_ci { 10, 0, HIDMAC_NOT_USE, 0, 0, 10 }, 491bd4fe43Sopenharmony_ci { 11, 0, HIDMAC_NOT_USE, 0, 0, 11 }, 501bd4fe43Sopenharmony_ci { 12, 0, HIDMAC_NOT_USE, 0, 0, 12 }, 511bd4fe43Sopenharmony_ci { 13, 0, HIDMAC_NOT_USE, 0, 0, 13 }, 521bd4fe43Sopenharmony_ci { 14, 0, HIDMAC_NOT_USE, 0, 0, 14 }, 531bd4fe43Sopenharmony_ci { 15, 0, HIDMAC_NOT_USE, 0, 0, 15 }, 541bd4fe43Sopenharmony_ci { 16, UART0_RX_ADDR, HIDMAC_HOST0, 0x47700004, PERI_MODE_8BIT, 16 }, 551bd4fe43Sopenharmony_ci { 17, UART0_TX_ADDR, HIDMAC_HOST0, 0x87700004, PERI_MODE_8BIT, 17 }, 561bd4fe43Sopenharmony_ci { 18, UART1_RX_ADDR, HIDMAC_HOST0, 0x47700004, PERI_MODE_8BIT, 18 }, 571bd4fe43Sopenharmony_ci { 19, UART1_TX_ADDR, HIDMAC_HOST0, 0x87700004, PERI_MODE_8BIT, 19 }, 581bd4fe43Sopenharmony_ci { 20, UART2_RX_ADDR, HIDMAC_HOST0, 0x47700004, PERI_MODE_8BIT, 20 }, 591bd4fe43Sopenharmony_ci { 21, UART2_TX_ADDR, HIDMAC_HOST0, 0x87700004, PERI_MODE_8BIT, 21 }, 601bd4fe43Sopenharmony_ci { 22, 0, HIDMAC_NOT_USE, 0, 0, 22 }, 611bd4fe43Sopenharmony_ci { 23, 0, HIDMAC_NOT_USE, 0, 0, 23 }, 621bd4fe43Sopenharmony_ci { 24, 0, HIDMAC_NOT_USE, 0, 0, 24 }, 631bd4fe43Sopenharmony_ci { 25, 0, HIDMAC_NOT_USE, 0, 0, 25 }, 641bd4fe43Sopenharmony_ci { 26, SPI0_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 26 }, 651bd4fe43Sopenharmony_ci { 27, SPI0_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 27 }, 661bd4fe43Sopenharmony_ci { 28, SPI1_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_16BIT, 28 }, 671bd4fe43Sopenharmony_ci { 29, SPI1_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_16BIT, 29 }, 681bd4fe43Sopenharmony_ci { 30, SPI2_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_16BIT, 30 }, 691bd4fe43Sopenharmony_ci { 31, SPI2_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_16BIT, 31 }, 701bd4fe43Sopenharmony_ci}; 711bd4fe43Sopenharmony_ci#define HIDMAC_PERIPH_ID_MAX 32 721bd4fe43Sopenharmony_ci 731bd4fe43Sopenharmony_ci#define ERROR_STATUS_NUM_0 0 741bd4fe43Sopenharmony_ci#define ERROR_STATUS_NUM_1 1 751bd4fe43Sopenharmony_ci#define ERROR_STATUS_NUM_2 2 761bd4fe43Sopenharmony_ci#define ERROR_STATUS_MAX 3 771bd4fe43Sopenharmony_ci 781bd4fe43Sopenharmony_cistatic int HiDmacIsrErrProc(struct DmaCntlr *cntlr, uint16_t chan) 791bd4fe43Sopenharmony_ci{ 801bd4fe43Sopenharmony_ci unsigned int chanErrStats[ERROR_STATUS_MAX]; 811bd4fe43Sopenharmony_ci 821bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_0] = OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR1_OFFSET); 831bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_0] = (chanErrStats[ERROR_STATUS_NUM_0] >> chan) & 0x01; 841bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_1] = OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR2_OFFSET); 851bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_1] = (chanErrStats[ERROR_STATUS_NUM_1] >> chan) & 0x01; 861bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_2] = OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR3_OFFSET); 871bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_2] = (chanErrStats[ERROR_STATUS_NUM_2] >> chan) & 0x01; 881bd4fe43Sopenharmony_ci if ((chanErrStats[ERROR_STATUS_NUM_0] | chanErrStats[ERROR_STATUS_NUM_1] | 891bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_2]) != 0) { 901bd4fe43Sopenharmony_ci HDF_LOGE("%s: Err in hidma %d finish, ERR1:0x%x, ERR2:0x%x, ERR3:0x%x", __func__, 911bd4fe43Sopenharmony_ci chan, chanErrStats[ERROR_STATUS_NUM_0], chanErrStats[ERROR_STATUS_NUM_1], 921bd4fe43Sopenharmony_ci chanErrStats[ERROR_STATUS_NUM_2]); 931bd4fe43Sopenharmony_ci OSAL_WRITEL(1 << chan, cntlr->remapBase + HIDMAC_INT_ERR1_RAW_OFFSET); 941bd4fe43Sopenharmony_ci HDF_LOGE("HIDMAC_INT_ERR1_RAW = 0x%x", OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR1_RAW_OFFSET)); 951bd4fe43Sopenharmony_ci OSAL_WRITEL(1 << chan, cntlr->remapBase + HIDMAC_INT_ERR2_RAW_OFFSET); 961bd4fe43Sopenharmony_ci HDF_LOGE("HIDMAC_INT_ERR2_RAW = 0x%x", OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR2_RAW_OFFSET)); 971bd4fe43Sopenharmony_ci OSAL_WRITEL(1 << chan, cntlr->remapBase + HIDMAC_INT_ERR3_RAW_OFFSET); 981bd4fe43Sopenharmony_ci HDF_LOGE("HIDMAC_INT_ERR3_RAW = 0x%x", OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR3_RAW_OFFSET)); 991bd4fe43Sopenharmony_ci return DMAC_CHN_ERROR; 1001bd4fe43Sopenharmony_ci } 1011bd4fe43Sopenharmony_ci return 0; 1021bd4fe43Sopenharmony_ci} 1031bd4fe43Sopenharmony_ci 1041bd4fe43Sopenharmony_cistatic int HiDmacGetChanStat(struct DmaCntlr *cntlr, uint16_t chan) 1051bd4fe43Sopenharmony_ci{ 1061bd4fe43Sopenharmony_ci int ret; 1071bd4fe43Sopenharmony_ci unsigned long chanStatus; 1081bd4fe43Sopenharmony_ci unsigned long chanTcStatus; 1091bd4fe43Sopenharmony_ci 1101bd4fe43Sopenharmony_ci chanStatus = OSAL_READL(cntlr->remapBase + HIDMAC_INT_STAT_OFFSET); 1111bd4fe43Sopenharmony_ci if ((chanStatus >> chan) & 0x1) { 1121bd4fe43Sopenharmony_ci chanTcStatus = OSAL_READL(cntlr->remapBase + HIDMAC_INT_TC1_OFFSET); 1131bd4fe43Sopenharmony_ci#ifdef DMAC_HI35XX_DEBUG 1141bd4fe43Sopenharmony_ci HDF_LOGD("%s: HIDMAC_INT_TC1 = 0x%lx, chan = %u", __func__, chanTcStatus, chan); 1151bd4fe43Sopenharmony_ci#endif 1161bd4fe43Sopenharmony_ci chanTcStatus = (chanTcStatus >> chan) & 0x1; 1171bd4fe43Sopenharmony_ci if (chanTcStatus != 0) { 1181bd4fe43Sopenharmony_ci OSAL_WRITEL(chanTcStatus << chan, cntlr->remapBase + HIDMAC_INT_TC1_RAW_OFFSET); 1191bd4fe43Sopenharmony_ci return DMAC_CHN_SUCCESS; 1201bd4fe43Sopenharmony_ci } 1211bd4fe43Sopenharmony_ci ret = HiDmacIsrErrProc(cntlr, chan); 1221bd4fe43Sopenharmony_ci if (ret != 0) { 1231bd4fe43Sopenharmony_ci HDF_LOGE("%s: fail, ret = %d", __func__, ret); 1241bd4fe43Sopenharmony_ci return DMAC_CHN_ERROR; 1251bd4fe43Sopenharmony_ci } 1261bd4fe43Sopenharmony_ci chanTcStatus = OSAL_READL(cntlr->remapBase + HIDMAC_INT_TC2_OFFSET); 1271bd4fe43Sopenharmony_ci#ifdef DMAC_HI35XX_DEBUG 1281bd4fe43Sopenharmony_ci HDF_LOGD("%s: HIDMAC_INT_TC2 = 0x%lx, chan = %u", __func__, chanTcStatus, chan); 1291bd4fe43Sopenharmony_ci#endif 1301bd4fe43Sopenharmony_ci chanTcStatus = (chanTcStatus >> chan) & 0x1; 1311bd4fe43Sopenharmony_ci if (chanTcStatus != 0) { 1321bd4fe43Sopenharmony_ci OSAL_WRITEL(chanTcStatus << chan, cntlr->remapBase + HIDMAC_INT_TC2_RAW_OFFSET); 1331bd4fe43Sopenharmony_ci } 1341bd4fe43Sopenharmony_ci } 1351bd4fe43Sopenharmony_ci return DMAC_NOT_FINISHED; 1361bd4fe43Sopenharmony_ci} 1371bd4fe43Sopenharmony_ci 1381bd4fe43Sopenharmony_cistatic unsigned int HiDmacGetPriId(uintptr_t periphAddr, int transType) 1391bd4fe43Sopenharmony_ci{ 1401bd4fe43Sopenharmony_ci unsigned int i; 1411bd4fe43Sopenharmony_ci 1421bd4fe43Sopenharmony_ci /* only check p2m and m2p */ 1431bd4fe43Sopenharmony_ci for (i = transType - 1; i < HIDMAC_MAX_PERIPHERALS; i += 2) { 1441bd4fe43Sopenharmony_ci if (g_peripheral[i].periphAddr == periphAddr) { 1451bd4fe43Sopenharmony_ci return i; 1461bd4fe43Sopenharmony_ci } 1471bd4fe43Sopenharmony_ci } 1481bd4fe43Sopenharmony_ci HDF_LOGE("%s: invalid peripheral addr", __func__); 1491bd4fe43Sopenharmony_ci return HIDMAC_PERIPH_ID_MAX; 1501bd4fe43Sopenharmony_ci} 1511bd4fe43Sopenharmony_ci 1521bd4fe43Sopenharmony_cistatic uint8_t HiDmacToLocalWitdh(uint32_t transferWitdh, uint32_t defaultWidth) 1531bd4fe43Sopenharmony_ci{ 1541bd4fe43Sopenharmony_ci switch (transferWitdh) { 1551bd4fe43Sopenharmony_ci case 0x1: 1561bd4fe43Sopenharmony_ci return PERI_MODE_8BIT; 1571bd4fe43Sopenharmony_ci case 0x2: 1581bd4fe43Sopenharmony_ci return PERI_MODE_16BIT; 1591bd4fe43Sopenharmony_ci case 0x3: 1601bd4fe43Sopenharmony_ci return PERI_MODE_32BIT; 1611bd4fe43Sopenharmony_ci case 0x4: 1621bd4fe43Sopenharmony_ci return PERI_MODE_64BIT; 1631bd4fe43Sopenharmony_ci default: 1641bd4fe43Sopenharmony_ci break; 1651bd4fe43Sopenharmony_ci } 1661bd4fe43Sopenharmony_ci return defaultWidth; 1671bd4fe43Sopenharmony_ci} 1681bd4fe43Sopenharmony_ci 1691bd4fe43Sopenharmony_cistatic int32_t HiDmacGetChanInfo(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, struct DmacMsg *msg) 1701bd4fe43Sopenharmony_ci{ 1711bd4fe43Sopenharmony_ci unsigned int periphId; 1721bd4fe43Sopenharmony_ci uint8_t localSrcWidth; 1731bd4fe43Sopenharmony_ci uint8_t localDstWidth; 1741bd4fe43Sopenharmony_ci 1751bd4fe43Sopenharmony_ci if (cntlr == NULL) { 1761bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 1771bd4fe43Sopenharmony_ci } 1781bd4fe43Sopenharmony_ci if (chanInfo == NULL || msg == NULL) { 1791bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 1801bd4fe43Sopenharmony_ci } 1811bd4fe43Sopenharmony_ci 1821bd4fe43Sopenharmony_ci if (chanInfo->transType == TRASFER_TYPE_P2M || chanInfo->transType == TRASFER_TYPE_M2P) { 1831bd4fe43Sopenharmony_ci periphId = HiDmacGetPriId(DmacMsgGetPeriphAddr(msg), chanInfo->transType); 1841bd4fe43Sopenharmony_ci if (periphId >= HIDMAC_PERIPH_ID_MAX) { 1851bd4fe43Sopenharmony_ci HDF_LOGE("%s: invalid io address", __func__); 1861bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 1871bd4fe43Sopenharmony_ci } 1881bd4fe43Sopenharmony_ci if (msg->srcWidth != msg->destWidth) { 1891bd4fe43Sopenharmony_ci HDF_LOGE("%s: src width:%u != dest width:%u", __func__, msg->srcWidth, msg->destWidth); 1901bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 1911bd4fe43Sopenharmony_ci } 1921bd4fe43Sopenharmony_ci chanInfo->srcWidth = msg->srcWidth; 1931bd4fe43Sopenharmony_ci chanInfo->destWidth = chanInfo->srcWidth; 1941bd4fe43Sopenharmony_ci localSrcWidth = HiDmacToLocalWitdh(chanInfo->srcWidth, g_peripheral[periphId].transWidth); 1951bd4fe43Sopenharmony_ci localDstWidth = localSrcWidth; 1961bd4fe43Sopenharmony_ci chanInfo->config = g_peripheral[periphId].transCfg | 1971bd4fe43Sopenharmony_ci (localSrcWidth << HIDMAC_SRC_WIDTH_OFFSET) | 1981bd4fe43Sopenharmony_ci (localDstWidth << HIDMAC_DST_WIDTH_OFFSET) | 1991bd4fe43Sopenharmony_ci (g_peripheral[periphId].dynPeripNum << HIDMAC_PERI_ID_OFFSET); 2001bd4fe43Sopenharmony_ci } 2011bd4fe43Sopenharmony_ci chanInfo->lliEnFlag = HIDMAC_LLI_ENABLE; 2021bd4fe43Sopenharmony_ci return HDF_SUCCESS; 2031bd4fe43Sopenharmony_ci} 2041bd4fe43Sopenharmony_ci 2051bd4fe43Sopenharmony_cistatic inline void HiDmacDisable(struct DmaCntlr *cntlr, uint16_t channel) 2061bd4fe43Sopenharmony_ci{ 2071bd4fe43Sopenharmony_ci if (cntlr != NULL) { 2081bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_CX_DISABLE, cntlr->remapBase + HIDMAC_CX_CFG_OFFSET(channel)); 2091bd4fe43Sopenharmony_ci } 2101bd4fe43Sopenharmony_ci} 2111bd4fe43Sopenharmony_ci 2121bd4fe43Sopenharmony_ci 2131bd4fe43Sopenharmony_ci#define HIDMAC_32BITS_MASK 0xFFFFFFFF 2141bd4fe43Sopenharmony_ci#define HIDMAC_32BITS_SHIFT 32 2151bd4fe43Sopenharmony_ci 2161bd4fe43Sopenharmony_cistatic int32_t HiDmacStartM2M(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, 2171bd4fe43Sopenharmony_ci uintptr_t psrc, uintptr_t pdst, size_t len) 2181bd4fe43Sopenharmony_ci{ 2191bd4fe43Sopenharmony_ci if (cntlr == NULL) { 2201bd4fe43Sopenharmony_ci HDF_LOGE("%s: invalid cntlr", __func__); 2211bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 2221bd4fe43Sopenharmony_ci } 2231bd4fe43Sopenharmony_ci if (chanInfo == NULL || len == 0) { 2241bd4fe43Sopenharmony_ci HDF_LOGE("%s: chanInfo null or invalid len:%zu", __func__, len); 2251bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 2261bd4fe43Sopenharmony_ci } 2271bd4fe43Sopenharmony_ci 2281bd4fe43Sopenharmony_ci OSAL_WRITEL(psrc & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_L(chanInfo->channel)); 2291bd4fe43Sopenharmony_ci#ifdef LOSCFG_AARCH64 2301bd4fe43Sopenharmony_ci OSAL_WRITEL((psrc >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK, 2311bd4fe43Sopenharmony_ci cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel)); 2321bd4fe43Sopenharmony_ci#else 2331bd4fe43Sopenharmony_ci OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel)); 2341bd4fe43Sopenharmony_ci#endif 2351bd4fe43Sopenharmony_ci 2361bd4fe43Sopenharmony_ci OSAL_WRITEL(pdst & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_L(chanInfo->channel)); 2371bd4fe43Sopenharmony_ci#ifdef LOSCFG_AARCH64 2381bd4fe43Sopenharmony_ci OSAL_WRITEL((pdst >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK, 2391bd4fe43Sopenharmony_ci cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel)); 2401bd4fe43Sopenharmony_ci#else 2411bd4fe43Sopenharmony_ci OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel)); 2421bd4fe43Sopenharmony_ci#endif 2431bd4fe43Sopenharmony_ci 2441bd4fe43Sopenharmony_ci OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_L(chanInfo->channel)); 2451bd4fe43Sopenharmony_ci OSAL_WRITEL(len, cntlr->remapBase + HIDMAC_CX_CNT0_OFFSET(chanInfo->channel)); 2461bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_CX_CFG_M2M, cntlr->remapBase + HIDMAC_CX_CFG_OFFSET(chanInfo->channel)); 2471bd4fe43Sopenharmony_ci return HDF_SUCCESS; 2481bd4fe43Sopenharmony_ci} 2491bd4fe43Sopenharmony_ci 2501bd4fe43Sopenharmony_cistatic int32_t HiDmacStartLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo) 2511bd4fe43Sopenharmony_ci{ 2521bd4fe43Sopenharmony_ci struct DmacLli *plli = NULL; 2531bd4fe43Sopenharmony_ci 2541bd4fe43Sopenharmony_ci if (cntlr == NULL) { 2551bd4fe43Sopenharmony_ci HDF_LOGE("%s: invalid cntlr", __func__); 2561bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 2571bd4fe43Sopenharmony_ci } 2581bd4fe43Sopenharmony_ci if (chanInfo == NULL || chanInfo->lli == NULL) { 2591bd4fe43Sopenharmony_ci HDF_LOGE("%s: chanInfo or lli is null", __func__); 2601bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 2611bd4fe43Sopenharmony_ci } 2621bd4fe43Sopenharmony_ci plli = chanInfo->lli; 2631bd4fe43Sopenharmony_ci 2641bd4fe43Sopenharmony_ci OSAL_WRITEL(plli->srcAddr & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_L(chanInfo->channel)); 2651bd4fe43Sopenharmony_ci#ifdef LOSCFG_AARCH64 2661bd4fe43Sopenharmony_ci OSAL_WRITEL((plli->srcAddr >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK, 2671bd4fe43Sopenharmony_ci cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel)); 2681bd4fe43Sopenharmony_ci#else 2691bd4fe43Sopenharmony_ci OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel)); 2701bd4fe43Sopenharmony_ci#endif 2711bd4fe43Sopenharmony_ci 2721bd4fe43Sopenharmony_ci OSAL_WRITEL(plli->destAddr & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_L(chanInfo->channel)); 2731bd4fe43Sopenharmony_ci#ifdef LOSCFG_AARCH64 2741bd4fe43Sopenharmony_ci OSAL_WRITEL((plli->destAddr >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK, 2751bd4fe43Sopenharmony_ci cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel)); 2761bd4fe43Sopenharmony_ci#else 2771bd4fe43Sopenharmony_ci OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel)); 2781bd4fe43Sopenharmony_ci#endif 2791bd4fe43Sopenharmony_ci 2801bd4fe43Sopenharmony_ci OSAL_WRITEL(plli->nextLli & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_L(chanInfo->channel)); 2811bd4fe43Sopenharmony_ci#ifdef LOSCFG_AARCH64 2821bd4fe43Sopenharmony_ci OSAL_WRITEL((plli->nextLli >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK, 2831bd4fe43Sopenharmony_ci cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_H(chanInfo->channel)); 2841bd4fe43Sopenharmony_ci#else 2851bd4fe43Sopenharmony_ci OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_H(chanInfo->channel)); 2861bd4fe43Sopenharmony_ci#endif 2871bd4fe43Sopenharmony_ci 2881bd4fe43Sopenharmony_ci OSAL_WRITEL(plli->count, cntlr->remapBase + HIDMAC_CX_CNT0_OFFSET(chanInfo->channel)); 2891bd4fe43Sopenharmony_ci 2901bd4fe43Sopenharmony_ci OSAL_WRITEL(plli->config | HIDMAC_CX_CFG_CHN_START, cntlr->remapBase + HIDMAC_CX_CFG_OFFSET(chanInfo->channel)); 2911bd4fe43Sopenharmony_ci return HDF_SUCCESS; 2921bd4fe43Sopenharmony_ci} 2931bd4fe43Sopenharmony_ci 2941bd4fe43Sopenharmony_cistatic uintptr_t HiDmacGetCurrDstAddr(struct DmaCntlr *cntlr, uint16_t channel) 2951bd4fe43Sopenharmony_ci{ 2961bd4fe43Sopenharmony_ci if (cntlr == NULL || channel >= HIDMAC_CHANNEL_NUM) { 2971bd4fe43Sopenharmony_ci return 0; 2981bd4fe43Sopenharmony_ci } 2991bd4fe43Sopenharmony_ci return OSAL_READL(cntlr->remapBase + HIDMAC_CX_CUR_DST_OFFSET(channel)); 3001bd4fe43Sopenharmony_ci} 3011bd4fe43Sopenharmony_ci 3021bd4fe43Sopenharmony_cistatic void HiDmacClkEn(uint16_t index) 3031bd4fe43Sopenharmony_ci{ 3041bd4fe43Sopenharmony_ci unsigned long tmp; 3051bd4fe43Sopenharmony_ci 3061bd4fe43Sopenharmony_ci if (index == 0) { 3071bd4fe43Sopenharmony_ci tmp = OSAL_READL(CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET); 3081bd4fe43Sopenharmony_ci tmp |= 1 << HIDMA0_CLK_OFFSET | 1 << HIDMA0_AXI_OFFSET; 3091bd4fe43Sopenharmony_ci OSAL_WRITEL(tmp, CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET); 3101bd4fe43Sopenharmony_ci } 3111bd4fe43Sopenharmony_ci} 3121bd4fe43Sopenharmony_ci 3131bd4fe43Sopenharmony_cistatic void HiDmacUnReset(uint16_t index) 3141bd4fe43Sopenharmony_ci{ 3151bd4fe43Sopenharmony_ci unsigned long tmp; 3161bd4fe43Sopenharmony_ci 3171bd4fe43Sopenharmony_ci if (index == 0) { 3181bd4fe43Sopenharmony_ci tmp = OSAL_READL(CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET); 3191bd4fe43Sopenharmony_ci tmp |= 1 << HIDMA0_RST_OFFSET; 3201bd4fe43Sopenharmony_ci OSAL_WRITEL(tmp, CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET); 3211bd4fe43Sopenharmony_ci 3221bd4fe43Sopenharmony_ci tmp = OSAL_READL(CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET); 3231bd4fe43Sopenharmony_ci tmp &= ~(1 << HIDMA0_RST_OFFSET); 3241bd4fe43Sopenharmony_ci OSAL_WRITEL(tmp, CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET); 3251bd4fe43Sopenharmony_ci } 3261bd4fe43Sopenharmony_ci} 3271bd4fe43Sopenharmony_ci 3281bd4fe43Sopenharmony_cistatic int32_t Hi35xxDmacInit(struct DmaCntlr *cntlr) 3291bd4fe43Sopenharmony_ci{ 3301bd4fe43Sopenharmony_ci HDF_LOGI("%s: enter", __func__); 3311bd4fe43Sopenharmony_ci 3321bd4fe43Sopenharmony_ci HiDmacClkEn(cntlr->index); 3331bd4fe43Sopenharmony_ci HiDmacUnReset(cntlr->index); 3341bd4fe43Sopenharmony_ci 3351bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_TC1_RAW_OFFSET); 3361bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_TC2_RAW_OFFSET); 3371bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_ERR1_RAW_OFFSET); 3381bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_ERR2_RAW_OFFSET); 3391bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_ERR3_RAW_OFFSET); 3401bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_TC1_MASK_OFFSET); 3411bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_TC2_MASK_OFFSET); 3421bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_ERR1_MASK_OFFSET); 3431bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_ERR2_MASK_OFFSET); 3441bd4fe43Sopenharmony_ci OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_ERR3_MASK_OFFSET); 3451bd4fe43Sopenharmony_ci return HDF_SUCCESS; 3461bd4fe43Sopenharmony_ci} 3471bd4fe43Sopenharmony_ci 3481bd4fe43Sopenharmony_cistatic uintptr_t HiDmacVaddrToPaddr(void *vaddr) 3491bd4fe43Sopenharmony_ci{ 3501bd4fe43Sopenharmony_ci return (uintptr_t)LOS_PaddrQuery(vaddr); 3511bd4fe43Sopenharmony_ci} 3521bd4fe43Sopenharmony_ci 3531bd4fe43Sopenharmony_cistatic void *HiDmacPaddrToVaddr(uintptr_t paddr) 3541bd4fe43Sopenharmony_ci{ 3551bd4fe43Sopenharmony_ci return LOS_PaddrToKVaddr((paddr_t)paddr); 3561bd4fe43Sopenharmony_ci} 3571bd4fe43Sopenharmony_ci 3581bd4fe43Sopenharmony_cistatic void HiDmacCacheInv(uintptr_t vaddr, uintptr_t vend) 3591bd4fe43Sopenharmony_ci{ 3601bd4fe43Sopenharmony_ci if (vaddr == 0 || vend == 0) { 3611bd4fe43Sopenharmony_ci return; 3621bd4fe43Sopenharmony_ci } 3631bd4fe43Sopenharmony_ci DCacheInvRange(vaddr, vend); 3641bd4fe43Sopenharmony_ci} 3651bd4fe43Sopenharmony_ci 3661bd4fe43Sopenharmony_cistatic void HiDmacCacheFlush(uintptr_t vaddr, uintptr_t vend) 3671bd4fe43Sopenharmony_ci{ 3681bd4fe43Sopenharmony_ci if (vaddr == 0 || vend == 0) { 3691bd4fe43Sopenharmony_ci return; 3701bd4fe43Sopenharmony_ci } 3711bd4fe43Sopenharmony_ci DCacheFlushRange(vaddr, vend); 3721bd4fe43Sopenharmony_ci} 3731bd4fe43Sopenharmony_ci 3741bd4fe43Sopenharmony_cistatic int32_t HiDmacParseHcs(struct DmaCntlr *cntlr, const struct DeviceResourceNode *node) 3751bd4fe43Sopenharmony_ci{ 3761bd4fe43Sopenharmony_ci int32_t ret; 3771bd4fe43Sopenharmony_ci struct DeviceResourceIface *drsOps = NULL; 3781bd4fe43Sopenharmony_ci 3791bd4fe43Sopenharmony_ci if (cntlr == NULL) { 3801bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 3811bd4fe43Sopenharmony_ci } 3821bd4fe43Sopenharmony_ci drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 3831bd4fe43Sopenharmony_ci if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) { 3841bd4fe43Sopenharmony_ci HDF_LOGE("%s: invalid drs ops", __func__); 3851bd4fe43Sopenharmony_ci return HDF_ERR_NOT_SUPPORT; 3861bd4fe43Sopenharmony_ci } 3871bd4fe43Sopenharmony_ci 3881bd4fe43Sopenharmony_ci ret = drsOps->GetUint32(node, "reg_pbase", &cntlr->phyBase, 0); 3891bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 3901bd4fe43Sopenharmony_ci HDF_LOGE("%s: read reg base fail", __func__); 3911bd4fe43Sopenharmony_ci return ret; 3921bd4fe43Sopenharmony_ci } 3931bd4fe43Sopenharmony_ci cntlr->remapBase = OsalIoRemap((unsigned long)cntlr->phyBase, (unsigned long)cntlr->regSize); 3941bd4fe43Sopenharmony_ci 3951bd4fe43Sopenharmony_ci ret = drsOps->GetUint32(node, "reg_size", &cntlr->regSize, 0); 3961bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 3971bd4fe43Sopenharmony_ci HDF_LOGE("%s: read reg size fail", __func__); 3981bd4fe43Sopenharmony_ci return ret; 3991bd4fe43Sopenharmony_ci } 4001bd4fe43Sopenharmony_ci ret = drsOps->GetUint16(node, "index", &cntlr->index, 0); 4011bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 4021bd4fe43Sopenharmony_ci HDF_LOGE("%s: read index fail", __func__); 4031bd4fe43Sopenharmony_ci return ret; 4041bd4fe43Sopenharmony_ci } 4051bd4fe43Sopenharmony_ci ret = drsOps->GetUint32(node, "irq", &cntlr->irq, 0); 4061bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 4071bd4fe43Sopenharmony_ci HDF_LOGE("%s: read irq fail", __func__); 4081bd4fe43Sopenharmony_ci return ret; 4091bd4fe43Sopenharmony_ci } 4101bd4fe43Sopenharmony_ci ret = drsOps->GetUint32(node, "max_transfer_size", &cntlr->maxTransSize, 0); 4111bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 4121bd4fe43Sopenharmony_ci HDF_LOGE("%s: read max transfer size fail", __func__); 4131bd4fe43Sopenharmony_ci return ret; 4141bd4fe43Sopenharmony_ci } 4151bd4fe43Sopenharmony_ci ret = drsOps->GetUint16(node, "channel_num", &cntlr->channelNum, 0); 4161bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 4171bd4fe43Sopenharmony_ci HDF_LOGE("%s: read channel num fail", __func__); 4181bd4fe43Sopenharmony_ci return ret; 4191bd4fe43Sopenharmony_ci } 4201bd4fe43Sopenharmony_ci HDF_LOGI("phybase:0x%x, size:0x%x, index:0x%x, irq:0x%x, max_trans_size:0x%x, chan_num:0x%x", 4211bd4fe43Sopenharmony_ci cntlr->phyBase, cntlr->regSize, cntlr->index, cntlr->irq, cntlr->maxTransSize, cntlr->channelNum); 4221bd4fe43Sopenharmony_ci return HDF_SUCCESS; 4231bd4fe43Sopenharmony_ci} 4241bd4fe43Sopenharmony_ci 4251bd4fe43Sopenharmony_cistatic int32_t HiDmacBind(struct HdfDeviceObject *device) 4261bd4fe43Sopenharmony_ci{ 4271bd4fe43Sopenharmony_ci struct DmaCntlr *cntlr = NULL; 4281bd4fe43Sopenharmony_ci 4291bd4fe43Sopenharmony_ci cntlr = DmaCntlrCreate(device); 4301bd4fe43Sopenharmony_ci if (cntlr == NULL) { 4311bd4fe43Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 4321bd4fe43Sopenharmony_ci } 4331bd4fe43Sopenharmony_ci cntlr->getChanInfo = HiDmacGetChanInfo; 4341bd4fe43Sopenharmony_ci cntlr->dmacCacheFlush = HiDmacCacheFlush; 4351bd4fe43Sopenharmony_ci cntlr->dmacCacheInv = HiDmacCacheInv; 4361bd4fe43Sopenharmony_ci cntlr->dmaChanEnable = HiDmacStartLli; 4371bd4fe43Sopenharmony_ci cntlr->dmaM2mChanEnable = HiDmacStartM2M; 4381bd4fe43Sopenharmony_ci cntlr->dmacChanDisable = HiDmacDisable; 4391bd4fe43Sopenharmony_ci cntlr->dmacVaddrToPaddr = HiDmacVaddrToPaddr; 4401bd4fe43Sopenharmony_ci cntlr->dmacPaddrToVaddr = HiDmacPaddrToVaddr; 4411bd4fe43Sopenharmony_ci cntlr->dmacGetChanStatus = HiDmacGetChanStat; 4421bd4fe43Sopenharmony_ci cntlr->dmacGetCurrDestAddr = HiDmacGetCurrDstAddr; 4431bd4fe43Sopenharmony_ci device->service = &cntlr->service; 4441bd4fe43Sopenharmony_ci return HDF_SUCCESS; 4451bd4fe43Sopenharmony_ci} 4461bd4fe43Sopenharmony_ci 4471bd4fe43Sopenharmony_cistatic int32_t HiDmacInit(struct HdfDeviceObject *device) 4481bd4fe43Sopenharmony_ci{ 4491bd4fe43Sopenharmony_ci int32_t ret; 4501bd4fe43Sopenharmony_ci struct DmaCntlr *cntlr = NULL; 4511bd4fe43Sopenharmony_ci 4521bd4fe43Sopenharmony_ci if (device == NULL || device->property == NULL) { 4531bd4fe43Sopenharmony_ci HDF_LOGE("%s: device or property null", __func__); 4541bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 4551bd4fe43Sopenharmony_ci } 4561bd4fe43Sopenharmony_ci 4571bd4fe43Sopenharmony_ci cntlr = CONTAINER_OF(device->service, struct DmaCntlr, service); 4581bd4fe43Sopenharmony_ci ret = HiDmacParseHcs(cntlr, device->property); 4591bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 4601bd4fe43Sopenharmony_ci return ret; 4611bd4fe43Sopenharmony_ci } 4621bd4fe43Sopenharmony_ci ret = Hi35xxDmacInit(cntlr); 4631bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 4641bd4fe43Sopenharmony_ci return ret; 4651bd4fe43Sopenharmony_ci } 4661bd4fe43Sopenharmony_ci return DmacCntlrAdd(cntlr); 4671bd4fe43Sopenharmony_ci} 4681bd4fe43Sopenharmony_ci 4691bd4fe43Sopenharmony_cistatic void HiDmacRelease(struct HdfDeviceObject *device) 4701bd4fe43Sopenharmony_ci{ 4711bd4fe43Sopenharmony_ci struct DmaCntlr *cntlr = NULL; 4721bd4fe43Sopenharmony_ci 4731bd4fe43Sopenharmony_ci if (device == NULL) { 4741bd4fe43Sopenharmony_ci return; 4751bd4fe43Sopenharmony_ci } 4761bd4fe43Sopenharmony_ci cntlr = CONTAINER_OF(device->service, struct DmaCntlr, service); 4771bd4fe43Sopenharmony_ci DmacCntlrRemove(cntlr); 4781bd4fe43Sopenharmony_ci DmaCntlrDestroy(cntlr); 4791bd4fe43Sopenharmony_ci} 4801bd4fe43Sopenharmony_ci 4811bd4fe43Sopenharmony_cistruct HdfDriverEntry g_hiDmacEntry = { 4821bd4fe43Sopenharmony_ci .moduleVersion = 1, 4831bd4fe43Sopenharmony_ci .Bind = HiDmacBind, 4841bd4fe43Sopenharmony_ci .Init = HiDmacInit, 4851bd4fe43Sopenharmony_ci .Release = HiDmacRelease, 4861bd4fe43Sopenharmony_ci .moduleName = "HDF_PLATFORM_DMAC", 4871bd4fe43Sopenharmony_ci}; 4881bd4fe43Sopenharmony_ciHDF_INIT(g_hiDmacEntry); 4891bd4fe43Sopenharmony_ci#ifdef __cplusplus 4901bd4fe43Sopenharmony_ci#if __cplusplus 4911bd4fe43Sopenharmony_ci} 4921bd4fe43Sopenharmony_ci#endif /* __cplusplus */ 4931bd4fe43Sopenharmony_ci#endif /* __cplusplus */ 494