Merge branch 'dev_ck_v2.1_lwh' into 'dev_ck_v2.1'
delete ko source code See merge request ucp/driver/ucp4008_platform_arm!1
This commit is contained in:
commit
cd47bbce35
25
driver/cache/Makefile
vendored
25
driver/cache/Makefile
vendored
@ -1,25 +0,0 @@
|
||||
export ARCH=arm64
|
||||
export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
#KERNELDIR = /public/liweihua/workspace/linux-5.15.40
|
||||
KERNELDIR = /public/liweihua/workspace/linux-5.10.165
|
||||
OBJ = SM_DDR
|
||||
|
||||
PWD = $(shell pwd)
|
||||
# Kernel modules
|
||||
ifeq ($(OBJ),SM_DDR)
|
||||
obj-m=ucp4008cache.o
|
||||
#ucp4008cache-objs=osp_sm_ddr.o
|
||||
#ucp4008cache-objs = cache.o osp_sm_ddr.o
|
||||
ucp4008cache-y:=osp_sm_ddr.o cache.o
|
||||
endif
|
||||
|
||||
# Specify flags for the module compilation.
|
||||
ccflags-y = -g -O0
|
||||
#INCLUDE += -l./../../common/
|
||||
build: kernel_modules
|
||||
kernel_modules:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
|
78
driver/cache/cache.S
vendored
78
driver/cache/cache.S
vendored
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Cache maintenance
|
||||
*
|
||||
* Copyright (C) 2001 Deep Blue Solutions Ltd.
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
//#include <asm/assembler.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/asm-uaccess.h>
|
||||
|
||||
/*
|
||||
* dcache_line_size - get the safe D-cache line size across all CPUs
|
||||
*/
|
||||
.macro mydcache_line_size, reg, tmp
|
||||
//read_ctr \tmp
|
||||
mrs \tmp, ctr_el0
|
||||
ubfm \tmp, \tmp, #16, #19 // cache line size encoding
|
||||
mov \reg, #4 // bytes per word
|
||||
lsl \reg, \reg, \tmp // actual cache line size
|
||||
.endm
|
||||
|
||||
/*
|
||||
* __inval_dcache_area(kaddr, size)
|
||||
*
|
||||
* Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
|
||||
* are invalidated. Any partial lines at the ends of the interval are
|
||||
* also cleaned to PoC to prevent data loss.
|
||||
*
|
||||
* - kaddr - kernel address
|
||||
* - size - size in question
|
||||
*/
|
||||
SYM_FUNC_START(__myinval_dcache_area)
|
||||
/* FALLTHROUGH */
|
||||
/*
|
||||
* __dma_inv_area(start, size)
|
||||
* - start - virtual start address of region
|
||||
* - size - size in question
|
||||
*/
|
||||
__mydma_inv_area:
|
||||
add x1, x1, x0
|
||||
mydcache_line_size x2, x3
|
||||
sub x3, x2, #1
|
||||
tst x1, x3 // end cache line aligned?
|
||||
bic x1, x1, x3
|
||||
b.eq 1f
|
||||
dc civac, x1 // clean & invalidate D / U line
|
||||
1: tst x0, x3 // start cache line aligned?
|
||||
bic x0, x0, x3
|
||||
b.eq 2f
|
||||
dc civac, x0 // clean & invalidate D / U line
|
||||
b 3f
|
||||
2: dc ivac, x0 // invalidate D / U line
|
||||
3: add x0, x0, x2
|
||||
cmp x0, x1
|
||||
b.lo 2b
|
||||
dsb sy
|
||||
ret
|
||||
//ENDPIPROC(__myinval_dcache_area)
|
||||
//SYM_FUNC_END(__mydma_inv_area)
|
||||
SYM_FUNC_END(__myinval_dcache_area)
|
||||
|
||||
|
532
driver/cache/osp_sm_ddr.c
vendored
532
driver/cache/osp_sm_ddr.c
vendored
@ -1,532 +0,0 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/async_tx.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
|
||||
/*函数原型*/
|
||||
static int __init ucp_sm_ddr_module_init(void);
|
||||
int ucp_sm_ddr_cache_open(struct inode *inode, struct file *filp);
|
||||
int ucp_sm_ddr_noncache_open(struct inode *inode, struct file *filp);
|
||||
|
||||
int ucp_sm_ddr_cache_release(struct inode *inode, struct file *filp);
|
||||
int ucp_sm_ddr_noncache_release(struct inode *inode, struct file *filp);
|
||||
|
||||
ssize_t ucp_sm_ddr_cache_read(struct file *filp, char __user *buf, size_t size_in, loff_t *ppos);
|
||||
ssize_t ucp_sm_ddr_noncache_read(struct file *filp, char __user *buf, size_t size_in, loff_t *ppos);
|
||||
|
||||
ssize_t ucp_sm_ddr_cache_write(struct file *filp, char __user *buf, size_t size, loff_t *ppos);
|
||||
ssize_t ucp_sm_ddr_noncache_write(struct file *filp, char __user *buf, size_t size, loff_t *ppos);
|
||||
|
||||
static long ucp_sm_ddr_cache_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
static long ucp_sm_ddr_noncache_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
|
||||
static int ucp_sm_ddr_cache_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
static int ucp_sm_ddr_noncache_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
static ssize_t ucp_mem_show(struct device *dev,struct device_attribute *attr, char *buf);
|
||||
static void __exit ucp_sm_ddr_module_exit(void);
|
||||
|
||||
extern void __myinval_dcache_area(unsigned long vir_cache_add, unsigned long len);
|
||||
|
||||
|
||||
|
||||
static const struct vm_operations_struct osp_mmap_mem_ops = {
|
||||
#ifdef CONFIG_HAVE_IOREMAP_PROT
|
||||
.access = generic_access_phys
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*申请设备名称*/
|
||||
#define DEVICE_NAME_SM_DDR_CACHE "ucp_sm_ddr_cache"
|
||||
#define DEVICE_NAME_SM_DDR_NONCACHE "ucp_sm_ddr_noncache"
|
||||
|
||||
|
||||
/*设备物理地址*/
|
||||
#if 1 //4008 add
|
||||
#define ECS_SM_BASE 0x07200000ul
|
||||
#define PET_SM_BASE 0x08700000ul
|
||||
#define SHARE_SM_BASE 0x09d00000ul
|
||||
#define DDR_BASE 0x10000000ul
|
||||
#define ARM_APE_MSG_BASE_PHY_ADDR 0x0A0000000UL
|
||||
#define ARM_STACK_BASE_PHY_ADDR 0x100000000UL //0x0B8000000UL
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*size num*/
|
||||
#define S128KB 0x00020000ul // 128K
|
||||
#define S8MB 0x00800000ul // 8M
|
||||
#define S16GB 0x1F0000000ul //0x400000000ul // 16G
|
||||
#define LEN_OF_ARM_STACK 0x100000000UL
|
||||
#define LEN_OF_ARM_APE_MSG 0x008000000UL
|
||||
|
||||
|
||||
/*设备空间大小*/
|
||||
#define ECS_SM_SIZE 0x000060000UL
|
||||
#define ECS_SM_MAX 0x00725fffful
|
||||
|
||||
#define PET_SM_SIZE 0x000060000UL
|
||||
#define PET_SM_MAX 0x00875fffful
|
||||
|
||||
#define SHARE_SM_SIZE S8MB
|
||||
#define SHARE_SM_MAX 0x0a4ffffful
|
||||
|
||||
|
||||
#define DDR_SIZE S16GB
|
||||
#define DDR_MAX 0x1fffffffful
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 //1002 add
|
||||
#define ECS_SM_BASE 0x02360000ul
|
||||
#define PET_SM_BASE 0x03860000ul
|
||||
|
||||
#define SHARE_SM_BASE 0x04e60000ul
|
||||
#define DDR_BASE 0x10000000ul
|
||||
|
||||
#define S128KB 0x00020000ul // 128K
|
||||
#define S8MB 0x00800000ul // 8M
|
||||
#define S16GB 0x400000000ul // 16G
|
||||
|
||||
#define ECS_SM_SIZE S128KB
|
||||
#define ECS_SM_MAX 0x0237fffful
|
||||
|
||||
#define PET_SM_SIZE S128KB
|
||||
#define PET_SM_MAX 0x0387fffful
|
||||
|
||||
#define SHARE_SM_SIZE S8MB
|
||||
#define SHARE_SM_MAX 0x0565fffful
|
||||
|
||||
#define DDR_SIZE S16GB
|
||||
|
||||
#define DDR_MAX 0x40ffffffful
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*error num*/
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
|
||||
|
||||
/*全局变量声明初始化*/
|
||||
|
||||
/*file operation structure*/
|
||||
static const struct file_operations ucp_sm_ddr_cache_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = ucp_sm_ddr_cache_open,
|
||||
.unlocked_ioctl = ucp_sm_ddr_cache_ioctl,
|
||||
.mmap = ucp_sm_ddr_cache_mmap,
|
||||
.release = ucp_sm_ddr_cache_release,
|
||||
};
|
||||
|
||||
static const struct file_operations ucp_sm_ddr_noncache_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = ucp_sm_ddr_noncache_open,
|
||||
.unlocked_ioctl = ucp_sm_ddr_noncache_ioctl,
|
||||
.mmap = ucp_sm_ddr_noncache_mmap,
|
||||
.release = ucp_sm_ddr_noncache_release,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct miscdevice ucp_sm_ddr_cache_miscdev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = DEVICE_NAME_SM_DDR_CACHE,
|
||||
.fops = &ucp_sm_ddr_cache_fops,
|
||||
};
|
||||
|
||||
static struct miscdevice ucp_sm_ddr_noncache_miscdev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = DEVICE_NAME_SM_DDR_NONCACHE,
|
||||
.fops = &ucp_sm_ddr_noncache_fops,
|
||||
};
|
||||
|
||||
|
||||
void __iomem * g_vir_ecs_sm_cache_add = NULL;
|
||||
void __iomem * g_vir_pet_sm_cache_add = NULL;
|
||||
void __iomem * g_vir_share_sm_cache_add = NULL;
|
||||
void __iomem * g_vir_ddr_cache_add = NULL;
|
||||
void __iomem * g_vir_msg_cache_add = NULL;
|
||||
void __iomem * g_vir_stack_cache_add = NULL;
|
||||
|
||||
|
||||
|
||||
static DEVICE_ATTR(ucp_sm_ddr_cache, S_IRUGO, ucp_mem_show, NULL);
|
||||
static DEVICE_ATTR(ucp_sm_ddr_noncache, S_IRUGO, ucp_mem_show, NULL);
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver init function********************/
|
||||
/********************************************************************/
|
||||
static int __init ucp_sm_ddr_module_init(void)
|
||||
{
|
||||
int iRet=0;
|
||||
|
||||
/*注册 设备驱动*/
|
||||
iRet = misc_register(&ucp_sm_ddr_cache_miscdev);
|
||||
if(iRet)
|
||||
{
|
||||
goto sm_ddr_misc_err;
|
||||
}
|
||||
iRet = misc_register(&ucp_sm_ddr_noncache_miscdev);
|
||||
if(iRet)
|
||||
{
|
||||
goto sm_ddr_misc_err;
|
||||
}
|
||||
|
||||
/*在/sys/class 目录下创建对应的属性文件*/
|
||||
iRet = device_create_file(ucp_sm_ddr_cache_miscdev.this_device, &dev_attr_ucp_sm_ddr_cache);
|
||||
if (iRet)
|
||||
{
|
||||
goto sm_ddr_cache_attr_err;
|
||||
printk(KERN_EMERG "ucp_sm_ddr_cache_module_init failed \r\n");
|
||||
|
||||
}
|
||||
|
||||
printk(KERN_EMERG "ucp_sm_ddr_cache_module_init ok cat /sys/devices/virtual/misc/ucp_sm_ddr_cache\r\n");
|
||||
|
||||
iRet = device_create_file(ucp_sm_ddr_noncache_miscdev.this_device, &dev_attr_ucp_sm_ddr_noncache);
|
||||
if (iRet)
|
||||
{
|
||||
goto sm_ddr_noncache_attr_err;
|
||||
printk(KERN_EMERG "ucp_sm_ddr_noncache_module_init failed \r\n");
|
||||
|
||||
}
|
||||
|
||||
printk(KERN_EMERG "ucp_sm_ddr_noncache_module_init ok cat /sys/devices/virtual/misc/ucp_sm_ddr_noncache\r\n");
|
||||
|
||||
g_vir_ecs_sm_cache_add = ioremap(ECS_SM_BASE, ECS_SM_SIZE);
|
||||
|
||||
g_vir_pet_sm_cache_add = ioremap(PET_SM_BASE, PET_SM_SIZE);
|
||||
|
||||
g_vir_share_sm_cache_add = ioremap(SHARE_SM_BASE, SHARE_SM_SIZE);
|
||||
|
||||
g_vir_msg_cache_add = ioremap(ARM_APE_MSG_BASE_PHY_ADDR, LEN_OF_ARM_APE_MSG);
|
||||
g_vir_stack_cache_add = ioremap(ARM_STACK_BASE_PHY_ADDR, LEN_OF_ARM_STACK);
|
||||
|
||||
|
||||
printk(KERN_EMERG "globle g_vir_ecs_sm_cache_add = 0x%lx \n ",(uint64_t)g_vir_ecs_sm_cache_add);
|
||||
|
||||
printk(KERN_EMERG "globle g_vir_pet_sm_cache_add = 0x%lx \n ",(uint64_t)g_vir_pet_sm_cache_add);
|
||||
|
||||
printk(KERN_EMERG "globle g_vir_share_sm_cache_add = 0x%lx \n ",(uint64_t)g_vir_share_sm_cache_add);
|
||||
|
||||
//printk(KERN_EMERG "globle g_vir_ddr_cache_add = 0x%lx \n ",g_vir_ddr_cache_add);
|
||||
|
||||
printk(KERN_EMERG "globle g_vir_msg_cache_add = 0x%lx \n ",(uint64_t)g_vir_msg_cache_add);
|
||||
|
||||
printk(KERN_EMERG "globle g_vir_stack_cache_add = 0x%lx \n ",(uint64_t)g_vir_stack_cache_add);
|
||||
|
||||
return 0;
|
||||
|
||||
sm_ddr_cache_attr_err:
|
||||
misc_deregister(&ucp_sm_ddr_cache_miscdev);
|
||||
sm_ddr_noncache_attr_err:
|
||||
misc_deregister(&ucp_sm_ddr_noncache_miscdev);
|
||||
sm_ddr_misc_err:
|
||||
return -EINVAL;
|
||||
}
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver open function********************/
|
||||
/********************************************************************/
|
||||
int ucp_sm_ddr_cache_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
/* device structure pointer assgined to file private data pointer */
|
||||
printk("enter %s\n",__func__);
|
||||
return 0;
|
||||
}
|
||||
int ucp_sm_ddr_noncache_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
/* device structure pointer assgined to file private data pointer */
|
||||
printk("enter %s\n",__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver release function*******************/
|
||||
/********************************************************************/
|
||||
int ucp_sm_ddr_cache_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int ucp_sm_ddr_noncache_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver read function*******************/
|
||||
/********************************************************************/
|
||||
ssize_t ucp_sm_ddr_cache_read(struct file *filp, char __user *buf, size_t size_in, loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ssize_t ucp_sm_ddr_noncache_read(struct file *filp, char __user *buf, size_t size_in, loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver write function*******************/
|
||||
/********************************************************************/
|
||||
ssize_t ucp_sm_ddr_cache_write(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ssize_t ucp_sm_ddr_noncache_write(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver ioctl function*******************/
|
||||
/********************************************************************/
|
||||
static long ucp_sm_ddr_cache_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
|
||||
void __iomem *vir_cache_add = NULL;
|
||||
|
||||
unsigned long uiOffset= 0, addr = arg, len = cmd;
|
||||
|
||||
|
||||
//printk("enter %s\n\n",__func__);
|
||||
|
||||
//printk("addr = %#lx len = %#lx\n\n",cmd,arg);
|
||||
|
||||
if(addr >= ECS_SM_BASE && addr <= ECS_SM_MAX)
|
||||
{
|
||||
|
||||
uiOffset = addr - ECS_SM_BASE;
|
||||
|
||||
vir_cache_add = g_vir_ecs_sm_cache_add + uiOffset ;
|
||||
|
||||
}
|
||||
else if(addr >= PET_SM_BASE && addr <= PET_SM_MAX)
|
||||
{
|
||||
|
||||
uiOffset = addr - PET_SM_BASE;
|
||||
|
||||
vir_cache_add = g_vir_pet_sm_cache_add + uiOffset ;
|
||||
|
||||
}
|
||||
else if(addr >= SHARE_SM_BASE && addr <= SHARE_SM_MAX)
|
||||
{
|
||||
|
||||
uiOffset = addr - SHARE_SM_BASE;
|
||||
|
||||
vir_cache_add = g_vir_share_sm_cache_add + uiOffset ;
|
||||
|
||||
}
|
||||
else if(addr >= ARM_APE_MSG_BASE_PHY_ADDR && addr < ARM_APE_MSG_BASE_PHY_ADDR + LEN_OF_ARM_APE_MSG)
|
||||
{
|
||||
|
||||
uiOffset = addr - ARM_APE_MSG_BASE_PHY_ADDR;
|
||||
|
||||
vir_cache_add = g_vir_msg_cache_add + uiOffset ;
|
||||
}
|
||||
else if(addr >= ARM_STACK_BASE_PHY_ADDR && addr < ARM_STACK_BASE_PHY_ADDR + LEN_OF_ARM_STACK)
|
||||
{
|
||||
|
||||
uiOffset = addr - ARM_STACK_BASE_PHY_ADDR;
|
||||
|
||||
vir_cache_add = g_vir_stack_cache_add + uiOffset ;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
printk("ucp_sm_ddr_cache_ioctl phy add out of range \n ");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//__mydma_inv_area(vir_cache_add, arg);
|
||||
__myinval_dcache_area((unsigned long)vir_cache_add, len);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long ucp_sm_ddr_noncache_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver mmap function*******************/
|
||||
/********************************************************************/
|
||||
static int ucp_sm_ddr_cache_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
|
||||
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
|
||||
unsigned long vmsize = vma->vm_end - vma->vm_start;
|
||||
unsigned long psize = PAGE_SIZE - offset;
|
||||
pgprot_t prot = vma->vm_page_prot;
|
||||
|
||||
/* 设置IO标志 */
|
||||
|
||||
/*if(vmsize > psize) {
|
||||
|
||||
return -ENXIO;
|
||||
}*/
|
||||
printk("enter %s,phyaddr = %#lx,vm_start = %#lx\n",__func__,offset,vma->vm_start);
|
||||
//printk(KERN_EMERG "titan : cached mode is cache \n");
|
||||
//printk(KERN_EMERG "titan : vma->vm_pgoff = 0x%x \n",offset);
|
||||
|
||||
vma->vm_ops = &osp_mmap_mem_ops;
|
||||
|
||||
if(remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vmsize, prot) != 0) {
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
//printk(KERN_EMERG "titan : vma->vm_start = 0x%x \n",vma->vm_start);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int ucp_sm_ddr_noncache_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
|
||||
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
|
||||
unsigned long vmsize = vma->vm_end - vma->vm_start;
|
||||
unsigned long psize = PAGE_SIZE - offset;
|
||||
pgprot_t prot = vma->vm_page_prot;
|
||||
|
||||
/* 设置IO标志 */
|
||||
|
||||
// vir_sm_noncache_add = ioremap_nocache(SM_BASE, SM_SIZE);
|
||||
|
||||
// vir_ddr_noncache_add = ioremap_nocache(DDR_BASE, DDR_SIZE);
|
||||
|
||||
|
||||
/*if(vmsize > psize) {
|
||||
|
||||
return -ENXIO;
|
||||
} */
|
||||
printk("enter %s,phyaddr = %#lx,vm_start = %#lx\n",__func__,offset,vma->vm_start);
|
||||
|
||||
//printk(KERN_EMERG "titan : vma->vm_pgoff = 0x%x \n",offset);
|
||||
|
||||
prot = pgprot_writecombine(prot);
|
||||
|
||||
vma->vm_ops = &osp_mmap_mem_ops;
|
||||
|
||||
//printk(KERN_EMERG "titan : cached mode is non cache \n");
|
||||
|
||||
if(remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vmsize, prot) != 0) {
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
static ssize_t ucp_mem_show(struct device *dev,struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*********************sm0~sm5 & ddr driver exit function*******************/
|
||||
/********************************************************************/
|
||||
/* module unload function*/
|
||||
static void __exit ucp_sm_ddr_module_exit(void)
|
||||
{
|
||||
|
||||
iounmap(g_vir_ecs_sm_cache_add);
|
||||
iounmap(g_vir_pet_sm_cache_add);
|
||||
iounmap(g_vir_share_sm_cache_add);
|
||||
iounmap(g_vir_ddr_cache_add);
|
||||
|
||||
|
||||
device_remove_file(ucp_sm_ddr_cache_miscdev.this_device, &dev_attr_ucp_sm_ddr_cache);
|
||||
device_remove_file(ucp_sm_ddr_noncache_miscdev.this_device, &dev_attr_ucp_sm_ddr_noncache);
|
||||
|
||||
|
||||
misc_deregister(&ucp_sm_ddr_cache_miscdev);
|
||||
misc_deregister(&ucp_sm_ddr_noncache_miscdev);
|
||||
|
||||
|
||||
|
||||
}
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* a simple char device driver: ExtInt without mutex
|
||||
*
|
||||
* Copyright (C) 2014 Barry Song (baohua@kernel.org)
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
|
||||
MODULE_AUTHOR ("lte team");
|
||||
MODULE_DESCRIPTION ("ucp_sm_ddr driver module" );
|
||||
MODULE_LICENSE ("GPL");
|
||||
module_init(ucp_sm_ddr_module_init);
|
||||
module_exit(ucp_sm_ddr_module_exit);
|
||||
MODULE_INFO(intree, "Y");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
export ARCH = arm64
|
||||
export CROSS_COMPILE = aarch64-linux-gnu-
|
||||
|
||||
ARCH=arm64
|
||||
CROSS_COMPILE = aarch64-linux-gnu-
|
||||
|
||||
KERNELDIR ?= /public/linboheng/workspace/ucp4008_nr_integrated_small_cell_new_kernel/kernel/linux-5.10.165
|
||||
PWD = $(shell pwd)
|
||||
obj-m := ioreg.o
|
||||
|
||||
# Specify flags for the module compilation.
|
||||
ccflags-y = -g -O0
|
||||
|
||||
build: kernel_modules
|
||||
kernel_modules:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
|
@ -1,182 +0,0 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <linux/async_tx.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <asm/div64.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/timex.h>
|
||||
|
||||
|
||||
|
||||
#define IOCTL_MMAPREG _IO('k',0x20)
|
||||
|
||||
|
||||
#define DEVICE_NAME "ioreg"
|
||||
|
||||
void __iomem * addr;
|
||||
|
||||
/*file open function*/
|
||||
int ioreg_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
/* device structure pointer assgined to file private data pointer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*file release function*/
|
||||
int ioreg_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ioctl device control function */
|
||||
static long ioreg_ioctl(struct file *filp, u32 cmd, unsigned long arg)
|
||||
{
|
||||
|
||||
u32 val;
|
||||
|
||||
|
||||
switch ((int)cmd)
|
||||
{
|
||||
|
||||
case IOCTL_MMAPREG:
|
||||
get_user(val, (unsigned long *)arg);
|
||||
addr = ioremap(val, 4096);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
default:
|
||||
return - EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t ioreg_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
|
||||
if (copy_to_user(buf, (void *)(addr), size))
|
||||
{
|
||||
|
||||
return -EFAULT;
|
||||
}
|
||||
iounmap(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t ioreg_write(struct file *filp,const char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
if(copy_from_user((void *)(addr), buf, size))
|
||||
{
|
||||
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
iounmap(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*file operation structure*/
|
||||
static const struct file_operations ioreg_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = ioreg_open,
|
||||
.read = ioreg_read,
|
||||
.write = ioreg_write,
|
||||
.unlocked_ioctl = ioreg_ioctl,
|
||||
.release = ioreg_release,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static struct miscdevice ioreg_miscdev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = DEVICE_NAME,
|
||||
.fops = &ioreg_fops,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int __init ioreg_module_init(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
|
||||
ret = misc_register(&ioreg_miscdev);
|
||||
if(ret)
|
||||
{
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
printk(KERN_EMERG "ioreg_module_init ok ");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* module unload function*/
|
||||
static void __exit ioreg_module_exit(void)
|
||||
{
|
||||
|
||||
misc_deregister(&ioreg_miscdev);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* a simple char device driver: ExtInt without mutex
|
||||
*
|
||||
* Copyright (C) 2014 Barry Song (baohua@kernel.org)
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
|
||||
MODULE_AUTHOR ("lte team");
|
||||
MODULE_DESCRIPTION ("FRAME_SYNC driver module" );
|
||||
MODULE_LICENSE ("GPL");
|
||||
module_init(ioreg_module_init);
|
||||
module_exit(ioreg_module_exit);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,288 +0,0 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <linux/mm.h>//remap_pfn_range
|
||||
|
||||
/* 主设备号 */
|
||||
#define BSP_DEV_MAJOR 0
|
||||
/* 主设备名 */
|
||||
#define BSP_DEV_NAME "mem_dump"
|
||||
|
||||
/* 模块加载函数 */
|
||||
static int osp_mem_init(void);
|
||||
/* 模块卸载函数 */
|
||||
static void osp_mem_exit(void);
|
||||
/* 打开设备函数 */
|
||||
int mem_bsp_open(struct inode *inode, struct file *filp);
|
||||
/* 释放设备函数 */
|
||||
int mem_bsp_release(struct inode *inode, struct file *filp);
|
||||
/* 读函数 */
|
||||
static ssize_t mem_bsp_read (struct file *filp, __user char *buf, size_t count, loff_t *f_pos);
|
||||
/* ioctl函数 */
|
||||
long mem_bsp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
/* mmap函数 */
|
||||
int mem_bsp_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
/* 写函数 */
|
||||
ssize_t mem_bsp_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
|
||||
|
||||
|
||||
|
||||
/******************************* 局部宏定义 ***********************************/
|
||||
/* bsp 主设备号 */
|
||||
|
||||
|
||||
typedef struct mem_struct{
|
||||
int g_s32BspDevMajor ;
|
||||
unsigned int g_u32CacheCoherent;
|
||||
struct cdev g_struBspDev;
|
||||
struct class *cls;
|
||||
dev_t g_devno;
|
||||
struct device *parent;
|
||||
struct device *this_device;
|
||||
|
||||
}mem_st;
|
||||
|
||||
|
||||
/******************************* 函数实现 *************************************/
|
||||
/*******************************************************************************
|
||||
* 函数名: mem_init
|
||||
* 描述: 模块加载时的入口函数
|
||||
* 相关文档:
|
||||
* 函数存储类型:int
|
||||
* 参数: 无
|
||||
* 返回值:
|
||||
* 0 成功
|
||||
* <0 失败
|
||||
* 说明:具体失败参考Linux错误信息头文件
|
||||
*******************************************************************************/
|
||||
|
||||
static mem_st mem_dev ={
|
||||
.g_s32BspDevMajor = 0,
|
||||
.g_u32CacheCoherent = 0,
|
||||
.g_devno = 0,
|
||||
|
||||
|
||||
};
|
||||
|
||||
static struct file_operations g_struBspOp = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = mem_bsp_read,
|
||||
.write = mem_bsp_write,
|
||||
.open = mem_bsp_open,
|
||||
.release = mem_bsp_release,
|
||||
.mmap = mem_bsp_mmap,
|
||||
.unlocked_ioctl = mem_bsp_ioctl,
|
||||
};
|
||||
|
||||
static int osp_mem_init(void)
|
||||
{
|
||||
/*函数调用结果*/
|
||||
int result;
|
||||
/*设备编号*/
|
||||
dev_t devno;
|
||||
|
||||
printk("bsp_init.\n");
|
||||
|
||||
/* 获取设备号 */
|
||||
if (0 == mem_dev.g_s32BspDevMajor)
|
||||
{
|
||||
/* 分配设备区域 */
|
||||
result = alloc_chrdev_region(&devno, 0, 1, BSP_DEV_NAME);
|
||||
|
||||
/* 判断返回值 */
|
||||
if (result < 0)
|
||||
{
|
||||
printk(KERN_WARNING "bsp: alloc_chrdev_region error! errno = %d\n", result);
|
||||
return result;
|
||||
}
|
||||
mem_dev.g_devno = devno;
|
||||
/* 保存主设备号信息 */
|
||||
mem_dev.g_s32BspDevMajor = MAJOR(devno);
|
||||
|
||||
/* 初始化dev变量 */
|
||||
cdev_init(&(mem_dev.g_struBspDev), &g_struBspOp);
|
||||
/* 设备dev相应变量值 */
|
||||
mem_dev.g_struBspDev.owner = THIS_MODULE;
|
||||
mem_dev.g_struBspDev.ops = &g_struBspOp;
|
||||
/* 向系统增加dev设备 */
|
||||
result = cdev_add(&mem_dev.g_struBspDev, devno, 1);
|
||||
if (result < 0)
|
||||
{
|
||||
printk ("cdev_add error!errno = %d", result);
|
||||
}
|
||||
|
||||
// ret = device_create_file(ucp_smem_miscdev.this_device, &dev_attr_ucp_smem);
|
||||
mem_dev.cls = class_create(THIS_MODULE, "mem_dump");
|
||||
device_create(mem_dev.cls, NULL, devno, NULL, "mem_dump");
|
||||
|
||||
printk("bsp module init success!\n");
|
||||
/* 返回成功 */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("bsp module already init!\n");
|
||||
/* 返回 */
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: ad9371_exit
|
||||
* 描述: 模块卸载函数
|
||||
* 相关文档:
|
||||
* 函数存储类型:void
|
||||
* 参数: 无
|
||||
* 返回值: 无
|
||||
* 说明:
|
||||
*******************************************************************************/
|
||||
static void osp_mem_exit(void)
|
||||
{
|
||||
/* 判断是否执行过模块加载 */
|
||||
if(mem_dev.g_s32BspDevMajor > 0)
|
||||
{
|
||||
/* 删除该字符设备 */
|
||||
device_destroy(mem_dev.cls, mem_dev.g_devno);
|
||||
class_destroy(mem_dev.cls);
|
||||
cdev_del(&(mem_dev.g_struBspDev));
|
||||
/* 释放已分配的空间 */
|
||||
unregister_chrdev_region(MKDEV(mem_dev.g_s32BspDevMajor, 0), 1);
|
||||
/* 清空主设备号 */
|
||||
mem_dev.g_s32BspDevMajor = 0;
|
||||
/* 调试信息输出 */
|
||||
printk("bsp module cleanup success!\n");
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: ad9731_bsp_open
|
||||
* 描述: 打开文件
|
||||
* 相关文档:
|
||||
* 函数存储类型:int
|
||||
* 参数:
|
||||
*
|
||||
* 参数名 类型 输入/输出 描述
|
||||
* -------- ---- --- -----------
|
||||
* inode struct inode* input 文件节点结构
|
||||
* filp struct file* input 文件结构
|
||||
* 返回值:
|
||||
* 0 成功
|
||||
* 说明:
|
||||
*******************************************************************************/
|
||||
int mem_bsp_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: ad9731_bsp_release
|
||||
* 描述: 关闭文件
|
||||
* 相关文档:
|
||||
* 函数存储类型:int
|
||||
* 参数:
|
||||
*
|
||||
* 参数名 类型 输入/输出 描述
|
||||
* -------- ---- --- -----------
|
||||
* inode struct inode* input 文件节点结构
|
||||
* filp struct file* input 文件结构
|
||||
* 返回值:
|
||||
* 0 成功
|
||||
* 说明:
|
||||
*******************************************************************************/
|
||||
int mem_bsp_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
/* 操作成功 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: ad9731_bsp_read ()
|
||||
*
|
||||
* 描述: 读操作。
|
||||
* 相关文档: <描述此函数的相关协议名称、版本及在协议中的位置>
|
||||
* 函数存储类型:
|
||||
|
||||
*******************************************************************************/
|
||||
static ssize_t mem_bsp_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: ad9731_bsp_write ()
|
||||
*
|
||||
* 描述: 写操作。
|
||||
* 相关文档: <描述此函数的相关协议名称、版本及在协议中的位置>
|
||||
* 函数存储类型:
|
||||
|
||||
*******************************************************************************/
|
||||
ssize_t mem_bsp_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: ad9731_bsp_ioctl
|
||||
* 描述: IO控制
|
||||
* 相关文档:
|
||||
* 函数存储类型:int
|
||||
* 参数:
|
||||
|
||||
*******************************************************************************/
|
||||
long mem_bsp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 函数名: mem_bsp_mmap
|
||||
* 描述: IO内存映射
|
||||
* 相关文档:
|
||||
* 函数存储类型:int
|
||||
* 参数:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
int mem_bsp_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
/* 设置IO标志 */
|
||||
|
||||
vma->vm_flags |= VM_IO;
|
||||
|
||||
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
printk("mmap start\n\r");
|
||||
|
||||
/* 建立映射 */
|
||||
if (remap_pfn_range(vma,
|
||||
vma->vm_start,
|
||||
vma->vm_pgoff,
|
||||
vma->vm_end-vma->vm_start,
|
||||
vma->vm_page_prot) < 0)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MODULE_AUTHOR ("mr yang");
|
||||
MODULE_DESCRIPTION ("mem_dump" );
|
||||
MODULE_LICENSE ("GPL");
|
||||
module_init(osp_mem_init);
|
||||
module_exit(osp_mem_exit);
|
||||
|
||||
/******************************* 源文件结束 ***********************************/
|
||||
|
@ -1,25 +0,0 @@
|
||||
export ARCH=arm64
|
||||
export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
#KERNELDIR = /public/liweihua/workspace/linux-5.0.21
|
||||
KERNELDIR = /public/liweihua/workspace/linux-5.10.165
|
||||
|
||||
OBJ = ARM_STC
|
||||
|
||||
PWD = $(shell pwd)
|
||||
# Kernel modules
|
||||
ifeq ($(OBJ),ARM_STC)
|
||||
obj-m = stc.o
|
||||
#mycache-objs = osp_sm_ddr.o cache.o
|
||||
stc-y := stc-dev.o
|
||||
endif
|
||||
|
||||
# Specify flags for the module compilation.
|
||||
ccflags-y = -g -O2
|
||||
#INCLUDE += -l./../../common/
|
||||
build: kernel_modules
|
||||
kernel_modules:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
|
@ -1,357 +0,0 @@
|
||||
/*
|
||||
* Driver for stc module.
|
||||
*
|
||||
* Copyright (C) 2022, liweihua@smartlogictech.com
|
||||
* Copyright 2022
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "stc_def.h"
|
||||
|
||||
#define UCP4008_STC_MODULE_VERSION ("V1.0")
|
||||
#define UCP4008_STC_DEVICE_NAME "stc_irq"
|
||||
|
||||
struct stc_driver g_stc_drv;
|
||||
|
||||
static irqreturn_t stc_tod_1pps_handler(int irqid, void *param)
|
||||
{
|
||||
struct stc_driver *pirqstc = param;
|
||||
|
||||
__raw_writel(0x1,pirqstc->io_base_addr + 4); //clear int
|
||||
pirqstc->irq_1pps_tod_cnt++;
|
||||
pirqstc->cond_1pps_tod = STC_TOD_1PPS;
|
||||
//printk("enter:%s,complete_cond = %d,\n",__func__,pirqstc->complete_cond);
|
||||
wake_up_interruptible(&pirqstc->pp1s_tod_queue);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stc_1pps_in_handler(int irqid, void *param)
|
||||
{
|
||||
struct stc_driver *pirqstc = param;
|
||||
|
||||
__raw_writel(0x2,pirqstc->io_base_addr + 4); //clear int
|
||||
pirqstc->irq_1pps_in_cnt++;
|
||||
pirqstc->cond_1pps_in = STC_EX_1PPS_IN;
|
||||
//printk("enter:%s,complete_cond = %d,\n",__func__,pirqstc->complete_cond);
|
||||
wake_up_interruptible(&pirqstc->pp1s_in_queue);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stc_hscc_dump_handler(int irqid, void *param)
|
||||
{
|
||||
struct stc_driver *pirqstc = param;
|
||||
|
||||
__raw_writel(0x4,pirqstc->io_base_addr + 4); //clear int
|
||||
pirqstc->irq_hscc_dump_cnt++;
|
||||
pirqstc->cond_hscc_dump = STC_HSCC_DUMP;
|
||||
//printk("enter:%s,complete_cond = %d,\n",__func__,pirqstc->complete_cond);
|
||||
wake_up_interruptible(&pirqstc->hscc_dump_queue);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int stc_open(struct inode* inode, struct file* file)
|
||||
{
|
||||
printk(KERN_INFO "[%s]\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t stc_read(struct file* file, char __user* buf, size_t size, loff_t* pos)
|
||||
{
|
||||
sint32 ret;
|
||||
uint32 cond_value;
|
||||
|
||||
if(STC_TOD_1PPS == size)
|
||||
{
|
||||
ret = wait_event_interruptible(g_stc_drv.pp1s_tod_queue, g_stc_drv.cond_1pps_tod);
|
||||
cond_value = g_stc_drv.irq_1pps_tod_cnt;
|
||||
g_stc_drv.cond_1pps_tod = STC_INT_RESERVED;
|
||||
}
|
||||
else if(STC_EX_1PPS_IN == size)
|
||||
{
|
||||
ret = wait_event_interruptible(g_stc_drv.pp1s_in_queue, g_stc_drv.cond_1pps_in);
|
||||
cond_value = g_stc_drv.irq_1pps_in_cnt;
|
||||
g_stc_drv.cond_1pps_in = STC_INT_RESERVED;
|
||||
}
|
||||
else if(STC_HSCC_DUMP == size)
|
||||
{
|
||||
ret = wait_event_interruptible(g_stc_drv.hscc_dump_queue, g_stc_drv.cond_hscc_dump);
|
||||
cond_value = g_stc_drv.irq_hscc_dump_cnt;
|
||||
g_stc_drv.cond_hscc_dump = STC_INT_RESERVED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
printk("exe:%s error!\n",__func__);
|
||||
return FAILURE;
|
||||
}
|
||||
ret = copy_to_user(buf, &cond_value, sizeof(uint32));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t stc_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sint64 stc_ioctl(struct file* file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
sint32 s32Ret = SUCCESS;
|
||||
stc_int_type_e int_type;
|
||||
struct stc_driver *stc_drv = &g_stc_drv;
|
||||
uint32 irq_enable = __raw_readl(g_stc_drv.io_base_addr + 8);
|
||||
|
||||
printk("enter:%s\n",__func__);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case STC_INT_CFG:
|
||||
{
|
||||
s32Ret = copy_from_user(&int_type, (void __user*)arg, sizeof(stc_int_type_e));
|
||||
if(s32Ret != 0)
|
||||
{
|
||||
printk(KERN_INFO "[%s]Copy user data failed!\n", __func__);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
switch(int_type)
|
||||
{
|
||||
case STC_TOD_1PPS:
|
||||
{
|
||||
s32Ret = request_irq(stc_drv->irq_1pps_tod, stc_tod_1pps_handler, IRQF_SHARED, "tod_1pps", (void *)stc_drv);
|
||||
if(s32Ret != SUCCESS)
|
||||
{
|
||||
free_irq(stc_drv->irq_1pps_tod, stc_drv);
|
||||
printk(KERN_INFO "[%s]irq_ipps_tod request error!\n", __func__);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
irq_enable |= 1;
|
||||
__raw_writel(irq_enable,g_stc_drv.io_base_addr + 8); //
|
||||
break;
|
||||
}
|
||||
case STC_EX_1PPS_IN:
|
||||
{
|
||||
s32Ret = request_irq(stc_drv->irq_1pps_in, stc_1pps_in_handler, IRQF_SHARED, "1pps_in", (void *)stc_drv);
|
||||
if(s32Ret != SUCCESS)
|
||||
{
|
||||
free_irq(stc_drv->irq_1pps_in, stc_drv);
|
||||
printk(KERN_INFO "[%s]irq_ipps_in request error!\n", __func__);
|
||||
return FAILURE;
|
||||
}
|
||||
printk(KERN_INFO "[%s]enable irq_ipps_in int!\n", __func__);
|
||||
irq_enable |= 2;
|
||||
__raw_writel(irq_enable,g_stc_drv.io_base_addr + 8); //
|
||||
break;
|
||||
}
|
||||
case STC_HSCC_DUMP:
|
||||
{
|
||||
s32Ret = request_irq(stc_drv->irq_hscc_dump, stc_hscc_dump_handler, IRQF_SHARED,"hscc_dump" ,(void *)stc_drv);
|
||||
if(s32Ret != SUCCESS)
|
||||
{
|
||||
free_irq(stc_drv->irq_hscc_dump, stc_drv);
|
||||
printk(KERN_INFO "[%s]irq_hscc_dump request error!\n", __func__);
|
||||
return FAILURE;
|
||||
}
|
||||
irq_enable |= 4;
|
||||
__raw_writel(irq_enable,g_stc_drv.io_base_addr + 8); //
|
||||
break;
|
||||
}
|
||||
default:break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
s32Ret = FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s32Ret;
|
||||
}
|
||||
|
||||
static int stc_release(struct inode* inode, struct file* file)
|
||||
{
|
||||
printk(KERN_INFO "[%s]realease \n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations stc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = stc_open,
|
||||
.read = stc_read,
|
||||
.write = stc_write,
|
||||
.release = stc_release,
|
||||
.unlocked_ioctl = stc_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice g_stc_dev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "stc_dev",
|
||||
.fops = &stc_fops,
|
||||
};
|
||||
|
||||
#if 0
|
||||
static int stc_module_init(void)
|
||||
{
|
||||
sint32 iRet;
|
||||
uint32 u32idx;
|
||||
|
||||
iRet = misc_register(&g_stc_dev);
|
||||
if(iRet != SUCCESS)
|
||||
{
|
||||
printk("misc_register error! iRet = %d\n", iRet);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&g_stc_drv, 0, sizeof(struct stc_driver));
|
||||
|
||||
g_stc_drv.irq_ipps_in = UCP4008_IRQ_1PPS_IN;
|
||||
g_stc_drv.irq_hscc_dump = UCP4008_IRQ_HSCC_DUMP;
|
||||
g_stc_drv.irq_ipps_tod = UCP4008_IRQ_1PPS_TOD;
|
||||
g_stc_drv.irq_ipps_in_cnt = 0;
|
||||
g_stc_drv.irq_hscc_dump_cnt = 0;
|
||||
g_stc_drv.irq_ipps_tod_cnt = 0;
|
||||
|
||||
init_waitqueue_head(&g_stc_drv.complete_queue);
|
||||
g_stc_drv.complete_cond = STC_INT_RESERVED;
|
||||
|
||||
g_stc_drv.io_base_addr = ioremap(STC_REG_BASE_ADDR,STC_REG_LEN);
|
||||
|
||||
//init timer
|
||||
#if 0
|
||||
init_timer(&g_stc_drv.avcn_timer_list);
|
||||
|
||||
setup_timer(&g_stc_drv.avcn_timer_list, avcn_debounce_timer, GPIO_INT_FUNC_RESET);
|
||||
#else
|
||||
//timer_setup(&g_stc_drv.avcn_timer_list, avcn_debounce_timer, 0);
|
||||
#endif
|
||||
printk(KERN_INFO "[%s] module version %s init...\n", __func__, UCP4008_STC_MODULE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stc_module_exit(void)
|
||||
{
|
||||
misc_deregister(&g_stc_dev);
|
||||
|
||||
free_irq(g_stc_drv.irq_ipps_in , &g_stc_drv);
|
||||
free_irq(g_stc_drv.irq_ipps_tod , &g_stc_drv);
|
||||
free_irq(g_stc_drv.irq_hscc_dump , &g_stc_drv);
|
||||
|
||||
printk(KERN_INFO "[%s] module version %s exit...\n", __func__, UCP4008_STC_MODULE_VERSION);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int smartlogic_stc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res_common;
|
||||
struct device *dev = &pdev->dev;
|
||||
int i, irq, iRet;
|
||||
int irq_no[3];
|
||||
|
||||
printk("enter:%s\n",__func__);
|
||||
|
||||
iRet = misc_register(&g_stc_dev);
|
||||
if(iRet != SUCCESS)
|
||||
{
|
||||
printk("misc_register error! iRet = %d\n", iRet);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "failed to get irq index %d\n", i);
|
||||
return -ENODEV;
|
||||
}
|
||||
irq_no[i] = irq;
|
||||
}
|
||||
|
||||
g_stc_drv.irq_1pps_tod = irq_no[0];
|
||||
g_stc_drv.irq_1pps_in = irq_no[1];
|
||||
g_stc_drv.irq_hscc_dump = irq_no[2];
|
||||
|
||||
res_common = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res_common)
|
||||
{
|
||||
dev_err(&pdev->dev, "memory resource not found");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_stc_drv.io_base_addr = devm_ioremap_resource(dev, res_common);
|
||||
if (IS_ERR(g_stc_drv.io_base_addr))
|
||||
{
|
||||
return PTR_ERR(g_stc_drv.io_base_addr);
|
||||
}
|
||||
|
||||
init_waitqueue_head(&g_stc_drv.pp1s_tod_queue);
|
||||
init_waitqueue_head(&g_stc_drv.pp1s_in_queue);
|
||||
init_waitqueue_head(&g_stc_drv.hscc_dump_queue);
|
||||
g_stc_drv.cond_1pps_tod = STC_INT_RESERVED;
|
||||
g_stc_drv.cond_1pps_in = STC_INT_RESERVED;
|
||||
g_stc_drv.cond_hscc_dump = STC_INT_RESERVED;
|
||||
g_stc_drv.irq_1pps_tod_cnt = 0;
|
||||
g_stc_drv.irq_1pps_in_cnt = 0;
|
||||
g_stc_drv.irq_hscc_dump_cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smartlogic_stc_remove(struct platform_device *pdev)
|
||||
{
|
||||
misc_deregister(&g_stc_dev);
|
||||
|
||||
free_irq(g_stc_drv.irq_1pps_in , &g_stc_drv);
|
||||
free_irq(g_stc_drv.irq_1pps_tod , &g_stc_drv);
|
||||
free_irq(g_stc_drv.irq_hscc_dump , &g_stc_drv);
|
||||
|
||||
printk(KERN_INFO "[%s] module version %s exit...\n", __func__, UCP4008_STC_MODULE_VERSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id smartlogic_stc_match[] = {
|
||||
{ .compatible = "smartlogic,stc" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, smartlogic_stc_match);
|
||||
|
||||
static struct platform_driver smartlogic_stc_driver = {
|
||||
.driver = {
|
||||
.name = "smartlogic_stc",
|
||||
.of_match_table = smartlogic_stc_match,
|
||||
},
|
||||
.probe = smartlogic_stc_probe,
|
||||
.remove = smartlogic_stc_remove,
|
||||
};
|
||||
module_platform_driver(smartlogic_stc_driver);
|
||||
|
||||
MODULE_AUTHOR("liweihua@smartlogictech.com");
|
||||
MODULE_DESCRIPTION ("Smartlogictech STC module driver!");
|
||||
MODULE_LICENSE ("GPL");
|
||||
|
@ -1,69 +0,0 @@
|
||||
#ifndef _STC_DEF_H_
|
||||
#define _STC_DEF_H_
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h> /*声明printk()这个内核态的函数*/
|
||||
#include <linux/fs.h> /*文件系统有关的,结构体file_operations也在fs头文件定义*/
|
||||
#include <linux/init.h> /*init和exit相关宏*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/irq.h> /*linux中断定义*/
|
||||
#include <asm/irq.h>
|
||||
#include <linux/interrupt.h> /*包含与中断相关的大部分宏及结构体的定义,request_irq()等*/
|
||||
#include <asm/uaccess.h> /*linux中的用户态内存交互函数,copy_from_user(),copy_to_user()等*/
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/miscdevice.h> /*misc混合设备注册与注销*/
|
||||
#include <asm/io.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
typedef char sint8;
|
||||
typedef unsigned char uint8;
|
||||
typedef int sint32;
|
||||
typedef unsigned int uint32;
|
||||
typedef long sint64;
|
||||
typedef unsigned long uint64;
|
||||
|
||||
|
||||
#define SUCCESS (0)
|
||||
#define FAILURE (-1)
|
||||
#define IRQ_EXCEPTION (0xFFFFFF)
|
||||
|
||||
#define STC_MODULE_MAGIC 'g'
|
||||
#define STC_INT_CFG _IOWR(STC_MODULE_MAGIC, 0x01, uint32)
|
||||
|
||||
#define STC_REG_BASE_ADDR (0x08568000ull) //STC鍩哄湴鍧€
|
||||
#define STC_REG_LEN (0x08000)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STC_INT_RESERVED = 0, /* Reserved*/ /* Reserved*/
|
||||
STC_TOD_1PPS, /* stc 1pps*/
|
||||
STC_EX_1PPS_IN, /* external 1pps */
|
||||
STC_HSCC_DUMP = 4 /* HSCC_DUMP */
|
||||
} stc_int_type_e;
|
||||
|
||||
struct stc_driver{
|
||||
sint32 irq_1pps_tod;
|
||||
sint32 irq_1pps_in;
|
||||
sint32 irq_hscc_dump;
|
||||
uint32 irq_1pps_tod_cnt;
|
||||
uint32 irq_1pps_in_cnt;
|
||||
uint32 irq_hscc_dump_cnt;
|
||||
stc_int_type_e cond_1pps_tod;
|
||||
stc_int_type_e cond_1pps_in;
|
||||
stc_int_type_e cond_hscc_dump;
|
||||
wait_queue_head_t pp1s_tod_queue;
|
||||
wait_queue_head_t pp1s_in_queue;
|
||||
wait_queue_head_t hscc_dump_queue;
|
||||
void __iomem *io_base_addr;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
PWD := $(shell pwd)
|
||||
|
||||
#KERNELDIR := /public/liweihua/workspace/linux-5.0.21
|
||||
KERNELDIR := /public/liweihua/workspace/linux-5.10.165
|
||||
|
||||
obj-m := tsc.o
|
||||
|
||||
modules:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
modules_install:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
|
||||
|
||||
clean:
|
||||
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers *.order irq-test
|
||||
|
||||
.PHONY: modules modules_install clean
|
||||
|
@ -1,67 +0,0 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#define ARMV8_PMCR_MASK 0x3f
|
||||
#define ARMV8_PMCR_E (1 << 0)
|
||||
#define ARMV8_PMCR_LC (1 << 6)
|
||||
|
||||
static inline u32 armv8pmu_pmcr_read(void)
|
||||
{
|
||||
u64 val = 0;
|
||||
asm volatile("mrs %0, pmcr_el0" : "=r" (val));
|
||||
return (u32)val;
|
||||
}
|
||||
static inline void armv8pmu_pmcr_write(u32 val)
|
||||
{
|
||||
val &= ARMV8_PMCR_MASK;
|
||||
isb();
|
||||
asm volatile("msr pmcr_el0, %0" : : "r" ((u64)val));
|
||||
}
|
||||
|
||||
static inline long long armv8_read_CNTPCT_EL0(void)
|
||||
{
|
||||
long long val;
|
||||
asm volatile("mrs %0, CNTVCT_EL0" : "=r" (val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
enable_cpu_counters(void* data)
|
||||
{
|
||||
asm volatile("msr pmuserenr_el0, %0" : : "r"(0xf));
|
||||
armv8pmu_pmcr_write(ARMV8_PMCR_LC|ARMV8_PMCR_E);
|
||||
asm volatile("msr PMCNTENSET_EL0, %0" :: "r" ((u32)(1<<31)));
|
||||
armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E|ARMV8_PMCR_LC);
|
||||
printk("\nCPU:%d ", smp_processor_id());
|
||||
}
|
||||
|
||||
static void
|
||||
disable_cpu_counters(void* data)
|
||||
{
|
||||
printk(KERN_INFO "\ndisabling user-mode PMU access on CPU #%d",
|
||||
smp_processor_id());
|
||||
|
||||
armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E);
|
||||
asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)0));
|
||||
}
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
on_each_cpu(enable_cpu_counters, NULL, 1);
|
||||
printk(KERN_INFO "Enable Access PMU Initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
on_each_cpu(disable_cpu_counters, NULL, 1);
|
||||
printk(KERN_INFO "Access PMU Disabled");
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("titan");
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
|
||||
KERN_DIR = /public/liweihua/workspace/linux-5.0.21
|
||||
|
||||
all:
|
||||
make -C ${KERN_DIR} M=`pwd` modules
|
||||
|
||||
clean:
|
||||
make -C ${KERN_DIR} M=`pwd` modules clean
|
||||
rm -rf modules.order
|
||||
|
||||
obj-m += ucp_2_revmem.o
|
||||
|
@ -1,3 +0,0 @@
|
||||
export ARCH=arm64
|
||||
export CROSS_COMPILE=/public/liweihua/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
make
|
@ -1,325 +0,0 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <linux/async_tx.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "ucp_2_revmem.h"
|
||||
|
||||
/*暂时将ucp_mem的主设备号定义为10 */
|
||||
|
||||
typedef struct tag_OSP_CACHE_REV
|
||||
{
|
||||
unsigned int phy_addr;
|
||||
unsigned int len;
|
||||
}OSP_CACHE_REV;
|
||||
|
||||
struct ucp_2_rev_device{
|
||||
struct device *dev;
|
||||
struct miscdevice *miscdev;
|
||||
void __iomem *vir_head;
|
||||
unsigned int phy_head;
|
||||
};
|
||||
|
||||
struct ucp_2_rev_device *ucp_2_rev_dev;
|
||||
|
||||
#define DEVICE_NAME "ucp_2_revmem"
|
||||
//#define DEVICE_NAME "ucp_2_mmap"
|
||||
|
||||
|
||||
#define IOCTL_CACHE_INVALID _IO('k',0x10)
|
||||
#define IOCTL_CACHE_FLUSH _IO('k',0x20)
|
||||
#define IOCTL_SET_CACHE _IO('k',0x30)
|
||||
#define IOCTL_SET_NOCACHE _IO('k',0x40)
|
||||
|
||||
#define UP_ALIGNED(num, n) (((num) + (n) - 1) & (~((n) - 1)))
|
||||
|
||||
#define REV_WITH_CACHE 2
|
||||
#define REV_WITH_NOCACHE 3
|
||||
|
||||
int is_cached=0;
|
||||
|
||||
extern void arch_sync_dma_for_device_p(struct device *dev, void *addr,
|
||||
size_t size, enum dma_data_direction dir);
|
||||
extern void arch_sync_dma_for_cpu_p(struct device *dev, void *addr,
|
||||
size_t size, enum dma_data_direction dir);
|
||||
|
||||
/*file open function*/
|
||||
int ucp_2_revmem_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
/* device structure pointer assgined to file private data pointer */
|
||||
printk("enter %s !!!\n",__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t ucp_2_revmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*file release function*/
|
||||
int ucp_2_revmem_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ioctl device control function */
|
||||
static long ucp_2_revmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
OSP_CACHE_REV operation;
|
||||
void __iomem *vir;
|
||||
struct ucp_2_rev_device *rev_dev = ucp_2_rev_dev;
|
||||
struct miscdevice *miscdev = rev_dev->miscdev;
|
||||
|
||||
// printk("%s\n",miscdev->name);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case IOCTL_SET_CACHE:
|
||||
is_cached = REV_WITH_CACHE;
|
||||
// dev_info(rev_dev->dev,"ioctl set with cache");
|
||||
break;
|
||||
case IOCTL_SET_NOCACHE:
|
||||
is_cached = REV_WITH_NOCACHE;
|
||||
// dev_info(rev_dev->dev,"ioctl set no cache");
|
||||
break;
|
||||
case IOCTL_CACHE_FLUSH:
|
||||
if(copy_from_user((void *)(&operation), (char *)arg, sizeof(OSP_CACHE_REV)))
|
||||
{
|
||||
dev_info(rev_dev->dev,"ioctl copy_from_user error");
|
||||
return - EINVAL;
|
||||
}
|
||||
|
||||
if(operation.phy_addr<=0 || operation.len <=0)
|
||||
{
|
||||
dev_info(rev_dev->dev,"ioctl user arg error");
|
||||
return - EINVAL;
|
||||
}
|
||||
|
||||
operation.len = UP_ALIGNED(operation.len,4);
|
||||
|
||||
// vir = ioremap_cache(operation.phy_addr,operation.len);
|
||||
vir = rev_dev->vir_head + (operation.phy_addr - rev_dev->phy_head);
|
||||
if(vir == NULL)
|
||||
{
|
||||
dev_info(rev_dev->dev,"ioctl vir error");
|
||||
return - EINVAL;
|
||||
}
|
||||
arch_sync_dma_for_device_p(rev_dev->dev, vir, operation.len, DMA_TO_DEVICE);
|
||||
break;
|
||||
|
||||
case IOCTL_CACHE_INVALID:
|
||||
if(copy_from_user((void *)(&operation), (char *)arg, sizeof(OSP_CACHE_REV)))
|
||||
{
|
||||
dev_info(rev_dev->dev,"ioctl copy_from_user error");
|
||||
return - EINVAL;
|
||||
}
|
||||
|
||||
if(operation.phy_addr<=0 || operation.len <=0)
|
||||
{
|
||||
dev_info(rev_dev->dev,"ioctl user arg error");
|
||||
return - EINVAL;
|
||||
}
|
||||
|
||||
operation.len = UP_ALIGNED(operation.len,4);
|
||||
|
||||
// vir = ioremap_cache(operation.phy_addr,operation.len);
|
||||
vir = rev_dev->vir_head + (operation.phy_addr - rev_dev->phy_head);
|
||||
if(vir == NULL)
|
||||
{
|
||||
dev_info(rev_dev->dev,"ioctl vir error");
|
||||
return - EINVAL;
|
||||
}
|
||||
arch_sync_dma_for_cpu_p(rev_dev->dev, vir, operation.len, DMA_FROM_DEVICE);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return - EINVAL;
|
||||
}
|
||||
// iounmap(vir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ucp_2_revmem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct ucp_2_rev_device *rev_dev = ucp_2_rev_dev;
|
||||
struct miscdevice *miscdev = rev_dev->miscdev;
|
||||
uint64_t offset = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
printk("enter %s !!!\n",__func__);
|
||||
|
||||
printk("ucp_revmem_mmap offset = %#llx,start = %#llx\n",offset,vma->vm_start);
|
||||
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_LOCKED;
|
||||
|
||||
if(offset < ARM_STACK_BASE_PHY_ADDR)
|
||||
{
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
}
|
||||
#if 0
|
||||
if(is_cached == REV_WITH_NOCACHE)
|
||||
{
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
}
|
||||
else if(is_cached == REV_WITH_CACHE)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_info(rev_dev->dev,"flag is_cached is error %d\n",is_cached);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
#endif
|
||||
if (remap_pfn_range(vma,
|
||||
vma->vm_start,
|
||||
vma->vm_pgoff,
|
||||
vma->vm_end-vma->vm_start,
|
||||
vma->vm_page_prot) < 0)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
// dev_info(rev_dev->dev,"ucp_revmem_mmap:%d ok\n",is_cached);
|
||||
printk("leave %s !!!\n",__func__);
|
||||
|
||||
is_cached = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*file operation structure*/
|
||||
static const struct file_operations ucp_2_revmem_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = ucp_2_revmem_open,
|
||||
.unlocked_ioctl = ucp_2_revmem_ioctl,
|
||||
.mmap = ucp_2_revmem_mmap,
|
||||
.release = ucp_2_revmem_release,
|
||||
};
|
||||
|
||||
static ssize_t ucp_2_revmem_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int len=0;
|
||||
|
||||
len += sprintf(buf+len, "%s\r\n", "ucp_2_mem attribute OK!");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(ucp_2_revmem, S_IRUGO, ucp_2_revmem_show, NULL);
|
||||
|
||||
static struct miscdevice ucp_2_revmem_miscdev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = DEVICE_NAME,
|
||||
.fops = &ucp_2_revmem_fops,
|
||||
};
|
||||
|
||||
static int __init ucp_2_revmem_module_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct miscdevice *misc_device;
|
||||
void __iomem * vir_addr;
|
||||
dma_addr_t phy_addr;
|
||||
int i;
|
||||
|
||||
ucp_2_rev_dev = (struct ucp_2_rev_device *)kzalloc(sizeof(*ucp_2_rev_dev), GFP_KERNEL);
|
||||
if (!ucp_2_rev_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
misc_device = &ucp_2_revmem_miscdev;
|
||||
ret = misc_register(&ucp_2_revmem_miscdev);
|
||||
if(ret)
|
||||
{
|
||||
goto misc_err;
|
||||
}
|
||||
|
||||
ret = device_create_file(ucp_2_revmem_miscdev.this_device, &dev_attr_ucp_2_revmem);
|
||||
if (ret)
|
||||
{
|
||||
goto attr_err;
|
||||
}
|
||||
ucp_2_rev_dev->dev = ucp_2_revmem_miscdev.this_device;
|
||||
ucp_2_rev_dev->miscdev = &ucp_2_revmem_miscdev;
|
||||
dev_set_drvdata(ucp_2_revmem_miscdev.this_device, ucp_2_rev_dev);
|
||||
|
||||
ucp_2_rev_dev->phy_head = UCP_2_APE_REV_MEM_START;
|
||||
ucp_2_rev_dev->vir_head = ioremap_cache(UCP_2_APE_REV_MEM_START,UCP_2_APE_REM_MEM_LEN);
|
||||
|
||||
dma_coerce_mask_and_coherent(ucp_2_rev_dev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
/*
|
||||
for(i = 0; i< 100; i++)
|
||||
{ //GFP_ATOMIC,GFP_KERNEL
|
||||
vir_addr = dma_alloc_coherent(ucp_2_rev_dev->dev, 0x64000, (dma_addr_t *)&phy_addr, GFP_ATOMIC);
|
||||
if(vir_addr == NULL)
|
||||
{
|
||||
printk("revmem dma_alloc_coherent error:%d\n",i);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
dev_info(ucp_2_rev_dev->dev,"ucp_2_revem_module_init ok\n");
|
||||
return 0;
|
||||
misc_err:
|
||||
device_remove_file(ucp_2_revmem_miscdev.this_device, &dev_attr_ucp_2_revmem);
|
||||
attr_err:
|
||||
misc_deregister(&ucp_2_revmem_miscdev);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* module unload function*/
|
||||
static void __exit ucp_2_revmem_module_exit(void)
|
||||
{
|
||||
device_remove_file(ucp_2_revmem_miscdev.this_device, &dev_attr_ucp_2_revmem);
|
||||
misc_deregister(&ucp_2_revmem_miscdev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* a simple char device driver: ExtInt without mutex
|
||||
*
|
||||
* Copyright (C) 2014 Barry Song (baohua@kernel.org)
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
|
||||
MODULE_AUTHOR ("lte team");
|
||||
MODULE_DESCRIPTION ("ucp_mem driver module" );
|
||||
MODULE_LICENSE ("GPL");
|
||||
module_init(ucp_2_revmem_module_init);
|
||||
module_exit(ucp_2_revmem_module_exit);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
#ifndef __HPP_REVMEM_H__
|
||||
#define __HPP_REVMEM_H__
|
||||
|
||||
|
||||
|
||||
|
||||
#define UCP_2_APE_REV_MEM_START 0x90000000
|
||||
#define UCP_2_APE_REV_MEM_BLOCK_SIZE 0x100000
|
||||
#define UCP_2_APE_REV_MEM_BLOCK_NUM 18
|
||||
/*#define HPP_APE_REM_MEM_LEN (HPP_APE_REV_MEM_BLOCK_NUM * HPP_APE_REV_MEM_BLOCK_SIZE)*/
|
||||
#define UCP_2_APE_REM_MEM_LEN 0x20000000
|
||||
|
||||
#define SHARE_MEM_BASE_PHY_ADDR 0x009D00000UL
|
||||
#define LEN_OF_SHARE_MEM 0x000800000UL
|
||||
#define SHARE_MEM_END_PHY_ADDR (SHARE_MEM_BASE_PHY_ADDR + LEN_OF_SHARE_MEM)
|
||||
|
||||
#define ARM_STACK_BASE_PHY_ADDR 0x0B8000000UL
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user