201 lines
6.3 KiB
C
Executable File
201 lines
6.3 KiB
C
Executable File
/*-----------------------------------------------------------------------------*/
|
|
/* Include Header Files */
|
|
/*-----------------------------------------------------------------------------*/
|
|
#include <linux/module.h>
|
|
#include <linux/stat.h>
|
|
#if defined (__aarch64__)
|
|
#include <linux/soc/nvt/fmem.h>
|
|
#else
|
|
#include <mach/fmem.h>
|
|
#endif
|
|
#include <linux/uaccess.h>
|
|
#include <asm/cache.h> // to get ARCH_DMA_MINALIGN
|
|
|
|
#define __MODULE__ rtos_cpu
|
|
#define __DBGLVL__ 8 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER
|
|
#define __DBGFLT__ "*"
|
|
#include <kwrap/debug.h>
|
|
#include <kwrap/cpu.h>
|
|
#include "vos_ioctl.h"
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Local Types Declarations */
|
|
/*-----------------------------------------------------------------------------*/
|
|
#define RTOS_CPU_INITED_TAG MAKEFOURCC('R', 'C', 'P', 'U') ///< a key value
|
|
|
|
#define VOS_DMA_ALIGN_DIFF (VOS_DMA_BIDIRECTIONAL_NON_ALIGN - VOS_DMA_BIDIRECTIONAL)
|
|
|
|
#if 0 //0 (disable the check), 1 (enable the check)
|
|
#define VOS_CPU_IS_ALIGNED(val) VOS_IS_ALIGNED(val)
|
|
#else
|
|
#define VOS_CPU_IS_ALIGNED(val) 1
|
|
#endif
|
|
|
|
#if defined(__LINUX)
|
|
|
|
#elif defined(__FREERTOS)
|
|
|
|
#else
|
|
#error Not supported OS
|
|
#endif
|
|
|
|
//VOS_ALIGN_BYTES is not the same as the real cache line size
|
|
//make sure the defined value meets OS requirements
|
|
STATIC_ASSERT(VOS_ALIGN_BYTES >= ARCH_DMA_MINALIGN);
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Local Global Variables */
|
|
/*-----------------------------------------------------------------------------*/
|
|
unsigned int rtos_cpu_debug_level = NVT_DBG_WRN;
|
|
|
|
module_param_named(rtos_cpu_debug_level, rtos_cpu_debug_level, int, S_IRUGO | S_IWUSR);
|
|
MODULE_PARM_DESC(rtos_cpu_debug_level, "Debug message level");
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Interface Functions */
|
|
/*-----------------------------------------------------------------------------*/
|
|
void rtos_cpu_init(void *param)
|
|
{
|
|
//check the value is the same as "enum dma_data_direction" defined in linux/dma-direction.h
|
|
STATIC_ASSERT((VOS_DMA_BIDIRECTIONAL - DMA_BIDIRECTIONAL) == 0);
|
|
STATIC_ASSERT((VOS_DMA_TO_DEVICE - DMA_TO_DEVICE) == 0);
|
|
STATIC_ASSERT((VOS_DMA_FROM_DEVICE - DMA_FROM_DEVICE) == 0);
|
|
STATIC_ASSERT((VOS_DMA_NONE - DMA_NONE) == 0);
|
|
STATIC_ASSERT((VOS_DMA_BIDIRECTIONAL_NON_ALIGN - VOS_DMA_BIDIRECTIONAL) == VOS_DMA_ALIGN_DIFF);
|
|
STATIC_ASSERT((VOS_DMA_TO_DEVICE_NON_ALIGN - VOS_DMA_TO_DEVICE) == VOS_DMA_ALIGN_DIFF);
|
|
STATIC_ASSERT((VOS_DMA_FROM_DEVICE_NON_ALIGN - VOS_DMA_FROM_DEVICE) == VOS_DMA_ALIGN_DIFF);
|
|
}
|
|
|
|
void rtos_cpu_exit(void)
|
|
{
|
|
}
|
|
|
|
VOS_ADDR vos_cpu_get_phy_addr(VOS_ADDR vaddr)
|
|
{
|
|
phys_addr_t ret_addr;
|
|
|
|
ret_addr = fmem_lookup_pa(vaddr);
|
|
if (0xFFFFFFFF == ret_addr) {
|
|
DBG_ERR("Get pa fail, vaddr 0x%lX\r\n", (ULONG)vaddr);
|
|
return VOS_ADDR_INVALID;
|
|
}
|
|
|
|
return (VOS_ADDR)ret_addr;
|
|
}
|
|
|
|
void vos_cpu_dcache_sync(VOS_ADDR vaddr, UINT32 len, VOS_DMA_DIRECTION dir)
|
|
{
|
|
VOS_DMA_DIRECTION real_dir;
|
|
|
|
if (dir <= VOS_DMA_NONE) {
|
|
//check the alignment
|
|
if (!VOS_CPU_IS_ALIGNED(vaddr) || !VOS_CPU_IS_ALIGNED(len)) {
|
|
DBG_ERR("vaddr(0x%lX) or len(0x%X) not aligned %d\r\n", (ULONG)vaddr, len, VOS_ALIGN_BYTES);
|
|
return;
|
|
}
|
|
real_dir = dir;
|
|
} else if (dir <= VOS_DMA_FROM_DEVICE_NON_ALIGN) {
|
|
//skip the alignment check
|
|
real_dir = dir - VOS_DMA_ALIGN_DIFF;
|
|
} else {
|
|
DBG_ERR("Invalid dir %d\r\n", dir);
|
|
return;
|
|
}
|
|
|
|
fmem_dcache_sync((void *)vaddr, len, (enum dma_data_direction)real_dir);
|
|
}
|
|
|
|
void vos_cpu_dcache_sync_vb(VOS_ADDR vaddr, UINT32 len, VOS_DMA_DIRECTION dir)
|
|
{
|
|
VOS_DMA_DIRECTION real_dir;
|
|
|
|
if (dir <= VOS_DMA_NONE) {
|
|
//check the alignment
|
|
if (!VOS_CPU_IS_ALIGNED(vaddr) || !VOS_CPU_IS_ALIGNED(len)) {
|
|
DBG_ERR("vaddr(0x%lX) or len(0x%X) not aligned %d\r\n", (ULONG)vaddr, len, VOS_ALIGN_BYTES);
|
|
return;
|
|
}
|
|
real_dir = dir;
|
|
} else if (dir <= VOS_DMA_FROM_DEVICE_NON_ALIGN) {
|
|
//skip the alignment check
|
|
real_dir = dir - VOS_DMA_ALIGN_DIFF;
|
|
} else {
|
|
DBG_ERR("Invalid dir %d\r\n", dir);
|
|
return;
|
|
}
|
|
|
|
fmem_dcache_sync_vb((void *)vaddr, len, (enum dma_data_direction)real_dir);
|
|
}
|
|
|
|
int vos_cpu_dcache_sync_by_cpu(VOS_ADDR vaddr, UINT32 len, VOS_DMA_DIRECTION dir, UINT cache_op_cpu_id)
|
|
{
|
|
unsigned long fmem_ret;
|
|
|
|
fmem_ret = fmem_dcache_sync_by_cpu((void *)vaddr, len, (enum dma_data_direction)dir, cache_op_cpu_id);
|
|
if (fmem_ret != 0) {
|
|
DBG_ERR("fmem_dcache_sync_by_cpu failed, ret %ld, cpu id %d\r\n", fmem_ret, cache_op_cpu_id);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _IOFUNC_CPU_IOCMD_DCACHE_SYNC(unsigned long arg)
|
|
{
|
|
VOS_CPU_IOARG ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_CPU_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ioarg.is_vb) {
|
|
vos_cpu_dcache_sync_vb((VOS_ADDR)ioarg.vaddr, (UINT32)ioarg.len, (VOS_DMA_DIRECTION)ioarg.dir);
|
|
} else {
|
|
vos_cpu_dcache_sync((VOS_ADDR)ioarg.vaddr, (UINT32)ioarg.len, (VOS_DMA_DIRECTION)ioarg.dir);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _IOFUNC_CPU_IOCMD_GET_PHY_ADDR(unsigned long arg)
|
|
{
|
|
VOS_CPU_IOARG_VA_PA ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_CPU_IOARG_VA_PA))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
//return to users
|
|
ioarg.paddr = (unsigned long)vos_cpu_get_phy_addr((VOS_ADDR)ioarg.vaddr);
|
|
if (copy_to_user((void *)arg, (void *)&ioarg, sizeof(VOS_CPU_IOARG_VA_PA))) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _IOFUNC_CPU_IOCMD_SYNC_CPU(unsigned long arg)
|
|
{
|
|
VOS_CPU_IOARG_SYNC_CPU ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_CPU_IOARG_SYNC_CPU))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (0 != vos_cpu_dcache_sync_by_cpu((VOS_ADDR)ioarg.vaddr, (UINT32)ioarg.len, (VOS_DMA_DIRECTION)ioarg.dir, (UINT)ioarg.cpu_id)) {
|
|
return -EPERM;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Kernel Mode Definiton */
|
|
/*-----------------------------------------------------------------------------*/
|
|
EXPORT_SYMBOL(vos_cpu_get_phy_addr);
|
|
EXPORT_SYMBOL(vos_cpu_dcache_sync);
|
|
EXPORT_SYMBOL(vos_cpu_dcache_sync_vb);
|
|
EXPORT_SYMBOL(vos_cpu_dcache_sync_by_cpu); |