brcm2708: add linux 4.19 support
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.19 / 950-0054-char-broadcom-Add-vcio-module.patch
1 From 9fc71e9f5ee71c3f91b43c8c94a0db17349b938c Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
3 Date: Fri, 26 Jun 2015 14:27:06 +0200
4 Subject: [PATCH 054/703] char: broadcom: Add vcio module
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Add module for accessing the mailbox property channel through
10 /dev/vcio. Was previously in bcm2708-vcio.
11
12 Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
13 ---
14 drivers/char/broadcom/Kconfig | 6 ++
15 drivers/char/broadcom/Makefile | 1 +
16 drivers/char/broadcom/vcio.c | 175 +++++++++++++++++++++++++++++++++
17 3 files changed, 182 insertions(+)
18 create mode 100644 drivers/char/broadcom/vcio.c
19
20 --- a/drivers/char/broadcom/Kconfig
21 +++ b/drivers/char/broadcom/Kconfig
22 @@ -15,6 +15,12 @@ config BCM2708_VCMEM
23 help
24 Helper for videocore memory access and total size allocation.
25
26 +config BCM_VCIO
27 + tristate "Mailbox userspace access"
28 + depends on BCM2835_MBOX
29 + help
30 + Gives access to the mailbox property channel from userspace.
31 +
32 endif
33
34 config BCM_VC_SM
35 --- a/drivers/char/broadcom/Makefile
36 +++ b/drivers/char/broadcom/Makefile
37 @@ -1,4 +1,5 @@
38 obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
39 +obj-$(CONFIG_BCM_VCIO) += vcio.o
40 obj-$(CONFIG_BCM_VC_SM) += vc_sm/
41
42 obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
43 --- /dev/null
44 +++ b/drivers/char/broadcom/vcio.c
45 @@ -0,0 +1,175 @@
46 +/*
47 + * Copyright (C) 2010 Broadcom
48 + * Copyright (C) 2015 Noralf Trønnes
49 + *
50 + * This program is free software; you can redistribute it and/or modify
51 + * it under the terms of the GNU General Public License version 2 as
52 + * published by the Free Software Foundation.
53 + *
54 + */
55 +
56 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
57 +
58 +#include <linux/cdev.h>
59 +#include <linux/device.h>
60 +#include <linux/fs.h>
61 +#include <linux/init.h>
62 +#include <linux/ioctl.h>
63 +#include <linux/module.h>
64 +#include <linux/slab.h>
65 +#include <linux/uaccess.h>
66 +#include <soc/bcm2835/raspberrypi-firmware.h>
67 +
68 +#define MBOX_CHAN_PROPERTY 8
69 +
70 +#define VCIO_IOC_MAGIC 100
71 +#define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
72 +
73 +static struct {
74 + dev_t devt;
75 + struct cdev cdev;
76 + struct class *class;
77 + struct rpi_firmware *fw;
78 +} vcio;
79 +
80 +static int vcio_user_property_list(void *user)
81 +{
82 + u32 *buf, size;
83 + int ret;
84 +
85 + /* The first 32-bit is the size of the buffer */
86 + if (copy_from_user(&size, user, sizeof(size)))
87 + return -EFAULT;
88 +
89 + buf = kmalloc(size, GFP_KERNEL);
90 + if (!buf)
91 + return -ENOMEM;
92 +
93 + if (copy_from_user(buf, user, size)) {
94 + kfree(buf);
95 + return -EFAULT;
96 + }
97 +
98 + /* Strip off protocol encapsulation */
99 + ret = rpi_firmware_property_list(vcio.fw, &buf[2], size - 12);
100 + if (ret) {
101 + kfree(buf);
102 + return ret;
103 + }
104 +
105 + buf[1] = RPI_FIRMWARE_STATUS_SUCCESS;
106 + if (copy_to_user(user, buf, size))
107 + ret = -EFAULT;
108 +
109 + kfree(buf);
110 +
111 + return ret;
112 +}
113 +
114 +static int vcio_device_open(struct inode *inode, struct file *file)
115 +{
116 + try_module_get(THIS_MODULE);
117 +
118 + return 0;
119 +}
120 +
121 +static int vcio_device_release(struct inode *inode, struct file *file)
122 +{
123 + module_put(THIS_MODULE);
124 +
125 + return 0;
126 +}
127 +
128 +static long vcio_device_ioctl(struct file *file, unsigned int ioctl_num,
129 + unsigned long ioctl_param)
130 +{
131 + switch (ioctl_num) {
132 + case IOCTL_MBOX_PROPERTY:
133 + return vcio_user_property_list((void *)ioctl_param);
134 + default:
135 + pr_err("unknown ioctl: %d\n", ioctl_num);
136 + return -EINVAL;
137 + }
138 +}
139 +
140 +const struct file_operations vcio_fops = {
141 + .unlocked_ioctl = vcio_device_ioctl,
142 + .open = vcio_device_open,
143 + .release = vcio_device_release,
144 +};
145 +
146 +static int __init vcio_init(void)
147 +{
148 + struct device_node *np;
149 + static struct device *dev;
150 + int ret;
151 +
152 + np = of_find_compatible_node(NULL, NULL,
153 + "raspberrypi,bcm2835-firmware");
154 +/* Uncomment this when we only boot with Device Tree
155 + if (!of_device_is_available(np))
156 + return -ENODEV;
157 +*/
158 + vcio.fw = rpi_firmware_get(np);
159 + if (!vcio.fw)
160 + return -ENODEV;
161 +
162 + ret = alloc_chrdev_region(&vcio.devt, 0, 1, "vcio");
163 + if (ret) {
164 + pr_err("failed to allocate device number\n");
165 + return ret;
166 + }
167 +
168 + cdev_init(&vcio.cdev, &vcio_fops);
169 + vcio.cdev.owner = THIS_MODULE;
170 + ret = cdev_add(&vcio.cdev, vcio.devt, 1);
171 + if (ret) {
172 + pr_err("failed to register device\n");
173 + goto err_unregister_chardev;
174 + }
175 +
176 + /*
177 + * Create sysfs entries
178 + * 'bcm2708_vcio' is used for backwards compatibility so we don't break
179 + * userspace. Raspian has a udev rule that changes the permissions.
180 + */
181 + vcio.class = class_create(THIS_MODULE, "bcm2708_vcio");
182 + if (IS_ERR(vcio.class)) {
183 + ret = PTR_ERR(vcio.class);
184 + pr_err("failed to create class\n");
185 + goto err_cdev_del;
186 + }
187 +
188 + dev = device_create(vcio.class, NULL, vcio.devt, NULL, "vcio");
189 + if (IS_ERR(dev)) {
190 + ret = PTR_ERR(dev);
191 + pr_err("failed to create device\n");
192 + goto err_class_destroy;
193 + }
194 +
195 + return 0;
196 +
197 +err_class_destroy:
198 + class_destroy(vcio.class);
199 +err_cdev_del:
200 + cdev_del(&vcio.cdev);
201 +err_unregister_chardev:
202 + unregister_chrdev_region(vcio.devt, 1);
203 +
204 + return ret;
205 +}
206 +module_init(vcio_init);
207 +
208 +static void __exit vcio_exit(void)
209 +{
210 + device_destroy(vcio.class, vcio.devt);
211 + class_destroy(vcio.class);
212 + cdev_del(&vcio.cdev);
213 + unregister_chrdev_region(vcio.devt, 1);
214 +}
215 +module_exit(vcio_exit);
216 +
217 +MODULE_AUTHOR("Gray Girling");
218 +MODULE_AUTHOR("Noralf Trønnes");
219 +MODULE_DESCRIPTION("Mailbox userspace access");
220 +MODULE_LICENSE("GPL");