bcm27xx: add linux 5.4 support
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0051-char-broadcom-Add-vcio-module.patch
1 From 665ddd6b1e4bad3473ef5f4834c04db3e8968867 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] 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 char: vcio: Add compat ioctl handling
15
16 There was no compat ioctl handler, so 32 bit userspace on a
17 64 bit kernel failed as IOCTL_MBOX_PROPERTY used the size
18 of char*.
19
20 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
21
22 char: vcio: Fail probe if rpi_firmware is not found.
23
24 Device Tree is now the only supported config mechanism, therefore
25 uncomment the block of code that fails the probe if the
26 firmware node can't be found.
27
28 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
29 ---
30 drivers/char/broadcom/Kconfig | 6 +
31 drivers/char/broadcom/Makefile | 1 +
32 drivers/char/broadcom/vcio.c | 194 +++++++++++++++++++++++++++++++++
33 3 files changed, 201 insertions(+)
34 create mode 100644 drivers/char/broadcom/vcio.c
35
36 --- a/drivers/char/broadcom/Kconfig
37 +++ b/drivers/char/broadcom/Kconfig
38 @@ -15,6 +15,12 @@ config BCM2708_VCMEM
39 help
40 Helper for videocore memory access and total size allocation.
41
42 +config BCM_VCIO
43 + tristate "Mailbox userspace access"
44 + depends on BCM2835_MBOX
45 + help
46 + Gives access to the mailbox property channel from userspace.
47 +
48 endif
49
50 config BCM_VC_SM
51 --- a/drivers/char/broadcom/Makefile
52 +++ b/drivers/char/broadcom/Makefile
53 @@ -1,4 +1,5 @@
54 obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
55 +obj-$(CONFIG_BCM_VCIO) += vcio.o
56 obj-$(CONFIG_BCM_VC_SM) += vc_sm/
57
58 obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
59 --- /dev/null
60 +++ b/drivers/char/broadcom/vcio.c
61 @@ -0,0 +1,194 @@
62 +/*
63 + * Copyright (C) 2010 Broadcom
64 + * Copyright (C) 2015 Noralf Trønnes
65 + *
66 + * This program is free software; you can redistribute it and/or modify
67 + * it under the terms of the GNU General Public License version 2 as
68 + * published by the Free Software Foundation.
69 + *
70 + */
71 +
72 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
73 +
74 +#include <linux/cdev.h>
75 +#include <linux/device.h>
76 +#include <linux/fs.h>
77 +#include <linux/init.h>
78 +#include <linux/ioctl.h>
79 +#include <linux/module.h>
80 +#include <linux/slab.h>
81 +#include <linux/uaccess.h>
82 +#include <soc/bcm2835/raspberrypi-firmware.h>
83 +
84 +#define MBOX_CHAN_PROPERTY 8
85 +
86 +#define VCIO_IOC_MAGIC 100
87 +#define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
88 +#ifdef CONFIG_COMPAT
89 +#define IOCTL_MBOX_PROPERTY32 _IOWR(VCIO_IOC_MAGIC, 0, compat_uptr_t)
90 +#endif
91 +
92 +static struct {
93 + dev_t devt;
94 + struct cdev cdev;
95 + struct class *class;
96 + struct rpi_firmware *fw;
97 +} vcio;
98 +
99 +static int vcio_user_property_list(void *user)
100 +{
101 + u32 *buf, size;
102 + int ret;
103 +
104 + /* The first 32-bit is the size of the buffer */
105 + if (copy_from_user(&size, user, sizeof(size)))
106 + return -EFAULT;
107 +
108 + buf = kmalloc(size, GFP_KERNEL);
109 + if (!buf)
110 + return -ENOMEM;
111 +
112 + if (copy_from_user(buf, user, size)) {
113 + kfree(buf);
114 + return -EFAULT;
115 + }
116 +
117 + /* Strip off protocol encapsulation */
118 + ret = rpi_firmware_property_list(vcio.fw, &buf[2], size - 12);
119 + if (ret) {
120 + kfree(buf);
121 + return ret;
122 + }
123 +
124 + buf[1] = RPI_FIRMWARE_STATUS_SUCCESS;
125 + if (copy_to_user(user, buf, size))
126 + ret = -EFAULT;
127 +
128 + kfree(buf);
129 +
130 + return ret;
131 +}
132 +
133 +static int vcio_device_open(struct inode *inode, struct file *file)
134 +{
135 + try_module_get(THIS_MODULE);
136 +
137 + return 0;
138 +}
139 +
140 +static int vcio_device_release(struct inode *inode, struct file *file)
141 +{
142 + module_put(THIS_MODULE);
143 +
144 + return 0;
145 +}
146 +
147 +static long vcio_device_ioctl(struct file *file, unsigned int ioctl_num,
148 + unsigned long ioctl_param)
149 +{
150 + switch (ioctl_num) {
151 + case IOCTL_MBOX_PROPERTY:
152 + return vcio_user_property_list((void *)ioctl_param);
153 + default:
154 + pr_err("unknown ioctl: %x\n", ioctl_num);
155 + return -EINVAL;
156 + }
157 +}
158 +
159 +#ifdef CONFIG_COMPAT
160 +static long vcio_device_compat_ioctl(struct file *file, unsigned int ioctl_num,
161 + unsigned long ioctl_param)
162 +{
163 + switch (ioctl_num) {
164 + case IOCTL_MBOX_PROPERTY32:
165 + return vcio_user_property_list(compat_ptr(ioctl_param));
166 + default:
167 + pr_err("unknown ioctl: %x\n", ioctl_num);
168 + return -EINVAL;
169 + }
170 +}
171 +#endif
172 +
173 +const struct file_operations vcio_fops = {
174 + .unlocked_ioctl = vcio_device_ioctl,
175 +#ifdef CONFIG_COMPAT
176 + .compat_ioctl = vcio_device_compat_ioctl,
177 +#endif
178 + .open = vcio_device_open,
179 + .release = vcio_device_release,
180 +};
181 +
182 +static int __init vcio_init(void)
183 +{
184 + struct device_node *np;
185 + static struct device *dev;
186 + int ret;
187 +
188 + np = of_find_compatible_node(NULL, NULL,
189 + "raspberrypi,bcm2835-firmware");
190 + if (!of_device_is_available(np))
191 + return -ENODEV;
192 +
193 + vcio.fw = rpi_firmware_get(np);
194 + if (!vcio.fw)
195 + return -ENODEV;
196 +
197 + ret = alloc_chrdev_region(&vcio.devt, 0, 1, "vcio");
198 + if (ret) {
199 + pr_err("failed to allocate device number\n");
200 + return ret;
201 + }
202 +
203 + cdev_init(&vcio.cdev, &vcio_fops);
204 + vcio.cdev.owner = THIS_MODULE;
205 + ret = cdev_add(&vcio.cdev, vcio.devt, 1);
206 + if (ret) {
207 + pr_err("failed to register device\n");
208 + goto err_unregister_chardev;
209 + }
210 +
211 + /*
212 + * Create sysfs entries
213 + * 'bcm2708_vcio' is used for backwards compatibility so we don't break
214 + * userspace. Raspian has a udev rule that changes the permissions.
215 + */
216 + vcio.class = class_create(THIS_MODULE, "bcm2708_vcio");
217 + if (IS_ERR(vcio.class)) {
218 + ret = PTR_ERR(vcio.class);
219 + pr_err("failed to create class\n");
220 + goto err_cdev_del;
221 + }
222 +
223 + dev = device_create(vcio.class, NULL, vcio.devt, NULL, "vcio");
224 + if (IS_ERR(dev)) {
225 + ret = PTR_ERR(dev);
226 + pr_err("failed to create device\n");
227 + goto err_class_destroy;
228 + }
229 +
230 + return 0;
231 +
232 +err_class_destroy:
233 + class_destroy(vcio.class);
234 +err_cdev_del:
235 + cdev_del(&vcio.cdev);
236 +err_unregister_chardev:
237 + unregister_chrdev_region(vcio.devt, 1);
238 +
239 + return ret;
240 +}
241 +module_init(vcio_init);
242 +
243 +static void __exit vcio_exit(void)
244 +{
245 + device_destroy(vcio.class, vcio.devt);
246 + class_destroy(vcio.class);
247 + cdev_del(&vcio.cdev);
248 + unregister_chrdev_region(vcio.devt, 1);
249 +}
250 +module_exit(vcio_exit);
251 +
252 +MODULE_AUTHOR("Gray Girling");
253 +MODULE_AUTHOR("Noralf Trønnes");
254 +MODULE_DESCRIPTION("Mailbox userspace access");
255 +MODULE_LICENSE("GPL");