OpenWrt – Rev 4

Subversion Repositories:
Rev:
From 8783aa0977780bc848678c6d4c506128e1ff0b6f 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 051/454] 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

--- 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,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");

Generated by GNU Enscript 1.6.5.90.