mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			230 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 13260f3ad2f348d5e866283819a9b87d4aea86b0 Mon Sep 17 00:00:00 2001
 | |
| From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 | |
| Date: Fri, 26 Jun 2015 14:27:06 +0200
 | |
| Subject: [PATCH 054/432] char: broadcom: Add vcio module
 | |
| MIME-Version: 1.0
 | |
| Content-Type: text/plain; charset=UTF-8
 | |
| Content-Transfer-Encoding: 8bit
 | |
| 
 | |
| Add module for accessing the mailbox property channel through
 | |
| /dev/vcio. Was previously in bcm2708-vcio.
 | |
| 
 | |
| Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
 | |
| ---
 | |
|  drivers/char/broadcom/Kconfig  |   6 ++
 | |
|  drivers/char/broadcom/Makefile |   1 +
 | |
|  drivers/char/broadcom/vcio.c   | 175 +++++++++++++++++++++++++++++++++
 | |
|  3 files changed, 182 insertions(+)
 | |
|  create mode 100644 drivers/char/broadcom/vcio.c
 | |
| 
 | |
| diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig
 | |
| index 4ef0d7af2bc7..cffd17df6a1b 100644
 | |
| --- a/drivers/char/broadcom/Kconfig
 | |
| +++ b/drivers/char/broadcom/Kconfig
 | |
| @@ -15,6 +15,12 @@ config BCM2708_VCMEM
 | |
|          help
 | |
|            Helper for videocore memory access and total size allocation.
 | |
|  
 | |
| +config BCM_VCIO
 | |
| +	tristate "Mailbox userspace access"
 | |
| +	depends on BCM2835_MBOX
 | |
| +	help
 | |
| +	  Gives access to the mailbox property channel from userspace.
 | |
| +
 | |
|  endif
 | |
|  
 | |
|  config BCM_VC_SM
 | |
| diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile
 | |
| index d0ad04f8e498..7d9cb3e0b1c3 100644
 | |
| --- a/drivers/char/broadcom/Makefile
 | |
| +++ b/drivers/char/broadcom/Makefile
 | |
| @@ -1,4 +1,5 @@
 | |
|  obj-$(CONFIG_BCM2708_VCMEM)	+= vc_mem.o
 | |
| +obj-$(CONFIG_BCM_VCIO)		+= vcio.o
 | |
|  obj-$(CONFIG_BCM_VC_SM)         += vc_sm/
 | |
|  
 | |
|  obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
 | |
| diff --git a/drivers/char/broadcom/vcio.c b/drivers/char/broadcom/vcio.c
 | |
| new file mode 100644
 | |
| index 000000000000..c19bc2075c77
 | |
| --- /dev/null
 | |
| +++ b/drivers/char/broadcom/vcio.c
 | |
| @@ -0,0 +1,175 @@
 | |
| +/*
 | |
| + *  Copyright (C) 2010 Broadcom
 | |
| + *  Copyright (C) 2015 Noralf Trønnes
 | |
| + *
 | |
| + * 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.
 | |
| + *
 | |
| + */
 | |
| +
 | |
| +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | |
| +
 | |
| +#include <linux/cdev.h>
 | |
| +#include <linux/device.h>
 | |
| +#include <linux/fs.h>
 | |
| +#include <linux/init.h>
 | |
| +#include <linux/ioctl.h>
 | |
| +#include <linux/module.h>
 | |
| +#include <linux/slab.h>
 | |
| +#include <linux/uaccess.h>
 | |
| +#include <soc/bcm2835/raspberrypi-firmware.h>
 | |
| +
 | |
| +#define MBOX_CHAN_PROPERTY 8
 | |
| +
 | |
| +#define VCIO_IOC_MAGIC 100
 | |
| +#define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
 | |
| +
 | |
| +static struct {
 | |
| +	dev_t devt;
 | |
| +	struct cdev cdev;
 | |
| +	struct class *class;
 | |
| +	struct rpi_firmware *fw;
 | |
| +} vcio;
 | |
| +
 | |
| +static int vcio_user_property_list(void *user)
 | |
| +{
 | |
| +	u32 *buf, size;
 | |
| +	int ret;
 | |
| +
 | |
| +	/* The first 32-bit is the size of the buffer */
 | |
| +	if (copy_from_user(&size, user, sizeof(size)))
 | |
| +		return -EFAULT;
 | |
| +
 | |
| +	buf = kmalloc(size, GFP_KERNEL);
 | |
| +	if (!buf)
 | |
| +		return -ENOMEM;
 | |
| +
 | |
| +	if (copy_from_user(buf, user, size)) {
 | |
| +		kfree(buf);
 | |
| +		return -EFAULT;
 | |
| +	}
 | |
| +
 | |
| +	/* Strip off protocol encapsulation */
 | |
| +	ret = rpi_firmware_property_list(vcio.fw, &buf[2], size - 12);
 | |
| +	if (ret) {
 | |
| +		kfree(buf);
 | |
| +		return ret;
 | |
| +	}
 | |
| +
 | |
| +	buf[1] = RPI_FIRMWARE_STATUS_SUCCESS;
 | |
| +	if (copy_to_user(user, buf, size))
 | |
| +		ret = -EFAULT;
 | |
| +
 | |
| +	kfree(buf);
 | |
| +
 | |
| +	return ret;
 | |
| +}
 | |
