mirror of https://github.com/OpenIPC/firmware.git
				
				
				
			
		
			
				
	
	
		
			170 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Diff
		
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Diff
		
	
	
| 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 <linux/errno.h>
 | |
| +#include <linux/slab.h>
 | |
| +#include <linux/delay.h>
 | |
| +#include <linux/miscdevice.h>
 | |
| +#include <linux/platform_device.h>
 | |
| +#include <linux/dma-mapping.h>
 | |
| +#include <linux/fs.h>
 | |
| +#include <linux/file.h>
 | |
| +#include <linux/module.h>
 | |
| +#include <linux/mm.h>
 | |
| +#include <linux/syscalls.h>
 | |
| +
 | |
| +#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");
 |