mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-29 18:19:02 +00:00
20ea6adbf1
Build system: x86_64 Build-tested: bcm2708, bcm2709, bcm2710, bcm2711 Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B Signed-off-by: Marty Jones <mj8263788@gmail.com> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
255 lines
6.2 KiB
Diff
255 lines
6.2 KiB
Diff
From 983ebbacaeeff7dd143170e649a63345d492c858 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 BCM2835_DEVGPIOMEM
|
|
--- a/drivers/char/broadcom/Makefile
|
|
+++ b/drivers/char/broadcom/Makefile
|
|
@@ -1,3 +1,4 @@
|
|
obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
|
|
+obj-$(CONFIG_BCM_VCIO) += vcio.o
|
|
obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
|
|
obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.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");
|