| +
 | |
| +static int vcio_device_open(struct inode *inode, struct file *file)
 | |
| +{
 | |
| +	try_module_get(THIS_MODULE);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static int vcio_device_release(struct inode *inode, struct file *file)
 | |
| +{
 | |
| +	module_put(THIS_MODULE);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static long vcio_device_ioctl(struct file *file, unsigned int ioctl_num,
 | |
| +			      unsigned long ioctl_param)
 | |
| +{
 | |
| +	switch (ioctl_num) {
 | |
| +	case IOCTL_MBOX_PROPERTY:
 | |
| +		return vcio_user_property_list((void *)ioctl_param);
 | |
| +	default:
 | |
| +		pr_err("unknown ioctl: %d\n", ioctl_num);
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +const struct file_operations vcio_fops = {
 | |
| +	.unlocked_ioctl = vcio_device_ioctl,
 | |
| +	.open = vcio_device_open,
 | |
| +	.release = vcio_device_release,
 | |
| +};
 | |
| +
 | |
| +static int __init vcio_init(void)
 | |
| +{
 | |
| +	struct device_node *np;
 | |
| +	static struct device *dev;
 | |
| +	int ret;
 | |
| +
 | |
| +	np = of_find_compatible_node(NULL, NULL,
 | |
| +				     "raspberrypi,bcm2835-firmware");
 | |
| +/* Uncomment this when we only boot with Device Tree
 | |
| +	if (!of_device_is_available(np))
 | |
| +		return -ENODEV;
 | |
| +*/
 | |
| +	vcio.fw = rpi_firmware_get(np);
 | |
| +	if (!vcio.fw)
 | |
| +		return -ENODEV;
 | |
| +
 | |
| +	ret = alloc_chrdev_region(&vcio.devt, 0, 1, "vcio");
 | |
| +	if (ret) {
 | |
| +		pr_err("failed to allocate device number\n");
 | |
| +		return ret;
 | |
| +	}
 | |
| +
 | |
| +	cdev_init(&vcio.cdev, &vcio_fops);
 | |
| +	vcio.cdev.owner = THIS_MODULE;
 | |
| +	ret = cdev_add(&vcio.cdev, vcio.devt, 1);
 | |
| +	if (ret) {
 | |
| +		pr_err("failed to register device\n");
 | |
| +		goto err_unregister_chardev;
 | |
| +	}
 | |
| +
 | |
| +	/*
 | |
| +	 * Create sysfs entries
 | |
| +	 * 'bcm2708_vcio' is used for backwards compatibility so we don't break
 | |
| +	 * userspace. Raspian has a udev rule that changes the permissions.
 | |
| +	 */
 | |
| +	vcio.class = class_create(THIS_MODULE, "bcm2708_vcio");
 | |
| +	if (IS_ERR(vcio.class)) {
 | |
| +		ret = PTR_ERR(vcio.class);
 | |
| +		pr_err("failed to create class\n");
 | |
| +		goto err_cdev_del;
 | |
| +	}
 | |
| +
 | |
| +	dev = device_create(vcio.class, NULL, vcio.devt, NULL, "vcio");
 | |
| +	if (IS_ERR(dev)) {
 | |
| +		ret = PTR_ERR(dev);
 | |
| +		pr_err("failed to create device\n");
 | |
| +		goto err_class_destroy;
 | |
| +	}
 | |
| +
 | |
| +	return 0;
 | |
| +
 | |
| +err_class_destroy:
 | |
| +	class_destroy(vcio.class);
 | |
| +err_cdev_del:
 | |
| +	cdev_del(&vcio.cdev);
 | |
| +err_unregister_chardev:
 | |
| +	unregister_chrdev_region(vcio.devt, 1);
 | |
| +
 | |
| +	return ret;
 | |
| +}
 | |
| +module_init(vcio_init);
 | |
| +
 | |
| +static void __exit vcio_exit(void)
 | |
| +{
 | |
| +	device_destroy(vcio.class, vcio.devt);
 | |
| +	class_destroy(vcio.class);
 | |
| +	cdev_del(&vcio.cdev);
 | |
| +	unregister_chrdev_region(vcio.devt, 1);
 | |
| +}
 | |
| +module_exit(vcio_exit);
 | |
| +
 | |
| +MODULE_AUTHOR("Gray Girling");
 | |
| +MODULE_AUTHOR("Noralf Trønnes");
 | |
| +MODULE_DESCRIPTION("Mailbox userspace access");
 | |
| +MODULE_LICENSE("GPL");
 | |
| -- 
 | |
| 2.19.1
 | |
| 
 |