#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*函数原型*/ 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");