yb_arm/driver/cache/osp_sm_ddr.c

533 lines
15 KiB
C
Raw Normal View History

2023-07-12 14:14:31 +08:00
#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>
/*<2A><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>*/
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
};
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD>*/
#define DEVICE_NAME_SM_DDR_CACHE "ucp_sm_ddr_cache"
#define DEVICE_NAME_SM_DDR_NONCACHE "ucp_sm_ddr_noncache"
/*<2A><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ*/
#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
/*<2A><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>С*/
#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 */
/*ȫ<>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>*/
/*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;
/*ע<><D7A2> <20><EFBFBD><E8B1B8><EFBFBD><EFBFBD>*/
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;
}
/*<2A><>/sys/class Ŀ¼<C4BF>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>*/
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;
/* <20><><EFBFBD><EFBFBD>IO<49><4F>־ */
/*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;
/* <20><><EFBFBD><EFBFBD>IO<49><4F>־ */
// 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");