0046-char-broadcom-Add-vcio-module.patch 5.3 KB

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