yb_arm/driver/arm_csu/src/arm_csu.c
2023-12-29 16:48:28 +08:00

242 lines
6.4 KiB
C

// +FHDR------------------------------------------------------------
// Copyright (c) 2022 SmartLogic.
// ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename : arm_csu.c
// Author : xinxin.li
// Created On : 2022-11-23
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------
#include "ucp_csu.h"
#include "arm_csu.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "ucp_utility.h"
#include "ucp_printf.h"
#include "drv_init.h"
uint8_t* virMemAddr = NULL;
int arm_csu_init()
{
if (-1 == g_drv_mem_fd0)
{
// printf("open dev mem. \r\n");
g_drv_mem_fd0 = open("/dev/mem", O_RDWR|O_SYNC);
if (0 > g_drv_mem_fd0)
{
UCP_PRINT_ERROR("open /dev/mem error\n");
return -1;
}
}
// printf("start mmap. \r\n");
virMemAddr = (uint8_t*)mmap(NULL, CSU_DEV_MAP_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, g_drv_mem_fd0, AP_CSU_BASE);
if ((uint8_t*)(-1) == virMemAddr)
{
UCP_PRINT_ERROR("mmap error!!");
return -1;
}
// printf("csu init. \r\n");
int i;
for (i = 0; i < 16; i++)
{
*((volatile uint32_t*)(virMemAddr+AP_CSU_DMAYNUMXNUM0) + (i<<3)) = ((4<<16)|1024);
*((volatile uint32_t*)(virMemAddr+AP_CSU_DMAYSTEPL0) + (i<<3)) = 1024;
*((volatile uint32_t*)(virMemAddr+AP_CSU_DMAYSTEPH0) + (i<<3)) = 0;
*((volatile uint32_t*)(virMemAddr+AP_CSU_DMAZSTEPL0) + (i<<3)) = 4096;
*((volatile uint32_t*)(virMemAddr+AP_CSU_DMAZSTEPH0) + (i<<3)) = 0;
}
*((volatile uint32_t*)(virMemAddr+AP_CSU_EM_BS_SMSEL_PREDATANUM)) = (0x2A<<16) | (0x0<<14) | (0x5<<5) | 0x9; // (0x3F<<16);
*((volatile uint32_t*)(virMemAddr+AP_CSU_EM_BS_SMSEL_PREDATANUM)) = (0x2A<<16) | (0x1<<14) | (0x5<<5) | 0x9;
*((volatile uint32_t*)(virMemAddr+AP_CSU_EM_BS_SMSEL_PREDATANUM)) = (0x2A<<16) | (0x2<<14) | (0x5<<5) | 0x9;
*((volatile uint32_t*)(virMemAddr+AP_CSU_EM_BS_SMSEL_PREDATANUM)) = (0x2A<<16) | (0x3<<14) | (0x5<<5) | 0x9;
*((volatile uint32_t*)(virMemAddr+AP_CSU_FINDDMATAG)) = 0x60;
*((volatile uint32_t*)(virMemAddr+AP_CSU_TAGMASK0)) = 0xFFFFFFFF;
*((volatile uint32_t*)(virMemAddr+AP_CSU_TAGMASK1)) = 0xFFFFFFFF;
*((volatile uint32_t*)(virMemAddr+AP_CSU_TAGMASK2)) = 0xFFFFFFFF;
*((volatile uint32_t*)(virMemAddr+AP_CSU_TAGMASK3)) = 0xFFFFFFFF;
return 0;
}
int get_arm_csu_status(uint8_t tag)
{
if (31 < tag)
{
UCP_PRINT_ERROR("input para error! tag = %d. \r\n", tag);
return -1;
}
uint32_t status = VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASTATUS);
return (status&(1<<tag)); // 0: not finished, 1: finished
}
int arm_csu_wait_done(uint8_t tag)
{
if (31 < tag)
{
UCP_PRINT_ERROR("input para error! tag = %d. \r\n", tag);
return -1;
}
volatile uint32_t status = 0;
while (1)
{
status = VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASTATUS);
// printf("tag = %d, dmastatus = 0x%x. \r\n", tag, status);
if (0 != (status&(1<<tag)))
{
break;
}
}
// while (0 == (VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASTATUS) & (1<<tag)));
return 0;
}
int arm_csu_wait_all_done(void)
{
#if 0
for (int i = 0; i < 32; i++)
{
arm_csu_wait_done(i);
}
#endif
while (1)
{
int cmdNum = 0;
for (int i = 0; i < 4; i++)
{
cmdNum += VIR_ADDR_VAL(virMemAddr, AP_CSU_CMDFIFO0_NUM+(i<<2));
}
if (0 == cmdNum)
{
break;
}
}
return 0;
}
//CmdFIFO 0 1 2 3
//tag 0 1 2 3 reg_group = 0(0->1)
//tag 4 5 6 7 1(2->3)
//tag 8 9 10 11 2(4->5)
//tag 12 13 14 15 3(6->7)
//tag 16 17 18 19 4(8->9)
//tag 20 21 22 23 5(10->11)
//tag 24 25 26 27 6(12->13)
//tag 28 29 30 31 7(14->15)
//tag 0 8 16 24 reg_group = 0(0->1) CmdFIFO =0
//tag 1 9 17 25 1(2->3) 1
//tag 2 10 18 26 2(4->5) 2
//tag 3 11 19 27 3(6->7) 3
//tag 4 12 20 28 4(8->9) 0
//tag 5 13 21 29 5(10->11) 1
//tag 6 14 22 30 6(12->13) 2
//tag 7 15 23 31 7(14->15) 3
// get unused register group according to tag number
int get_free_reg_group(uint8_t tag)
{
if (31 < tag)
{
return -1;
}
uint8_t fifoNum = tag & 0x3; // tag % 4;
uint8_t regGroup = tag & 0x7; // tag / 4;
uint32_t bitMap = (0x01010101<<regGroup);
uint32_t dmaStatus = VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASTATUS);
//if (0 == (dmaStatus & (0xF<<regGroup)))
if (bitMap != (dmaStatus & bitMap))
{
return -1;
}
return ((fifoNum<<16) | regGroup); // [31:16]fifoNum(0~3), [15:0]reg group(0~7)
}
int get_free_channel()
{
while (1)
{
for (int tag = 0; tag < 32; tag++)
{
if (0 == (VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASTATUS) & (1<<tag)))
{
continue;
}
else
{
uint32_t temp = get_free_reg_group(tag);
if (-1 == temp)
{
continue;
}
else
{
uint8_t regGroup = temp & 0xFF;
uint8_t fifoNum = (temp>>16) & 0xFF;
int ret = regGroup | (fifoNum<<8) | (tag<<16);
return ret;
}
}
}
}
}
int arm_csu_dma_1D_transfer(uint64_t addrSrc, uint64_t addrDst, uint32_t dataLen)
{
uint8_t regGroup = 0;
uint8_t fifoNum = 0;
uint8_t tag = 0;
uint32_t temp = get_free_channel();
// printf("get free channle: 0x%x. \r\n", temp);
regGroup = temp & 0xFF;
fifoNum = (temp>>8) & 0xFF;
tag = (temp>>16)&0xFF;
uint16_t offset = regGroup << 6;
// src reg
VIR_ADDR_VAL(virMemAddr, AP_CSU_DMAADDRL0 + offset) = addrSrc & 0xFFFFFFFF;
VIR_ADDR_VAL(virMemAddr, AP_CSU_DMAADDRH0 + offset) = addrSrc >> 32;
VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASIZEGRANALLNUM0 + offset) = (0xF<<28) | dataLen;
// dst reg
VIR_ADDR_VAL(virMemAddr, AP_CSU_DMAADDRL1 + offset) = addrDst & 0xFFFFFFFF;
VIR_ADDR_VAL(virMemAddr, AP_CSU_DMAADDRH1 + offset) = addrDst >> 32;
VIR_ADDR_VAL(virMemAddr, AP_CSU_DMASIZEGRANALLNUM1 + offset) = (0xE<<24) | dataLen; // write global, size=0
VIR_ADDR_VAL(virMemAddr, AP_CSU_CMDHIGHDATA) = 0;
stCsuDmaCmdL dmaCmdL;
dmaCmdL.dmaType = 1;
dmaCmdL.idSrc = 0 + (regGroup<<1);
dmaCmdL.idDst = 1 + (regGroup<<1);
dmaCmdL.dmaTag = tag;
//(uint32_t)(VIR_ADDR_VAL(virMemAddr, AP_CSU_CMDFIFO0+(fifoNum<<2))) = (uint32_t)(*((uint32_t*)(&dmaCmdL)));
memcpy((uint32_t*)(virMemAddr+AP_CSU_CMDFIFO0+(fifoNum<<2)), (uint32_t*)(&dmaCmdL), 4);
return tag;
}