diff --git a/device/config/chips/v851s/configs/fastboot_sl100_back/linux/config-4.9 b/device/config/chips/v851s/configs/fastboot_sl100_back/linux/config-4.9 index cae5b017d..09b04eb36 100755 --- a/device/config/chips/v851s/configs/fastboot_sl100_back/linux/config-4.9 +++ b/device/config/chips/v851s/configs/fastboot_sl100_back/linux/config-4.9 @@ -1127,6 +1127,7 @@ CONFIG_SUNXI_SYS_INFO=y CONFIG_DUMP_REG=y CONFIG_DUMP_REG_MISC=y # CONFIG_SUNXI_TIMER_TEST is not set +# CONFIG_MEM_OPERATION is not set # CONFIG_SUNXI_TRANSFORM is not set # CONFIG_SUNXI_DI is not set CONFIG_SUNXI_G2D=y diff --git a/device/config/chips/v851s3/configs/fastboot_sl100_front/board.dts b/device/config/chips/v851s3/configs/fastboot_sl100_front/board.dts index 5270aa528..821997078 100755 --- a/device/config/chips/v851s3/configs/fastboot_sl100_front/board.dts +++ b/device/config/chips/v851s3/configs/fastboot_sl100_front/board.dts @@ -41,6 +41,10 @@ }; reserved-memory { + wakeup_source: wakeup_source { + reg = <0x0 0x4307F000 0x0 0x00001000>; + no-map; + }; e907_fw: e907_fw { reg = <0x0 0x43080000 0x0 0x00190000>; }; diff --git a/device/config/chips/v851s3/configs/fastboot_sl100_front/linux/config-4.9 b/device/config/chips/v851s3/configs/fastboot_sl100_front/linux/config-4.9 index 0a13d8afd..150939705 100755 --- a/device/config/chips/v851s3/configs/fastboot_sl100_front/linux/config-4.9 +++ b/device/config/chips/v851s3/configs/fastboot_sl100_front/linux/config-4.9 @@ -1254,6 +1254,7 @@ CONFIG_SUNXI_SYS_INFO=y CONFIG_DUMP_REG=y CONFIG_DUMP_REG_MISC=y # CONFIG_SUNXI_TIMER_TEST is not set +CONFIG_MEM_OPERATION=y # CONFIG_SUNXI_TRANSFORM is not set # CONFIG_SUNXI_DI is not set CONFIG_SUNXI_G2D=y diff --git a/lichee/linux-4.9/drivers/char/Kconfig b/lichee/linux-4.9/drivers/char/Kconfig index 65154ddc2..836ad1870 100644 --- a/lichee/linux-4.9/drivers/char/Kconfig +++ b/lichee/linux-4.9/drivers/char/Kconfig @@ -596,6 +596,7 @@ source "drivers/char/sunxi-scr/Kconfig" source "drivers/char/sunxi-sysinfo/Kconfig" source "drivers/char/dump_reg/Kconfig" source "drivers/char/timer_test/Kconfig" +source "drivers/char/mem_operation/Kconfig" source "drivers/char/sunxi_tr/Kconfig" source "drivers/char/sunxi-di/Kconfig" source "drivers/char/sunxi_g2d/Kconfig" diff --git a/lichee/linux-4.9/drivers/char/Makefile b/lichee/linux-4.9/drivers/char/Makefile index 921907a95..e3636a46b 100644 --- a/lichee/linux-4.9/drivers/char/Makefile +++ b/lichee/linux-4.9/drivers/char/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o obj-$(CONFIG_ARCH_SUNXI) += sunxi-sysinfo/ obj-$(CONFIG_SUNXI_TIMER_TEST) += timer_test/ +obj-$(CONFIG_MEM_OPERATION) += mem_operation/ obj-$(CONFIG_DUMP_REG) += dump_reg/ obj-$(CONFIG_SUNXI_TRANSFORM) += sunxi_tr/ obj-y += sunxi-di/ diff --git a/lichee/linux-4.9/drivers/char/mem_operation/Kconfig b/lichee/linux-4.9/drivers/char/mem_operation/Kconfig new file mode 100755 index 000000000..50abf52b9 --- /dev/null +++ b/lichee/linux-4.9/drivers/char/mem_operation/Kconfig @@ -0,0 +1,10 @@ +# +# sunxi timer test configuration. +# + +config MEM_OPERATION + tristate "mem operation test driver" + default n + help + Nothing help. + diff --git a/lichee/linux-4.9/drivers/char/mem_operation/Makefile b/lichee/linux-4.9/drivers/char/mem_operation/Makefile new file mode 100755 index 000000000..9fd6e2cff --- /dev/null +++ b/lichee/linux-4.9/drivers/char/mem_operation/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_MEM_OPERATION) += mem_operation_drv.o + diff --git a/lichee/linux-4.9/drivers/char/mem_operation/mem_operation_drv.c b/lichee/linux-4.9/drivers/char/mem_operation/mem_operation_drv.c new file mode 100644 index 000000000..d3c3bdd8b --- /dev/null +++ b/lichee/linux-4.9/drivers/char/mem_operation/mem_operation_drv.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WEIGHT_ADDR 0x4307F000 // 权重加载的内存地址处 +#define MEM_ACCESS_RELEASE_PHYS_ADDR _IOR('M', 0, unsigned int) // 自定义ioctl命令,用于释放预留内存 + +static int major = 0; +static struct class *mem_operation_class; + +static int check_page_reserved(unsigned long addr) +{ + struct page *page; + + page = pfn_to_page(addr >> PAGE_SHIFT); // 将虚拟地址转换为页面索引,然后得到页面结构 + if (PageReserved(page)) { + printk(KERN_INFO "Page at address 0x%lx is reserved.\n", addr); + return 0; + } else { + printk(KERN_INFO "Page at address 0x%lx is not reserved.\n", addr); + return -1; + } +} + +static int mem_operation_drv_open (struct inode *node, struct file *file) +{ + printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); + return 0; +} + +static int mem_operation_drv_close (struct inode *node, struct file *file) +{ + printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); + return 0; +} + +static int mem_operation_drv_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long phy = WEIGHT_ADDR; + + if(check_page_reserved(WEIGHT_ADDR) < 0) + return -EINVAL; + + /* 设置属性: cache, buffer */ + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + /* map */ + if (remap_pfn_range(vma, vma->vm_start, phy >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + printk("mmap remap_pfn_range failed\n"); + return -ENOBUFS; + } + + return 0; +} + +static long mem_operation_drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + switch (cmd) { + case MEM_ACCESS_RELEASE_PHYS_ADDR: { + unsigned int mem_size; + + if (get_user(mem_size, (unsigned long __user *)arg)) + return -EFAULT; + + if(check_page_reserved(WEIGHT_ADDR) < 0) + return -EINVAL; + + memblock_free(WEIGHT_ADDR, mem_size); + free_reserved_area(__va(WEIGHT_ADDR), __va(WEIGHT_ADDR + mem_size), -1, "wakeup_source"); + printk("release phy addr: 0x%x, size: %d\n", WEIGHT_ADDR, mem_size); + break; + } + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static struct file_operations mem_operation_drv = { + .owner = THIS_MODULE, + .open = mem_operation_drv_open, + .release = mem_operation_drv_close, + .mmap = mem_operation_drv_mmap, + .unlocked_ioctl = mem_operation_drv_ioctl, +}; + +static int __init mem_operation_init(void) +{ + int err; + + printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); + major = register_chrdev(0, "mem_operation", &mem_operation_drv); /* /dev/mem_operation */ + + mem_operation_class = class_create(THIS_MODULE, "mem_operation_class"); + err = PTR_ERR(mem_operation_class); + if (IS_ERR(mem_operation_class)) { + printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); + unregister_chrdev(major, "mem_operation"); + return -1; + } + + device_create(mem_operation_class, NULL, MKDEV(major, 0), NULL, "mem_operation"); /* 设备节点: /dev/mem_operation */ + + return 0; +} + +static void __exit mem_operation_exit(void) +{ + printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); + device_destroy(mem_operation_class, MKDEV(major, 0)); + class_destroy(mem_operation_class); + unregister_chrdev(major, "mem_operation"); +} + +module_init(mem_operation_init); +module_exit(mem_operation_exit); +MODULE_LICENSE("GPL");