123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991 |
- From b08bfcd6d88d7006f458e21dddabd42e53780708 Mon Sep 17 00:00:00 2001
- From: popcornmix <popcornmix@gmail.com>
- Date: Wed, 17 Jun 2015 16:07:06 +0100
- Subject: [PATCH] vc_mem: Add vc_mem driver
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- Signed-off-by: popcornmix <popcornmix@gmail.com>
- BCM270x: Move vc_mem
- Make the vc_mem module available for ARCH_BCM2835 by moving it.
- Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
- ---
- arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 ---
- arch/arm/mach-bcm2709/vc_mem.c | 431 ----------------------------
- drivers/char/broadcom/Kconfig | 12 +-
- drivers/char/broadcom/Makefile | 1 +
- drivers/char/broadcom/vc_mem.c | 422 +++++++++++++++++++++++++++
- include/linux/broadcom/vc_mem.h | 35 +++
- 6 files changed, 469 insertions(+), 467 deletions(-)
- delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h
- delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c
- create mode 100644 drivers/char/broadcom/vc_mem.c
- create mode 100644 include/linux/broadcom/vc_mem.h
- --- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h
- +++ /dev/null
- @@ -1,35 +0,0 @@
- -/*****************************************************************************
- -* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
- -*
- -* Unless you and Broadcom execute a separate written software license
- -* agreement governing use of this software, this software is licensed to you
- -* under the terms of the GNU General Public License version 2, available at
- -* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- -*
- -* Notwithstanding the above, under no circumstances may you combine this
- -* software in any way with any other Broadcom software provided under a
- -* license other than the GPL, without Broadcom's express prior written
- -* consent.
- -*****************************************************************************/
- -
- -#if !defined( VC_MEM_H )
- -#define VC_MEM_H
- -
- -#include <linux/ioctl.h>
- -
- -#define VC_MEM_IOC_MAGIC 'v'
- -
- -#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
- -#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
- -#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
- -#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
- -
- -#if defined( __KERNEL__ )
- -#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
- -
- -extern unsigned long mm_vc_mem_phys_addr;
- -extern unsigned int mm_vc_mem_size;
- -extern int vc_mem_get_current_size( void );
- -#endif
- -
- -#endif /* VC_MEM_H */
- --- a/arch/arm/mach-bcm2709/vc_mem.c
- +++ /dev/null
- @@ -1,431 +0,0 @@
- -/*****************************************************************************
- -* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
- -*
- -* Unless you and Broadcom execute a separate written software license
- -* agreement governing use of this software, this software is licensed to you
- -* under the terms of the GNU General Public License version 2, available at
- -* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- -*
- -* Notwithstanding the above, under no circumstances may you combine this
- -* software in any way with any other Broadcom software provided under a
- -* license other than the GPL, without Broadcom's express prior written
- -* consent.
- -*****************************************************************************/
- -
- -#include <linux/kernel.h>
- -#include <linux/module.h>
- -#include <linux/fs.h>
- -#include <linux/device.h>
- -#include <linux/cdev.h>
- -#include <linux/mm.h>
- -#include <linux/slab.h>
- -#include <linux/debugfs.h>
- -#include <asm/uaccess.h>
- -#include <linux/dma-mapping.h>
- -#include <linux/platform_data/mailbox-bcm2708.h>
- -
- -#ifdef CONFIG_ARCH_KONA
- -#include <chal/chal_ipc.h>
- -#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709)
- -#else
- -#include <csp/chal_ipc.h>
- -#endif
- -
- -#include "mach/vc_mem.h"
- -
- -#define DRIVER_NAME "vc-mem"
- -
- -// Device (/dev) related variables
- -static dev_t vc_mem_devnum = 0;
- -static struct class *vc_mem_class = NULL;
- -static struct cdev vc_mem_cdev;
- -static int vc_mem_inited = 0;
- -
- -#ifdef CONFIG_DEBUG_FS
- -static struct dentry *vc_mem_debugfs_entry;
- -#endif
- -
- -/*
- - * Videocore memory addresses and size
- - *
- - * Drivers that wish to know the videocore memory addresses and sizes should
- - * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in
- - * headers. This allows the other drivers to not be tied down to a a certain
- - * address/size at compile time.
- - *
- - * In the future, the goal is to have the videocore memory virtual address and
- - * size be calculated at boot time rather than at compile time. The decision of
- - * where the videocore memory resides and its size would be in the hands of the
- - * bootloader (and/or kernel). When that happens, the values of these variables
- - * would be calculated and assigned in the init function.
- - */
- -// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
- -unsigned long mm_vc_mem_phys_addr = 0x00000000;
- -unsigned int mm_vc_mem_size = 0;
- -unsigned int mm_vc_mem_base = 0;
- -
- -EXPORT_SYMBOL(mm_vc_mem_phys_addr);
- -EXPORT_SYMBOL(mm_vc_mem_size);
- -EXPORT_SYMBOL(mm_vc_mem_base);
- -
- -static uint phys_addr = 0;
- -static uint mem_size = 0;
- -static uint mem_base = 0;
- -
- -
- -/****************************************************************************
- -*
- -* vc_mem_open
- -*
- -***************************************************************************/
- -
- -static int
- -vc_mem_open(struct inode *inode, struct file *file)
- -{
- - (void) inode;
- - (void) file;
- -
- - pr_debug("%s: called file = 0x%p\n", __func__, file);
- -
- - return 0;
- -}
- -
- -/****************************************************************************
- -*
- -* vc_mem_release
- -*
- -***************************************************************************/
- -
- -static int
- -vc_mem_release(struct inode *inode, struct file *file)
- -{
- - (void) inode;
- - (void) file;
- -
- - pr_debug("%s: called file = 0x%p\n", __func__, file);
- -
- - return 0;
- -}
- -
- -/****************************************************************************
- -*
- -* vc_mem_get_size
- -*
- -***************************************************************************/
- -
- -static void
- -vc_mem_get_size(void)
- -{
- -}
- -
- -/****************************************************************************
- -*
- -* vc_mem_get_base
- -*
- -***************************************************************************/
- -
- -static void
- -vc_mem_get_base(void)
- -{
- -}
- -
- -/****************************************************************************
- -*
- -* vc_mem_get_current_size
- -*
- -***************************************************************************/
- -
- -int
- -vc_mem_get_current_size(void)
- -{
- - return mm_vc_mem_size;
- -}
- -
- -EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
- -
- -/****************************************************************************
- -*
- -* vc_mem_ioctl
- -*
- -***************************************************************************/
- -
- -static long
- -vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- -{
- - int rc = 0;
- -
- - (void) cmd;
- - (void) arg;
- -
- - pr_debug("%s: called file = 0x%p\n", __func__, file);
- -
- - switch (cmd) {
- - case VC_MEM_IOC_MEM_PHYS_ADDR:
- - {
- - pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
- - __func__, (void *) mm_vc_mem_phys_addr);
- -
- - if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
- - sizeof (mm_vc_mem_phys_addr)) != 0) {
- - rc = -EFAULT;
- - }
- - break;
- - }
- - case VC_MEM_IOC_MEM_SIZE:
- - {
- - // Get the videocore memory size first
- - vc_mem_get_size();
- -
- - pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
- - mm_vc_mem_size);
- -
- - if (copy_to_user((void *) arg, &mm_vc_mem_size,
- - sizeof (mm_vc_mem_size)) != 0) {
- - rc = -EFAULT;
- - }
- - break;
- - }
- - case VC_MEM_IOC_MEM_BASE:
- - {
- - // Get the videocore memory base
- - vc_mem_get_base();
- -
- - pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
- - mm_vc_mem_base);
- -
- - if (copy_to_user((void *) arg, &mm_vc_mem_base,
- - sizeof (mm_vc_mem_base)) != 0) {
- - rc = -EFAULT;
- - }
- - break;
- - }
- - case VC_MEM_IOC_MEM_LOAD:
- - {
- - // Get the videocore memory base
- - vc_mem_get_base();
- -
- - pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
- - mm_vc_mem_base);
- -
- - if (copy_to_user((void *) arg, &mm_vc_mem_base,
- - sizeof (mm_vc_mem_base)) != 0) {
- - rc = -EFAULT;
- - }
- - break;
- - }
- - default:
- - {
- - return -ENOTTY;
- - }
- - }
- - pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc);
- -
- - return rc;
- -}
- -
- -/****************************************************************************
- -*
- -* vc_mem_mmap
- -*
- -***************************************************************************/
- -
- -static int
- -vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
- -{
- - int rc = 0;
- - unsigned long length = vma->vm_end - vma->vm_start;
- - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- -
- - pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
- - __func__, (long) vma->vm_start, (long) vma->vm_end,
- - (long) vma->vm_pgoff);
- -
- - if (offset + length > mm_vc_mem_size) {
- - pr_err("%s: length %ld is too big\n", __func__, length);
- - return -EINVAL;
- - }
- - // Do not cache the memory map
- - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- -
- - rc = remap_pfn_range(vma, vma->vm_start,
- - (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
- - vma->vm_pgoff, length, vma->vm_page_prot);
- - if (rc != 0) {
- - pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
- - }
- -
- - return rc;
- -}
- -
- -/****************************************************************************
- -*
- -* File Operations for the driver.
- -*
- -***************************************************************************/
- -
- -static const struct file_operations vc_mem_fops = {
- - .owner = THIS_MODULE,
- - .open = vc_mem_open,
- - .release = vc_mem_release,
- - .unlocked_ioctl = vc_mem_ioctl,
- - .mmap = vc_mem_mmap,
- -};
- -
- -#ifdef CONFIG_DEBUG_FS
- -static void vc_mem_debugfs_deinit(void)
- -{
- - debugfs_remove_recursive(vc_mem_debugfs_entry);
- - vc_mem_debugfs_entry = NULL;
- -}
- -
- -
- -static int vc_mem_debugfs_init(
- - struct device *dev)
- -{
- - vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL);
- - if (!vc_mem_debugfs_entry) {
- - dev_warn(dev, "could not create debugfs entry\n");
- - return -EFAULT;
- - }
- -
- - if (!debugfs_create_x32("vc_mem_phys_addr",
- - 0444,
- - vc_mem_debugfs_entry,
- - (u32 *)&mm_vc_mem_phys_addr)) {
- - dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
- - __func__);
- - goto fail;
- - }
- -
- - if (!debugfs_create_x32("vc_mem_size",
- - 0444,
- - vc_mem_debugfs_entry,
- - (u32 *)&mm_vc_mem_size)) {
- - dev_warn(dev, "%s:could not create vc_mem_size entry\n",
- - __func__);
- - goto fail;
- - }
- -
- - if (!debugfs_create_x32("vc_mem_base",
- - 0444,
- - vc_mem_debugfs_entry,
- - (u32 *)&mm_vc_mem_base)) {
- - dev_warn(dev, "%s:could not create vc_mem_base entry\n",
- - __func__);
- - goto fail;
- - }
- -
- - return 0;
- -
- -fail:
- - vc_mem_debugfs_deinit();
- - return -EFAULT;
- -}
- -
- -#endif /* CONFIG_DEBUG_FS */
- -
- -
- -/****************************************************************************
- -*
- -* vc_mem_init
- -*
- -***************************************************************************/
- -
- -static int __init
- -vc_mem_init(void)
- -{
- - int rc = -EFAULT;
- - struct device *dev;
- -
- - pr_debug("%s: called\n", __func__);
- -
- - mm_vc_mem_phys_addr = phys_addr;
- - mm_vc_mem_size = mem_size;
- - mm_vc_mem_base = mem_base;
- -
- - vc_mem_get_size();
- -
- - pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
- - mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
- -
- - if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
- - pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
- - __func__, rc);
- - goto out_err;
- - }
- -
- - cdev_init(&vc_mem_cdev, &vc_mem_fops);
- - if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
- - pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
- - goto out_unregister;
- - }
- -
- - vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME);
- - if (IS_ERR(vc_mem_class)) {
- - rc = PTR_ERR(vc_mem_class);
- - pr_err("%s: class_create failed (rc=%d)\n", __func__, rc);
- - goto out_cdev_del;
- - }
- -
- - dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL,
- - DRIVER_NAME);
- - if (IS_ERR(dev)) {
- - rc = PTR_ERR(dev);
- - pr_err("%s: device_create failed (rc=%d)\n", __func__, rc);
- - goto out_class_destroy;
- - }
- -
- -#ifdef CONFIG_DEBUG_FS
- - /* don't fail if the debug entries cannot be created */
- - vc_mem_debugfs_init(dev);
- -#endif
- -
- - vc_mem_inited = 1;
- - return 0;
- -
- - device_destroy(vc_mem_class, vc_mem_devnum);
- -
- - out_class_destroy:
- - class_destroy(vc_mem_class);
- - vc_mem_class = NULL;
- -
- - out_cdev_del:
- - cdev_del(&vc_mem_cdev);
- -
- - out_unregister:
- - unregister_chrdev_region(vc_mem_devnum, 1);
- -
- - out_err:
- - return -1;
- -}
- -
- -/****************************************************************************
- -*
- -* vc_mem_exit
- -*
- -***************************************************************************/
- -
- -static void __exit
- -vc_mem_exit(void)
- -{
- - pr_debug("%s: called\n", __func__);
- -
- - if (vc_mem_inited) {
- -#if CONFIG_DEBUG_FS
- - vc_mem_debugfs_deinit();
- -#endif
- - device_destroy(vc_mem_class, vc_mem_devnum);
- - class_destroy(vc_mem_class);
- - cdev_del(&vc_mem_cdev);
- - unregister_chrdev_region(vc_mem_devnum, 1);
- - }
- -}
- -
- -module_init(vc_mem_init);
- -module_exit(vc_mem_exit);
- -MODULE_LICENSE("GPL");
- -MODULE_AUTHOR("Broadcom Corporation");
- -
- -module_param(phys_addr, uint, 0644);
- -module_param(mem_size, uint, 0644);
- -module_param(mem_base, uint, 0644);
- --- a/drivers/char/broadcom/Kconfig
- +++ b/drivers/char/broadcom/Kconfig
- @@ -7,9 +7,19 @@ menuconfig BRCM_CHAR_DRIVERS
- help
- Broadcom's char drivers
-
- +if BRCM_CHAR_DRIVERS
- +
- config BCM_VC_CMA
- bool "Videocore CMA"
- - depends on CMA && BRCM_CHAR_DRIVERS && BCM2708_VCHIQ
- + depends on CMA && BCM2708_VCHIQ
- default n
- help
- Helper for videocore CMA access.
- +
- +config BCM2708_VCMEM
- + bool "Videocore Memory"
- + default y
- + help
- + Helper for videocore memory access and total size allocation.
- +
- +endif
- --- a/drivers/char/broadcom/Makefile
- +++ b/drivers/char/broadcom/Makefile
- @@ -1 +1,2 @@
- obj-$(CONFIG_BCM_VC_CMA) += vc_cma/
- +obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
- --- /dev/null
- +++ b/drivers/char/broadcom/vc_mem.c
- @@ -0,0 +1,422 @@
- +/*****************************************************************************
- +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
- +*
- +* Unless you and Broadcom execute a separate written software license
- +* agreement governing use of this software, this software is licensed to you
- +* under the terms of the GNU General Public License version 2, available at
- +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- +*
- +* Notwithstanding the above, under no circumstances may you combine this
- +* software in any way with any other Broadcom software provided under a
- +* license other than the GPL, without Broadcom's express prior written
- +* consent.
- +*****************************************************************************/
- +
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/fs.h>
- +#include <linux/device.h>
- +#include <linux/cdev.h>
- +#include <linux/mm.h>
- +#include <linux/slab.h>
- +#include <linux/debugfs.h>
- +#include <asm/uaccess.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/broadcom/vc_mem.h>
- +
- +#define DRIVER_NAME "vc-mem"
- +
- +// Device (/dev) related variables
- +static dev_t vc_mem_devnum = 0;
- +static struct class *vc_mem_class = NULL;
- +static struct cdev vc_mem_cdev;
- +static int vc_mem_inited = 0;
- +
- +#ifdef CONFIG_DEBUG_FS
- +static struct dentry *vc_mem_debugfs_entry;
- +#endif
- +
- +/*
- + * Videocore memory addresses and size
- + *
- + * Drivers that wish to know the videocore memory addresses and sizes should
- + * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in
- + * headers. This allows the other drivers to not be tied down to a a certain
- + * address/size at compile time.
- + *
- + * In the future, the goal is to have the videocore memory virtual address and
- + * size be calculated at boot time rather than at compile time. The decision of
- + * where the videocore memory resides and its size would be in the hands of the
- + * bootloader (and/or kernel). When that happens, the values of these variables
- + * would be calculated and assigned in the init function.
- + */
- +// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
- +unsigned long mm_vc_mem_phys_addr = 0x00000000;
- +unsigned int mm_vc_mem_size = 0;
- +unsigned int mm_vc_mem_base = 0;
- +
- +EXPORT_SYMBOL(mm_vc_mem_phys_addr);
- +EXPORT_SYMBOL(mm_vc_mem_size);
- +EXPORT_SYMBOL(mm_vc_mem_base);
- +
- +static uint phys_addr = 0;
- +static uint mem_size = 0;
- +static uint mem_base = 0;
- +
- +
- +/****************************************************************************
- +*
- +* vc_mem_open
- +*
- +***************************************************************************/
- +
- +static int
- +vc_mem_open(struct inode *inode, struct file *file)
- +{
- + (void) inode;
- + (void) file;
- +
- + pr_debug("%s: called file = 0x%p\n", __func__, file);
- +
- + return 0;
- +}
- +
- +/****************************************************************************
- +*
- +* vc_mem_release
- +*
- +***************************************************************************/
- +
- +static int
- +vc_mem_release(struct inode *inode, struct file *file)
- +{
- + (void) inode;
- + (void) file;
- +
- + pr_debug("%s: called file = 0x%p\n", __func__, file);
- +
- + return 0;
- +}
- +
- +/****************************************************************************
- +*
- +* vc_mem_get_size
- +*
- +***************************************************************************/
- +
- +static void
- +vc_mem_get_size(void)
- +{
- +}
- +
- +/****************************************************************************
- +*
- +* vc_mem_get_base
- +*
- +***************************************************************************/
- +
- +static void
- +vc_mem_get_base(void)
- +{
- +}
- +
- +/****************************************************************************
- +*
- +* vc_mem_get_current_size
- +*
- +***************************************************************************/
- +
- +int
- +vc_mem_get_current_size(void)
- +{
- + return mm_vc_mem_size;
- +}
- +
- +EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
- +
- +/****************************************************************************
- +*
- +* vc_mem_ioctl
- +*
- +***************************************************************************/
- +
- +static long
- +vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- +{
- + int rc = 0;
- +
- + (void) cmd;
- + (void) arg;
- +
- + pr_debug("%s: called file = 0x%p\n", __func__, file);
- +
- + switch (cmd) {
- + case VC_MEM_IOC_MEM_PHYS_ADDR:
- + {
- + pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
- + __func__, (void *) mm_vc_mem_phys_addr);
- +
- + if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
- + sizeof (mm_vc_mem_phys_addr)) != 0) {
- + rc = -EFAULT;
- + }
- + break;
- + }
- + case VC_MEM_IOC_MEM_SIZE:
- + {
- + // Get the videocore memory size first
- + vc_mem_get_size();
- +
- + pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
- + mm_vc_mem_size);
- +
- + if (copy_to_user((void *) arg, &mm_vc_mem_size,
- + sizeof (mm_vc_mem_size)) != 0) {
- + rc = -EFAULT;
- + }
- + break;
- + }
- + case VC_MEM_IOC_MEM_BASE:
- + {
- + // Get the videocore memory base
- + vc_mem_get_base();
- +
- + pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
- + mm_vc_mem_base);
- +
- + if (copy_to_user((void *) arg, &mm_vc_mem_base,
- + sizeof (mm_vc_mem_base)) != 0) {
- + rc = -EFAULT;
- + }
- + break;
- + }
- + case VC_MEM_IOC_MEM_LOAD:
- + {
- + // Get the videocore memory base
- + vc_mem_get_base();
- +
- + pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
- + mm_vc_mem_base);
- +
- + if (copy_to_user((void *) arg, &mm_vc_mem_base,
- + sizeof (mm_vc_mem_base)) != 0) {
- + rc = -EFAULT;
- + }
- + break;
- + }
- + default:
- + {
- + return -ENOTTY;
- + }
- + }
- + pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc);
- +
- + return rc;
- +}
- +
- +/****************************************************************************
- +*
- +* vc_mem_mmap
- +*
- +***************************************************************************/
- +
- +static int
- +vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
- +{
- + int rc = 0;
- + unsigned long length = vma->vm_end - vma->vm_start;
- + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- +
- + pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
- + __func__, (long) vma->vm_start, (long) vma->vm_end,
- + (long) vma->vm_pgoff);
- +
- + if (offset + length > mm_vc_mem_size) {
- + pr_err("%s: length %ld is too big\n", __func__, length);
- + return -EINVAL;
- + }
- + // Do not cache the memory map
- + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- +
- + rc = remap_pfn_range(vma, vma->vm_start,
- + (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
- + vma->vm_pgoff, length, vma->vm_page_prot);
- + if (rc != 0) {
- + pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
- + }
- +
- + return rc;
- +}
- +
- +/****************************************************************************
- +*
- +* File Operations for the driver.
- +*
- +***************************************************************************/
- +
- +static const struct file_operations vc_mem_fops = {
- + .owner = THIS_MODULE,
- + .open = vc_mem_open,
- + .release = vc_mem_release,
- + .unlocked_ioctl = vc_mem_ioctl,
- + .mmap = vc_mem_mmap,
- +};
- +
- +#ifdef CONFIG_DEBUG_FS
- +static void vc_mem_debugfs_deinit(void)
- +{
- + debugfs_remove_recursive(vc_mem_debugfs_entry);
- + vc_mem_debugfs_entry = NULL;
- +}
- +
- +
- +static int vc_mem_debugfs_init(
- + struct device *dev)
- +{
- + vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL);
- + if (!vc_mem_debugfs_entry) {
- + dev_warn(dev, "could not create debugfs entry\n");
- + return -EFAULT;
- + }
- +
- + if (!debugfs_create_x32("vc_mem_phys_addr",
- + 0444,
- + vc_mem_debugfs_entry,
- + (u32 *)&mm_vc_mem_phys_addr)) {
- + dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
- + __func__);
- + goto fail;
- + }
- +
- + if (!debugfs_create_x32("vc_mem_size",
- + 0444,
- + vc_mem_debugfs_entry,
- + (u32 *)&mm_vc_mem_size)) {
- + dev_warn(dev, "%s:could not create vc_mem_size entry\n",
- + __func__);
- + goto fail;
- + }
- +
- + if (!debugfs_create_x32("vc_mem_base",
- + 0444,
- + vc_mem_debugfs_entry,
- + (u32 *)&mm_vc_mem_base)) {
- + dev_warn(dev, "%s:could not create vc_mem_base entry\n",
- + __func__);
- + goto fail;
- + }
- +
- + return 0;
- +
- +fail:
- + vc_mem_debugfs_deinit();
- + return -EFAULT;
- +}
- +
- +#endif /* CONFIG_DEBUG_FS */
- +
- +
- +/****************************************************************************
- +*
- +* vc_mem_init
- +*
- +***************************************************************************/
- +
- +static int __init
- +vc_mem_init(void)
- +{
- + int rc = -EFAULT;
- + struct device *dev;
- +
- + pr_debug("%s: called\n", __func__);
- +
- + mm_vc_mem_phys_addr = phys_addr;
- + mm_vc_mem_size = mem_size;
- + mm_vc_mem_base = mem_base;
- +
- + vc_mem_get_size();
- +
- + pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
- + mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
- +
- + if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
- + pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
- + __func__, rc);
- + goto out_err;
- + }
- +
- + cdev_init(&vc_mem_cdev, &vc_mem_fops);
- + if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
- + pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
- + goto out_unregister;
- + }
- +
- + vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME);
- + if (IS_ERR(vc_mem_class)) {
- + rc = PTR_ERR(vc_mem_class);
- + pr_err("%s: class_create failed (rc=%d)\n", __func__, rc);
- + goto out_cdev_del;
- + }
- +
- + dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL,
- + DRIVER_NAME);
- + if (IS_ERR(dev)) {
- + rc = PTR_ERR(dev);
- + pr_err("%s: device_create failed (rc=%d)\n", __func__, rc);
- + goto out_class_destroy;
- + }
- +
- +#ifdef CONFIG_DEBUG_FS
- + /* don't fail if the debug entries cannot be created */
- + vc_mem_debugfs_init(dev);
- +#endif
- +
- + vc_mem_inited = 1;
- + return 0;
- +
- + device_destroy(vc_mem_class, vc_mem_devnum);
- +
- + out_class_destroy:
- + class_destroy(vc_mem_class);
- + vc_mem_class = NULL;
- +
- + out_cdev_del:
- + cdev_del(&vc_mem_cdev);
- +
- + out_unregister:
- + unregister_chrdev_region(vc_mem_devnum, 1);
- +
- + out_err:
- + return -1;
- +}
- +
- +/****************************************************************************
- +*
- +* vc_mem_exit
- +*
- +***************************************************************************/
- +
- +static void __exit
- +vc_mem_exit(void)
- +{
- + pr_debug("%s: called\n", __func__);
- +
- + if (vc_mem_inited) {
- +#if CONFIG_DEBUG_FS
- + vc_mem_debugfs_deinit();
- +#endif
- + device_destroy(vc_mem_class, vc_mem_devnum);
- + class_destroy(vc_mem_class);
- + cdev_del(&vc_mem_cdev);
- + unregister_chrdev_region(vc_mem_devnum, 1);
- + }
- +}
- +
- +module_init(vc_mem_init);
- +module_exit(vc_mem_exit);
- +MODULE_LICENSE("GPL");
- +MODULE_AUTHOR("Broadcom Corporation");
- +
- +module_param(phys_addr, uint, 0644);
- +module_param(mem_size, uint, 0644);
- +module_param(mem_base, uint, 0644);
- --- /dev/null
- +++ b/include/linux/broadcom/vc_mem.h
- @@ -0,0 +1,35 @@
- +/*****************************************************************************
- +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
- +*
- +* Unless you and Broadcom execute a separate written software license
- +* agreement governing use of this software, this software is licensed to you
- +* under the terms of the GNU General Public License version 2, available at
- +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
- +*
- +* Notwithstanding the above, under no circumstances may you combine this
- +* software in any way with any other Broadcom software provided under a
- +* license other than the GPL, without Broadcom's express prior written
- +* consent.
- +*****************************************************************************/
- +
- +#ifndef _VC_MEM_H
- +#define _VC_MEM_H
- +
- +#include <linux/ioctl.h>
- +
- +#define VC_MEM_IOC_MAGIC 'v'
- +
- +#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
- +#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
- +#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
- +#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
- +
- +#if defined( __KERNEL__ )
- +#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
- +
- +extern unsigned long mm_vc_mem_phys_addr;
- +extern unsigned int mm_vc_mem_size;
- +extern int vc_mem_get_current_size( void );
- +#endif
- +
- +#endif /* _VC_MEM_H */
|