2022-11-10 22:22:48 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
|
|
|
|
* All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
|
|
|
|
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
|
|
|
|
* either version 1.0 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
* See the Phytium Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* FilePath: fpcie_dma.c
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Date: 2022-08-10 14:55:11
|
|
|
|
|
* LastEditTime: 2022-08-18 08:57:38
|
|
|
|
|
* Description: This file is for pcie dma implementation.
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*
|
|
|
|
|
* Modify History:
|
|
|
|
|
* Ver Who Date Changes
|
|
|
|
|
* ----- ------ -------- --------------------------------------
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* 1.0 huanghe 2022/8/18 init commit
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "fpcie_hw.h"
|
|
|
|
|
#include "fpcie_dma.h"
|
|
|
|
|
#include "fpcie.h"
|
|
|
|
|
#include "ftypes.h"
|
|
|
|
|
#include "fcache.h"
|
|
|
|
|
#include "fkernel.h"
|
2023-05-11 10:25:21 +08:00
|
|
|
|
#include "fdebug.h"
|
2022-11-10 22:22:48 +08:00
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
|
|
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
|
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
|
|
2023-05-11 10:25:21 +08:00
|
|
|
|
|
2022-11-10 22:22:48 +08:00
|
|
|
|
#define FPCIE_DMA_DEBUG_TAG "FPCIE_DMA"
|
|
|
|
|
#define FPCIE_DMA_ERROR(format, ...) FT_DEBUG_PRINT_E(FPCIE_DMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FPCIE_DMA_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FPCIE_DMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FPCIE_DMA_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FPCIE_DMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FPCIE_DMA_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FPCIE_DMA_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPcieDmaDescSet
|
|
|
|
|
* @msg: PCIE DMA descriptor group packet
|
|
|
|
|
* @param {uintptr} axi_addr is memory address
|
|
|
|
|
* @param {uintptr} bar_addr is Base Address Register value
|
|
|
|
|
* @param {u32} length want to send byte length
|
|
|
|
|
* @param {struct FPcieDmaDescriptor *} desc Desc is the descriptor to be configured
|
|
|
|
|
* @param {struct FPcieDmaDescriptor *} next_desc is the next descriptor that needs to be sent
|
|
|
|
|
* @return {FError}
|
|
|
|
|
*/
|
|
|
|
|
FError FPcieDmaDescSet(uintptr axi_addr,
|
|
|
|
|
uintptr bar_addr,
|
|
|
|
|
u32 length,
|
|
|
|
|
struct FPcieDmaDescriptor *desc,
|
|
|
|
|
struct FPcieDmaDescriptor *next_desc)
|
|
|
|
|
{
|
|
|
|
|
/* 设置内存地址 */
|
|
|
|
|
desc->axi_base_address = axi_addr;
|
|
|
|
|
desc->axi_address_phase_controls = 0x00;
|
|
|
|
|
|
|
|
|
|
/* 设置pcie空间地址 */
|
|
|
|
|
desc->pcie_base_address = bar_addr;
|
|
|
|
|
desc->pcie_tlp_header_attributes = 0x01;
|
|
|
|
|
|
|
|
|
|
/* 设置数据长度, 设置dma完成中断 */
|
|
|
|
|
desc->transfer_control = length;
|
|
|
|
|
|
|
|
|
|
desc->axi_bus_status = 0x00;
|
|
|
|
|
desc->pcie_bus_status = 0x00;
|
|
|
|
|
desc->channel_status = 0x00;
|
|
|
|
|
|
|
|
|
|
if (next_desc != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* 使能链表模式 */
|
|
|
|
|
desc->transfer_control &= ~(BIT(24));
|
|
|
|
|
desc->transfer_control |= BIT(29);
|
|
|
|
|
|
|
|
|
|
/* 设置下一级链表地址 */
|
|
|
|
|
desc->next_descriptor = (uintptr)next_desc;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
desc->transfer_control |= BIT(24);
|
|
|
|
|
desc->transfer_control &= ~(BIT(29));
|
|
|
|
|
desc->next_descriptor = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPcieDmaRead
|
|
|
|
|
* @msg: Pcie reads through dma
|
|
|
|
|
* @param {uintptr} bar_addr is Base Address Register value
|
|
|
|
|
* @param {FPcieDmaDescriptor} *desc is first address of the receive descriptor
|
|
|
|
|
*/
|
|
|
|
|
void FPcieDmaRead(uintptr bar_address, struct FPcieDmaDescriptor *desc)
|
|
|
|
|
{
|
|
|
|
|
/* The enable channel is interrupted */
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_INT_ENABLE_OFFSET, FPCIE_CTRL_DMA_INT_ENABLE_CH0_DONE_MASK | FPCIE_CTRL_DMA_INT_ENABLE_CH0_ERR_MASK);
|
|
|
|
|
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH0_SP_L_OFFSET, (u32)((uintptr)desc & 0xffffffffU));
|
|
|
|
|
#ifdef __aarch64__
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH0_SP_H_OFFSET, (u32)(((uintptr)desc >> 32) & 0xffffffffU));
|
|
|
|
|
#else
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH0_SP_H_OFFSET, 0);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH0_CTRL_OFFSET, FPCIE_CTRL_DMA_CH0_CTRL_GO_MASK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPcieDmaWrite
|
|
|
|
|
* @msg: Pcie writes through dma
|
|
|
|
|
* @param {uintptr} bar_address is Base Address Register value
|
|
|
|
|
* @param {FPcieDmaDescriptor} *desc is first address of the send descriptor
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void FPcieDmaWrite(uintptr bar_address, struct FPcieDmaDescriptor *desc)
|
|
|
|
|
{
|
|
|
|
|
/* The enable channel is interrupted */
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_INT_ENABLE_OFFSET, FPCIE_CTRL_DMA_INT_ENABLE_CH1_DONE_MASK | FPCIE_CTRL_DMA_INT_ENABLE_CH1_ERR_MASK);
|
|
|
|
|
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH1_SP_L_OFFSET, (u32)((uintptr)desc & 0xffffffffU));
|
|
|
|
|
#ifdef __aarch64__
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH1_SP_H_OFFSET, (u32)(((uintptr)desc >> 32) & 0xffffffffU));
|
|
|
|
|
#else
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH1_SP_H_OFFSET, 0);
|
|
|
|
|
#endif
|
|
|
|
|
FPCIE_WRITEREG(bar_address, FPCIE_REG_DMA_CH1_CTRL_OFFSET, FPCIE_CTRL_DMA_CH1_CTRL_GO_MASK | FPCIE_CTRL_DMA_CH1_CTRL_OBNOTIB_MASK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FPcieDmaPollDone
|
|
|
|
|
* @msg: Polling waits for DMA to complete
|
|
|
|
|
* @param {FPcieDmaDescriptor *} desc is the current need to wait for dma to complete
|
|
|
|
|
* @param {u32} wait_cnt is the count that needs to wait to end
|
|
|
|
|
* @return FError
|
|
|
|
|
*/
|
|
|
|
|
FError FPcieDmaPollDone(struct FPcieDmaDescriptor *desc, u32 wait_cnt)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FPCIE_DMA_DEBUG_I("Desc axi_bus_status :[0x%02x].", desc->axi_bus_status);
|
|
|
|
|
FPCIE_DMA_DEBUG_I("Desc pcie_bus_status:[0x%02x].", desc->pcie_bus_status);
|
|
|
|
|
FPCIE_DMA_DEBUG_I("Desc channel_status :[0x%02x].", desc->channel_status);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
|
|
|
|
|
while (wait_cnt > 0)
|
|
|
|
|
{
|
|
|
|
|
if (desc->channel_status == 0x1)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FPCIE_DMA_DEBUG_I("Dma channel transfer done.");
|
2022-11-10 22:22:48 +08:00
|
|
|
|
return FT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
wait_cnt--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FPCIE_ERR_TIMEOUT;
|
|
|
|
|
}
|