diff -drupN a/drivers/misc/rmem.c b/drivers/misc/rmem.c --- a/drivers/misc/rmem.c 1970-01-01 03:00:00.000000000 +0300 +++ b/drivers/misc/rmem.c 2022-06-09 05:02:30.000000000 +0300 @@ -0,0 +1,165 @@ +/* + * rmem.c - Reserved memory driver for libimp. + * + * Copyright (C) 2012 Ingenic Semiconductor Co., 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RMEM_MAGIC 'r' +#define RMEM_CMD_FLUSH_CACHE _IOWR(RMEM_MAGIC, 0, struct rmem_flush_cache_info) +#define RMEM_CMD_RMEM_INFO _IOWR(RMEM_MAGIC, 1, struct rmem_info) + +struct rmem_info { + unsigned int vaddr; + unsigned int paddr; +}; +static struct rmem_info rmem_addr; + + +static struct miscdevice mdev; + +struct rmem_flush_cache_info { + unsigned int addr; + unsigned int len; + unsigned int dir; +}; + +static int rmem_open(struct inode *inode, struct file *filp) +{ + pr_debug("[%d:%d] %s\n", current->tgid, current->pid, __func__); + return 0; +} + +static int rmem_release(struct inode *inode, struct file *filp) +{ + pr_debug("[%d:%d] %s\n", current->tgid, current->pid, __func__); + return 0; +} + +static long rmem_cmd_flush_cache(long arg) +{ + struct rmem_flush_cache_info info; + long ret = 0; + if (copy_from_user(&info, (void *)arg, sizeof(info))) { + return -EFAULT; + } + + dma_cache_sync(NULL, (void *)info.addr, info.len, info.dir); + + return ret; +} + +static long rmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case RMEM_CMD_FLUSH_CACHE: + return rmem_cmd_flush_cache(arg); + case RMEM_CMD_RMEM_INFO: + if (copy_to_user((void *)arg, &rmem_addr, sizeof(struct rmem_info))) { + return -EFAULT; + } + break; + default: + pr_err("Unknown ioctl: 0x%.8X\n", cmd); + return -EINVAL; + } +} + +static int rmem_mmap(struct file *file, struct vm_area_struct *vma) +{ + vma->vm_flags |= VM_IO; + + pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; + pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; + + if (io_remap_pfn_range(vma,vma->vm_start, + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + rmem_addr.vaddr = vma->vm_start; + rmem_addr.paddr = vma->vm_pgoff * PAGE_SIZE; + + + return 0; +} + +static struct file_operations rmem_misc_fops = { + .open = rmem_open, + .release = rmem_release, + .unlocked_ioctl = rmem_ioctl, + .mmap = rmem_mmap, +}; + +static int rmem_probe(struct platform_device *pdev) +{ + int ret; + + + mdev.minor = MISC_DYNAMIC_MINOR; + mdev.name = "rmem"; + mdev.fops = &rmem_misc_fops; + + ret = misc_register(&mdev); + if (ret < 0) { + pr_err("rmem register failed\n"); + return -1; + } + + rmem_addr.vaddr = 0; + rmem_addr.paddr = 0; + + return 0; +} + +static int rmem_remove(struct platform_device *dev) +{ + return 0; +} + +static struct platform_driver rmem_driver = { + .probe = rmem_probe, + .remove = rmem_remove, + .driver = { + .name = "rmem", + }, +}; + +struct platform_device rmem_device = { + .name = "rmem", + .id = -1, + .resource = NULL, + .num_resources = 0, +}; + +static int __init rmem_init(void) +{ + platform_device_register(&rmem_device); + return platform_driver_register(&rmem_driver); +} + +static void __exit rmem_exit(void) +{ + platform_device_unregister(&rmem_device); + platform_driver_unregister(&rmem_driver); +} + +module_init(rmem_init); +module_exit(rmem_exit); + +MODULE_LICENSE("GPL v2");