ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/target/linux/bcm27xx/patches-5.4/950-0051-char-broadcom-Add-vcio-module.patch b/target/linux/bcm27xx/patches-5.4/950-0051-char-broadcom-Add-vcio-module.patch
new file mode 100644
index 0000000..db50183
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0051-char-broadcom-Add-vcio-module.patch
@@ -0,0 +1,255 @@
+From 665ddd6b1e4bad3473ef5f4834c04db3e8968867 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] 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>
+
+char: vcio: Add compat ioctl handling
+
+There was no compat ioctl handler, so 32 bit userspace on a
+64 bit kernel failed as IOCTL_MBOX_PROPERTY used the size
+of char*.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+
+char: vcio: Fail probe if rpi_firmware is not found.
+
+Device Tree is now the only supported config mechanism, therefore
+uncomment the block of code that fails the probe if the
+firmware node can't be found.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/char/broadcom/Kconfig  |   6 +
+ drivers/char/broadcom/Makefile |   1 +
+ drivers/char/broadcom/vcio.c   | 194 +++++++++++++++++++++++++++++++++
+ 3 files changed, 201 insertions(+)
+ create mode 100644 drivers/char/broadcom/vcio.c
+
+--- 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
+--- 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
+--- /dev/null
++++ b/drivers/char/broadcom/vcio.c
+@@ -0,0 +1,194 @@
++/*
++ *  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 *)
++#ifdef CONFIG_COMPAT
++#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
++#endif
++
++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: %x\n", ioctl_num);
++		return -EINVAL;
++	}
++}
++
++#ifdef CONFIG_COMPAT
++static long vcio_device_compat_ioctl(struct file *file, unsigned int ioctl_num,
++				     unsigned long ioctl_param)
++{
++	switch (ioctl_num) {
++	case IOCTL_MBOX_PROPERTY32:
++		return vcio_user_property_list(compat_ptr(ioctl_param));
++	default:
++		pr_err("unknown ioctl: %x\n", ioctl_num);
++		return -EINVAL;
++	}
++}
++#endif
++
++const struct file_operations vcio_fops = {
++	.unlocked_ioctl = vcio_device_ioctl,
++#ifdef CONFIG_COMPAT
++	.compat_ioctl = vcio_device_compat_ioctl,
++#endif
++	.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");
++	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");