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