Skip to content

Commit ebf4ec9

Browse files
notropopcornmix
authored andcommitted
char: broadcom: Add vcio module
Add module for accessing the mailbox property channel through /dev/vcio. Was previously in bcm2708-vcio. Signed-off-by: Noralf Trønnes <[email protected]>
1 parent a1417df commit ebf4ec9

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed

drivers/char/broadcom/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ config BCM2708_VCMEM
2222
help
2323
Helper for videocore memory access and total size allocation.
2424

25+
config BCM_VCIO
26+
tristate "Mailbox userspace access"
27+
depends on BCM2835_MBOX
28+
help
29+
Gives access to the mailbox property channel from userspace.
30+
2531
endif
2632

2733
config BCM_VC_SM

drivers/char/broadcom/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
obj-$(CONFIG_BCM_VC_CMA) += vc_cma/
22
obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
3+
obj-$(CONFIG_BCM_VCIO) += vcio.o
34
obj-$(CONFIG_BCM_VC_SM) += vc_sm/
45

56
obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o

drivers/char/broadcom/vcio.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Copyright (C) 2010 Broadcom
3+
* Copyright (C) 2015 Noralf Trønnes
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License version 2 as
7+
* published by the Free Software Foundation.
8+
*
9+
*/
10+
11+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12+
13+
#include <linux/cdev.h>
14+
#include <linux/device.h>
15+
#include <linux/fs.h>
16+
#include <linux/init.h>
17+
#include <linux/ioctl.h>
18+
#include <linux/module.h>
19+
#include <linux/slab.h>
20+
#include <linux/uaccess.h>
21+
#include <soc/bcm2835/raspberrypi-firmware.h>
22+
23+
#define MBOX_CHAN_PROPERTY 8
24+
25+
#define VCIO_IOC_MAGIC 100
26+
#define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *)
27+
28+
static struct {
29+
dev_t devt;
30+
struct cdev cdev;
31+
struct class *class;
32+
struct rpi_firmware *fw;
33+
} vcio;
34+
35+
static int vcio_user_property_list(void *user)
36+
{
37+
u32 *buf, size;
38+
int ret;
39+
40+
/* The first 32-bit is the size of the buffer */
41+
if (copy_from_user(&size, user, sizeof(size)))
42+
return -EFAULT;
43+
44+
buf = kmalloc(size, GFP_KERNEL);
45+
if (!buf)
46+
return -ENOMEM;
47+
48+
if (copy_from_user(buf, user, size)) {
49+
kfree(buf);
50+
return -EFAULT;
51+
}
52+
53+
/* Strip off protocol encapsulation */
54+
ret = rpi_firmware_property_list(vcio.fw, &buf[2], size - 12);
55+
if (ret) {
56+
kfree(buf);
57+
return ret;
58+
}
59+
60+
buf[1] = RPI_FIRMWARE_STATUS_SUCCESS;
61+
if (copy_to_user(user, buf, size))
62+
ret = -EFAULT;
63+
64+
kfree(buf);
65+
66+
return ret;
67+
}
68+
69+
static int vcio_device_open(struct inode *inode, struct file *file)
70+
{
71+
try_module_get(THIS_MODULE);
72+
73+
return 0;
74+
}
75+
76+
static int vcio_device_release(struct inode *inode, struct file *file)
77+
{
78+
module_put(THIS_MODULE);
79+
80+
return 0;
81+
}
82+
83+
static long vcio_device_ioctl(struct file *file, unsigned int ioctl_num,
84+
unsigned long ioctl_param)
85+
{
86+
switch (ioctl_num) {
87+
case IOCTL_MBOX_PROPERTY:
88+
return vcio_user_property_list((void *)ioctl_param);
89+
default:
90+
pr_err("unknown ioctl: %d\n", ioctl_num);
91+
return -EINVAL;
92+
}
93+
}
94+
95+
const struct file_operations vcio_fops = {
96+
.unlocked_ioctl = vcio_device_ioctl,
97+
.open = vcio_device_open,
98+
.release = vcio_device_release,
99+
};
100+
101+
static int __init vcio_init(void)
102+
{
103+
struct device_node *np;
104+
static struct device *dev;
105+
int ret;
106+
107+
np = of_find_compatible_node(NULL, NULL,
108+
"raspberrypi,bcm2835-firmware");
109+
/* Uncomment this when we only boot with Device Tree
110+
if (!of_device_is_available(np))
111+
return -ENODEV;
112+
*/
113+
vcio.fw = rpi_firmware_get(np);
114+
if (!vcio.fw)
115+
return -ENODEV;
116+
117+
ret = alloc_chrdev_region(&vcio.devt, 0, 1, "vcio");
118+
if (ret) {
119+
pr_err("failed to allocate device number\n");
120+
return ret;
121+
}
122+
123+
cdev_init(&vcio.cdev, &vcio_fops);
124+
vcio.cdev.owner = THIS_MODULE;
125+
ret = cdev_add(&vcio.cdev, vcio.devt, 1);
126+
if (ret) {
127+
pr_err("failed to register device\n");
128+
goto err_unregister_chardev;
129+
}
130+
131+
/*
132+
* Create sysfs entries
133+
* 'bcm2708_vcio' is used for backwards compatibility so we don't break
134+
* userspace. Raspian has a udev rule that changes the permissions.
135+
*/
136+
vcio.class = class_create(THIS_MODULE, "bcm2708_vcio");
137+
if (IS_ERR(vcio.class)) {
138+
ret = PTR_ERR(vcio.class);
139+
pr_err("failed to create class\n");
140+
goto err_cdev_del;
141+
}
142+
143+
dev = device_create(vcio.class, NULL, vcio.devt, NULL, "vcio");
144+
if (IS_ERR(dev)) {
145+
ret = PTR_ERR(dev);
146+
pr_err("failed to create device\n");
147+
goto err_class_destroy;
148+
}
149+
150+
return 0;
151+
152+
err_class_destroy:
153+
class_destroy(vcio.class);
154+
err_cdev_del:
155+
cdev_del(&vcio.cdev);
156+
err_unregister_chardev:
157+
unregister_chrdev_region(vcio.devt, 1);
158+
159+
return ret;
160+
}
161+
module_init(vcio_init);
162+
163+
static void __exit vcio_exit(void)
164+
{
165+
device_destroy(vcio.class, vcio.devt);
166+
class_destroy(vcio.class);
167+
cdev_del(&vcio.cdev);
168+
unregister_chrdev_region(vcio.devt, 1);
169+
}
170+
module_exit(vcio_exit);
171+
172+
MODULE_AUTHOR("Gray Girling");
173+
MODULE_AUTHOR("Noralf Trønnes");
174+
MODULE_DESCRIPTION("Mailbox userspace access");
175+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)