[Armadeus-commitlog] armadeus branch, master, updated. armadeus-4.1-143-gee4261a
Brought to you by:
sszy
|
From: Julien B a. A. <ar...@us...> - 2012-03-15 16:31:24
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "armadeus".
The branch, master has been updated
via ee4261af589d4909987d3e569813c944dcc1ce8c (commit)
via 5846e1cdebf65f9c7565b9815e243d0d2ed611b4 (commit)
via 2fcb73de18864ef34c5c14ad52a0f83d086a9b41 (commit)
via 5947cf0dc68dc0cd64762fbc97d0440c2ff895e7 (commit)
from 45a0645d3fc32439f5467dd29586f039beeef4fa (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ee4261af589d4909987d3e569813c944dcc1ce8c
Merge: 5846e1c 45a0645
Author: Julien Boibessot <jul...@ar...>
Date: Thu Mar 15 17:30:41 2012 +0100
Merge branch 'master' of ssh://armadeus.git.sourceforge.net/gitroot/armadeus/armadeus
commit 5846e1cdebf65f9c7565b9815e243d0d2ed611b4
Author: Julien Boibessot <jul...@ar...>
Date: Thu Mar 15 17:28:38 2012 +0100
[BUILD] Make forced linux build work again on new BR
commit 2fcb73de18864ef34c5c14ad52a0f83d086a9b41
Author: Julien Boibessot <jul...@ar...>
Date: Thu Mar 15 17:27:49 2012 +0100
Updates buildroot/.gitignore for new BR
commit 5947cf0dc68dc0cd64762fbc97d0440c2ff895e7
Author: Julien Boibessot <jul...@ar...>
Date: Thu Mar 15 17:27:10 2012 +0100
[LINUX] APF51: Add IPUv3 base driver and updates VPU's one
-----------------------------------------------------------------------
Summary of changes:
Makefile | 7 +-
buildroot/.gitignore | 2 +
...00126692-3-add_hw-events_vpu_srtc_drivers.patch | 1076 +--
...ale-0034-ENGR00126692-3-add_hw-vpu_driver.patch | 1117 +++
...R00136875-1-Add-function-pgprot_writethru.patch | 27 +
...5-2-make-video-buffer-cacheable-to-improv.patch | 25 +
...45-armadeus-add_freescale_mxc_dvfs_driver.patch | 279 +
.../446-armadeus-add_freescale_ipu3_driver.patch |10343 ++++++++++++++++++++
8 files changed, 11811 insertions(+), 1065 deletions(-)
create mode 100644 patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-vpu_driver.patch
create mode 100644 patches/linux/2.6.38/442-freescale-0535-ENGR00136875-1-Add-function-pgprot_writethru.patch
create mode 100644 patches/linux/2.6.38/442-freescale-0536-ENGR00136875-2-make-video-buffer-cacheable-to-improv.patch
create mode 100644 patches/linux/2.6.38/445-armadeus-add_freescale_mxc_dvfs_driver.patch
create mode 100644 patches/linux/2.6.38/446-armadeus-add_freescale_ipu3_driver.patch
diff --git a/Makefile b/Makefile
index 20c4e1c..ae1abc8 100644
--- a/Makefile
+++ b/Makefile
@@ -135,8 +135,13 @@ buildauto: $(BUILDROOT_DIR)/.patched
$(MAKE) -C $(BUILDROOT_DIR)
linux26 linux: $(BUILDROOT_DIR)/.configured
- @-touch $(ARMADEUS_LINUX_DIR)/.config
+ifeq ($(BUILDROOT_VERSION),2011.05)
+ @-touch $(ARMADEUS_LINUX_DIR)/.config
@$(MAKE) -C $(BUILDROOT_DIR) $@
+else
+ @rm -f $(ARMADEUS_LINUX_DIR)/.stamp_built
+ @$(MAKE) -C $(BUILDROOT_DIR) linux
+endif
linux26-clean linux-clean: $(BUILDROOT_DIR)/.configured
ifneq (,$(filter $(BUILDROOT_VERSION),20081103 2010.05))
diff --git a/buildroot/.gitignore b/buildroot/.gitignore
index b742057..bf9a495 100644
--- a/buildroot/.gitignore
+++ b/buildroot/.gitignore
@@ -2,12 +2,14 @@
/boot/
/dl
/docs/
+/downloads
/fs/
/linux/
/output/
/project/
/toolchain
/scripts/
+/support
/.*
!/.gitignore
/Config.in
diff --git a/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-events_vpu_srtc_drivers.patch b/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-events_vpu_srtc_drivers.patch
index f90b18e..8e26798 100644
--- a/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-events_vpu_srtc_drivers.patch
+++ b/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-events_vpu_srtc_drivers.patch
@@ -17,10 +17,6 @@ Signed-off-by: Dinh Nguyen <Din...@fr...>
drivers/mxc/hw_event/Kconfig | 11 +
drivers/mxc/hw_event/Makefile | 1 +
drivers/mxc/hw_event/mxc_hw_event.c | 266 +
- drivers/mxc/vpu/Kconfig | 30 +
- drivers/mxc/vpu/Makefile | 10 +
- drivers/mxc/vpu/mxc_vl2cc.c | 124 +
- drivers/mxc/vpu/mxc_vpu.c | 862 ++
drivers/rtc/Kconfig | 46 +
drivers/rtc/Makefile | 5 +
drivers/rtc/rtc-mxc_v2.c | 766 ++
@@ -29,7 +25,7 @@ Signed-off-by: Dinh Nguyen <Din...@fr...>
Index: linux-2.6.38.8/drivers/mxc/hw_event/Kconfig
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/hw_event/Kconfig 2011-10-20 19:28:29.000000000 +0200
++++ linux-2.6.38.8/drivers/mxc/hw_event/Kconfig 2012-03-13 11:32:42.000000000 +0100
@@ -0,0 +1,11 @@
+menu "MXC HARDWARE EVENT"
+
@@ -45,13 +41,13 @@ Index: linux-2.6.38.8/drivers/mxc/hw_event/Kconfig
Index: linux-2.6.38.8/drivers/mxc/hw_event/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/hw_event/Makefile 2011-10-20 19:28:29.000000000 +0200
++++ linux-2.6.38.8/drivers/mxc/hw_event/Makefile 2012-03-13 11:32:42.000000000 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_MXC_HWEVENT) += mxc_hw_event.o
Index: linux-2.6.38.8/drivers/mxc/hw_event/mxc_hw_event.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/hw_event/mxc_hw_event.c 2011-10-20 19:28:29.000000000 +0200
++++ linux-2.6.38.8/drivers/mxc/hw_event/mxc_hw_event.c 2012-03-13 11:32:42.000000000 +0100
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2007-2010 Freescale Semiconductor, Inc. All Rights Reserved.
@@ -319,1056 +315,10 @@ Index: linux-2.6.38.8/drivers/mxc/hw_event/mxc_hw_event.c
+
+EXPORT_SYMBOL(hw_event_send);
+MODULE_LICENSE("GPL");
-Index: linux-2.6.38.8/drivers/mxc/vpu/Kconfig
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/vpu/Kconfig 2011-10-20 19:28:29.000000000 +0200
-@@ -0,0 +1,30 @@
-+#
-+# Codec configuration
-+#
-+
-+menu "MXC VPU(Video Processing Unit) support"
-+
-+config MXC_VPU
-+ tristate "Support for MXC VPU(Video Processing Unit)"
-+ depends on (ARCH_MX3 || ARCH_MX27 || ARCH_MX37 || ARCH_MX5)
-+ default y
-+ ---help---
-+ The VPU codec device provides codec function for H.264/MPEG4/H.263,
-+ as well as MPEG2/VC-1/DivX on some platforms.
-+
-+config MXC_VPU_IRAM
-+ tristate "Use IRAM as temporary buffer for VPU to enhance performace"
-+ depends on (ARCH_MX37 || ARCH_MX5)
-+ default y
-+ ---help---
-+ The VPU can use internal RAM as temporary buffer to save external
-+ memroy bandwith, thus to enhance video performance.
-+
-+config MXC_VPU_DEBUG
-+ bool "MXC VPU debugging"
-+ depends on MXC_VPU != n
-+ help
-+ This is an option for the developers; most people should
-+ say N here. This enables MXC VPU driver debugging.
-+
-+endmenu
-Index: linux-2.6.38.8/drivers/mxc/vpu/Makefile
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/vpu/Makefile 2011-10-20 19:28:29.000000000 +0200
-@@ -0,0 +1,10 @@
-+#
-+# Makefile for the VPU drivers.
-+#
-+
-+obj-$(CONFIG_MXC_VPU) += vpu.o
-+vpu-objs := mxc_vpu.o mxc_vl2cc.o
-+
-+ifeq ($(CONFIG_MXC_VPU_DEBUG),y)
-+EXTRA_CFLAGS += -DDEBUG
-+endif
-Index: linux-2.6.38.8/drivers/mxc/vpu/mxc_vl2cc.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/vpu/mxc_vl2cc.c 2011-10-20 19:28:29.000000000 +0200
-@@ -0,0 +1,124 @@
-+/*
-+ * Copyright 2007-2010 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+
-+/*
-+ * The code contained herein is licensed under the GNU General Public
-+ * License. You may obtain a copy of the GNU General Public License
-+ * Version 2 or later at the following locations:
-+ *
-+ * http://www.opensource.org/licenses/gpl-license.html
-+ * http://www.gnu.org/copyleft/gpl.html
-+ */
-+
-+/*!
-+ * @file mxc_vl2cc.c
-+ *
-+ * @brief VL2CC initialization and flush operation implementation
-+ *
-+ * @ingroup VL2CC
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+
-+#define VL2CC_CTRL_OFFSET (0x100)
-+#define VL2CC_AUXCTRL_OFFSET (0x104)
-+#define VL2CC_INVWAY_OFFSET (0x77C)
-+#define VL2CC_CLEANWAY_OFFSET (0x7BC)
-+
-+/*! VL2CC clock handle. */
-+static struct clk *vl2cc_clk;
-+static u32 *vl2cc_base;
-+
-+/*!
-+ * Initialization function of VL2CC. Remap the VL2CC base address.
-+ *
-+ * @return status 0 success.
-+ */
-+int vl2cc_init(u32 vl2cc_hw_base)
-+{
-+ vl2cc_base = ioremap(vl2cc_hw_base, SZ_8K - 1);
-+ if (vl2cc_base == NULL) {
-+ printk(KERN_INFO "vl2cc: Unable to ioremap\n");
-+ return -ENOMEM;
-+ }
-+
-+ vl2cc_clk = clk_get(NULL, "vl2cc_clk");
-+ if (IS_ERR(vl2cc_clk)) {
-+ printk(KERN_INFO "vl2cc: Unable to get clock\n");
-+ iounmap(vl2cc_base);
-+ return -EIO;
-+ }
-+
-+ printk(KERN_INFO "VL2CC initialized\n");
-+ return 0;
-+}
-+
-+/*!
-+ * Enable VL2CC hardware
-+ */
-+void vl2cc_enable(void)
-+{
-+ volatile u32 reg;
-+
-+ clk_enable(vl2cc_clk);
-+
-+ /* Disable VL2CC */
-+ reg = __raw_readl(vl2cc_base + VL2CC_CTRL_OFFSET);
-+ reg &= 0xFFFFFFFE;
-+ __raw_writel(reg, vl2cc_base + VL2CC_CTRL_OFFSET);
-+
-+ /* Set the latency for data RAM reads, data RAM writes, tag RAM and
-+ * dirty RAM to 1 cycle - write 0x0 to AUX CTRL [11:0] and also
-+ * configure the number of ways to 8 - write 8 to AUX CTRL [16:13]
-+ */
-+ reg = __raw_readl(vl2cc_base + VL2CC_AUXCTRL_OFFSET);
-+ reg &= 0xFFFE1000; /* Clear [16:13] too */
-+ reg |= (0x8 << 13); /* [16:13] = 8; */
-+ __raw_writel(reg, vl2cc_base + VL2CC_AUXCTRL_OFFSET);
-+
-+ /* Invalidate the VL2CC ways - write 0xff to INV BY WAY and poll the
-+ * register until its value is 0x0
-+ */
-+ __raw_writel(0xff, vl2cc_base + VL2CC_INVWAY_OFFSET);
-+ while (__raw_readl(vl2cc_base + VL2CC_INVWAY_OFFSET) != 0x0)
-+ ;
-+
-+ /* Enable VL2CC */
-+ reg = __raw_readl(vl2cc_base + VL2CC_CTRL_OFFSET);
-+ reg |= 0x1;
-+ __raw_writel(reg, vl2cc_base + VL2CC_CTRL_OFFSET);
-+}
-+
-+/*!
-+ * Flush VL2CC
-+ */
-+void vl2cc_flush(void)
-+{
-+ __raw_writel(0xff, vl2cc_base + VL2CC_CLEANWAY_OFFSET);
-+ while (__raw_readl(vl2cc_base + VL2CC_CLEANWAY_OFFSET) != 0x0)
-+ ;
-+}
-+
-+/*!
-+ * Disable VL2CC
-+ */
-+void vl2cc_disable(void)
-+{
-+ __raw_writel(0, vl2cc_base + VL2CC_CTRL_OFFSET);
-+ clk_disable(vl2cc_clk);
-+}
-+
-+/*!
-+ * Cleanup VL2CC
-+ */
-+void vl2cc_cleanup(void)
-+{
-+ clk_put(vl2cc_clk);
-+ iounmap(vl2cc_base);
-+}
-Index: linux-2.6.38.8/drivers/mxc/vpu/mxc_vpu.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/vpu/mxc_vpu.c 2011-10-20 19:28:29.000000000 +0200
-@@ -0,0 +1,862 @@
-+/*
-+ * Copyright 2006-2010 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+
-+/*
-+ * The code contained herein is licensed under the GNU General Public
-+ * License. You may obtain a copy of the GNU General Public License
-+ * Version 2 or later at the following locations:
-+ *
-+ * http://www.opensource.org/licenses/gpl-license.html
-+ * http://www.gnu.org/copyleft/gpl.html
-+ */
-+
-+/*!
-+ * @file mxc_vpu.c
-+ *
-+ * @brief VPU system initialization and file operation implementation
-+ *
-+ * @ingroup VPU
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/interrupt.h>
-+#include <linux/ioport.h>
-+#include <linux/stat.h>
-+#include <linux/platform_device.h>
-+#include <linux/kdev_t.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/iram_alloc.h>
-+#include <linux/wait.h>
-+#include <linux/list.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/fsl_devices.h>
-+#include <linux/uaccess.h>
-+#include <linux/io.h>
-+#include <linux/slab.h>
-+
-+#include <asm/sizes.h>
-+#include <mach/clock.h>
-+#include <mach/hardware.h>
-+
-+#include <mach/mxc_vpu.h>
-+
-+struct vpu_priv {
-+ struct fasync_struct *async_queue;
-+};
-+
-+/* To track the allocated memory buffer */
-+typedef struct memalloc_record {
-+ struct list_head list;
-+ struct vpu_mem_desc mem;
-+} memalloc_record;
-+
-+struct iram_setting {
-+ u32 start;
-+ u32 end;
-+};
-+
-+static DEFINE_SPINLOCK(vpu_lock);
-+static LIST_HEAD(head);
-+
-+static int vpu_major;
-+static int vpu_clk_usercount;
-+static struct class *vpu_class;
-+static struct vpu_priv vpu_data;
-+static u8 open_count;
-+static struct clk *vpu_clk;
-+static struct vpu_mem_desc bitwork_mem = { 0 };
-+static struct vpu_mem_desc pic_para_mem = { 0 };
-+static struct vpu_mem_desc user_data_mem = { 0 };
-+static struct vpu_mem_desc share_mem = { 0 };
-+
-+static void __iomem *vpu_base;
-+static int vpu_irq;
-+static u32 phy_vpu_base_addr;
-+static struct mxc_vpu_platform_data *vpu_plat;
-+
-+/* IRAM setting */
-+static struct iram_setting iram;
-+
-+/* implement the blocking ioctl */
-+static int codec_done;
-+static wait_queue_head_t vpu_queue;
-+
-+static u32 workctrl_regsave[6];
-+static u32 rd_ptr_regsave[4];
-+static u32 wr_ptr_regsave[4];
-+static u32 dis_flag_regsave[4];
-+
-+#define READ_REG(x) __raw_readl(vpu_base + x)
-+#define WRITE_REG(val, x) __raw_writel(val, vpu_base + x)
-+#define SAVE_WORK_REGS do { \
-+ int i; \
-+ for (i = 0; i < ARRAY_SIZE(workctrl_regsave)/2; i++) \
-+ workctrl_regsave[i] = READ_REG(BIT_WORK_CTRL_BUF_REG(i));\
-+} while (0)
-+#define RESTORE_WORK_REGS do { \
-+ int i; \
-+ for (i = 0; i < ARRAY_SIZE(workctrl_regsave)/2; i++) \
-+ WRITE_REG(workctrl_regsave[i], BIT_WORK_CTRL_BUF_REG(i));\
-+} while (0)
-+#define SAVE_CTRL_REGS do { \
-+ int i; \
-+ for (i = ARRAY_SIZE(workctrl_regsave)/2; \
-+ i < ARRAY_SIZE(workctrl_regsave); i++) \
-+ workctrl_regsave[i] = READ_REG(BIT_WORK_CTRL_BUF_REG(i));\
-+} while (0)
-+#define RESTORE_CTRL_REGS do { \
-+ int i; \
-+ for (i = ARRAY_SIZE(workctrl_regsave)/2; \
-+ i < ARRAY_SIZE(workctrl_regsave); i++) \
-+ WRITE_REG(workctrl_regsave[i], BIT_WORK_CTRL_BUF_REG(i));\
-+} while (0)
-+#define SAVE_RDWR_PTR_REGS do { \
-+ int i; \
-+ for (i = 0; i < ARRAY_SIZE(rd_ptr_regsave); i++) \
-+ rd_ptr_regsave[i] = READ_REG(BIT_RD_PTR_REG(i)); \
-+ for (i = 0; i < ARRAY_SIZE(wr_ptr_regsave); i++) \
-+ wr_ptr_regsave[i] = READ_REG(BIT_WR_PTR_REG(i)); \
-+} while (0)
-+#define RESTORE_RDWR_PTR_REGS do { \
-+ int i; \
-+ for (i = 0; i < ARRAY_SIZE(rd_ptr_regsave); i++) \
-+ WRITE_REG(rd_ptr_regsave[i], BIT_RD_PTR_REG(i)); \
-+ for (i = 0; i < ARRAY_SIZE(wr_ptr_regsave); i++) \
-+ WRITE_REG(wr_ptr_regsave[i], BIT_WR_PTR_REG(i)); \
-+} while (0)
-+#define SAVE_DIS_FLAG_REGS do { \
-+ int i; \
-+ for (i = 0; i < ARRAY_SIZE(dis_flag_regsave); i++) \
-+ dis_flag_regsave[i] = READ_REG(BIT_FRM_DIS_FLG_REG(i)); \
-+} while (0)
-+#define RESTORE_DIS_FLAG_REGS do { \
-+ int i; \
-+ for (i = 0; i < ARRAY_SIZE(dis_flag_regsave); i++) \
-+ WRITE_REG(dis_flag_regsave[i], BIT_FRM_DIS_FLG_REG(i)); \
-+} while (0)
-+
-+/*!
-+ * Private function to alloc dma buffer
-+ * @return status 0 success.
-+ */
-+static int vpu_alloc_dma_buffer(struct vpu_mem_desc *mem)
-+{
-+ mem->cpu_addr = (unsigned long)
-+ dma_alloc_coherent(NULL, PAGE_ALIGN(mem->size),
-+ (dma_addr_t *) (&mem->phy_addr),
-+ GFP_DMA | GFP_KERNEL);
-+ pr_debug("[ALLOC] mem alloc cpu_addr = 0x%x\n", mem->cpu_addr);
-+ if ((void *)(mem->cpu_addr) == NULL) {
-+ printk(KERN_ERR "Physical memory allocation error!\n");
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+/*!
-+ * Private function to free dma buffer
-+ */
-+static void vpu_free_dma_buffer(struct vpu_mem_desc *mem)
-+{
-+ if (mem->cpu_addr != 0) {
-+ dma_free_coherent(0, PAGE_ALIGN(mem->size),
-+ (void *)mem->cpu_addr, mem->phy_addr);
-+ }
-+}
-+
-+/*!
-+ * Private function to free buffers
-+ * @return status 0 success.
-+ */
-+static int vpu_free_buffers(void)
-+{
-+ struct memalloc_record *rec, *n;
-+ struct vpu_mem_desc mem;
-+
-+ list_for_each_entry_safe(rec, n, &head, list) {
-+ mem = rec->mem;
-+ if (mem.cpu_addr != 0) {
-+ vpu_free_dma_buffer(&mem);
-+ pr_debug("[FREE] freed paddr=0x%08X\n", mem.phy_addr);
-+ /* delete from list */
-+ list_del(&rec->list);
-+ kfree(rec);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/*!
-+ * @brief vpu interrupt handler
-+ */
-+static irqreturn_t vpu_irq_handler(int irq, void *dev_id)
-+{
-+ struct vpu_priv *dev = dev_id;
-+
-+ READ_REG(BIT_INT_STATUS);
-+ WRITE_REG(0x1, BIT_INT_CLEAR);
-+
-+ if (dev->async_queue)
-+ kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
-+
-+ /*
-+ * Clock is gated on when dec/enc started, gate it off when
-+ * interrupt is received.
-+ */
-+ clk_disable(vpu_clk);
-+
-+ codec_done = 1;
-+ wake_up_interruptible(&vpu_queue);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+/*!
-+ * @brief open function for vpu file operation
-+ *
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_open(struct inode *inode, struct file *filp)
-+{
-+ spin_lock(&vpu_lock);
-+ if ((open_count++ == 0) && cpu_is_mx32())
-+ vl2cc_enable();
-+ filp->private_data = (void *)(&vpu_data);
-+ spin_unlock(&vpu_lock);
-+ return 0;
-+}
-+
-+/*!
-+ * @brief IO ctrl function for vpu file operation
-+ * @param cmd IO ctrl command
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_ioctl(struct inode *inode, struct file *filp, u_int cmd,
-+ u_long arg)
-+{
-+ int ret = 0;
-+
-+ switch (cmd) {
-+ case VPU_IOC_PHYMEM_ALLOC:
-+ {
-+ struct memalloc_record *rec;
-+
-+ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
-+ if (!rec)
-+ return -ENOMEM;
-+
-+ ret = copy_from_user(&(rec->mem),
-+ (struct vpu_mem_desc *)arg,
-+ sizeof(struct vpu_mem_desc));
-+ if (ret) {
-+ kfree(rec);
-+ return -EFAULT;
-+ }
-+
-+ pr_debug("[ALLOC] mem alloc size = 0x%x\n",
-+ rec->mem.size);
-+
-+ ret = vpu_alloc_dma_buffer(&(rec->mem));
-+ if (ret == -1) {
-+ kfree(rec);
-+ printk(KERN_ERR
-+ "Physical memory allocation error!\n");
-+ break;
-+ }
-+ ret = copy_to_user((void __user *)arg, &(rec->mem),
-+ sizeof(struct vpu_mem_desc));
-+ if (ret) {
-+ kfree(rec);
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ spin_lock(&vpu_lock);
-+ list_add(&rec->list, &head);
-+ spin_unlock(&vpu_lock);
-+
-+ break;
-+ }
-+ case VPU_IOC_PHYMEM_FREE:
-+ {
-+ struct memalloc_record *rec, *n;
-+ struct vpu_mem_desc vpu_mem;
-+
-+ ret = copy_from_user(&vpu_mem,
-+ (struct vpu_mem_desc *)arg,
-+ sizeof(struct vpu_mem_desc));
-+ if (ret)
-+ return -EACCES;
-+
-+ pr_debug("[FREE] mem freed cpu_addr = 0x%x\n",
-+ vpu_mem.cpu_addr);
-+ if ((void *)vpu_mem.cpu_addr != NULL) {
-+ vpu_free_dma_buffer(&vpu_mem);
-+ }
-+
-+ spin_lock(&vpu_lock);
-+ list_for_each_entry_safe(rec, n, &head, list) {
-+ if (rec->mem.cpu_addr == vpu_mem.cpu_addr) {
-+ /* delete from list */
-+ list_del(&rec->list);
-+ kfree(rec);
-+ break;
-+ }
-+ }
-+ spin_unlock(&vpu_lock);
-+
-+ break;
-+ }
-+ case VPU_IOC_WAIT4INT:
-+ {
-+ u_long timeout = (u_long) arg;
-+ if (!wait_event_interruptible_timeout
-+ (vpu_queue, codec_done != 0,
-+ msecs_to_jiffies(timeout))) {
-+ printk(KERN_WARNING "VPU blocking: timeout.\n");
-+ ret = -ETIME;
-+ } else if (signal_pending(current)) {
-+ printk(KERN_WARNING
-+ "VPU interrupt received.\n");
-+ ret = -ERESTARTSYS;
-+ } else
-+ codec_done = 0;
-+ break;
-+ }
-+ case VPU_IOC_VL2CC_FLUSH:
-+ if (cpu_is_mx32()) {
-+ vl2cc_flush();
-+ }
-+ break;
-+ case VPU_IOC_IRAM_SETTING:
-+ {
-+ ret = copy_to_user((void __user *)arg, &iram,
-+ sizeof(struct iram_setting));
-+ if (ret)
-+ ret = -EFAULT;
-+
-+ break;
-+ }
-+ case VPU_IOC_CLKGATE_SETTING:
-+ {
-+ u32 clkgate_en;
-+
-+ if (get_user(clkgate_en, (u32 __user *) arg))
-+ return -EFAULT;
-+
-+ if (clkgate_en) {
-+ clk_enable(vpu_clk);
-+ } else {
-+ clk_disable(vpu_clk);
-+ }
-+
-+ break;
-+ }
-+ case VPU_IOC_GET_SHARE_MEM:
-+ {
-+ spin_lock(&vpu_lock);
-+ if (share_mem.cpu_addr != 0) {
-+ ret = copy_to_user((void __user *)arg,
-+ &share_mem,
-+ sizeof(struct vpu_mem_desc));
-+ spin_unlock(&vpu_lock);
-+ break;
-+ } else {
-+ if (copy_from_user(&share_mem,
-+ (struct vpu_mem_desc *)arg,
-+ sizeof(struct vpu_mem_desc))) {
-+ spin_unlock(&vpu_lock);
-+ return -EFAULT;
-+ }
-+ if (vpu_alloc_dma_buffer(&share_mem) == -1)
-+ ret = -EFAULT;
-+ else {
-+ if (copy_to_user((void __user *)arg,
-+ &share_mem,
-+ sizeof(struct
-+ vpu_mem_desc)))
-+ ret = -EFAULT;
-+ }
-+ }
-+ spin_unlock(&vpu_lock);
-+ break;
-+ }
-+ case VPU_IOC_GET_WORK_ADDR:
-+ {
-+ if (bitwork_mem.cpu_addr != 0) {
-+ ret =
-+ copy_to_user((void __user *)arg,
-+ &bitwork_mem,
-+ sizeof(struct vpu_mem_desc));
-+ break;
-+ } else {
-+ if (copy_from_user(&bitwork_mem,
-+ (struct vpu_mem_desc *)arg,
-+ sizeof(struct vpu_mem_desc)))
-+ return -EFAULT;
-+
-+ if (vpu_alloc_dma_buffer(&bitwork_mem) == -1)
-+ ret = -EFAULT;
-+ else if (copy_to_user((void __user *)arg,
-+ &bitwork_mem,
-+ sizeof(struct
-+ vpu_mem_desc)))
-+ ret = -EFAULT;
-+ }
-+ break;
-+ }
-+ case VPU_IOC_GET_PIC_PARA_ADDR:
-+ {
-+ if (pic_para_mem.cpu_addr != 0) {
-+ ret =
-+ copy_to_user((void __user *)arg,
-+ &pic_para_mem,
-+ sizeof(struct vpu_mem_desc));
-+ break;
-+ } else {
-+ if (copy_from_user(&pic_para_mem,
-+ (struct vpu_mem_desc *)arg,
-+ sizeof(struct vpu_mem_desc)))
-+ return -EFAULT;
-+
-+ if (vpu_alloc_dma_buffer(&pic_para_mem) == -1)
-+ ret = -EFAULT;
-+ else if (copy_to_user((void __user *)arg,
-+ &pic_para_mem,
-+ sizeof(struct
-+ vpu_mem_desc)))
-+ ret = -EFAULT;
-+ }
-+ break;
-+ }
-+ case VPU_IOC_GET_USER_DATA_ADDR:
-+ {
-+ if (user_data_mem.cpu_addr != 0) {
-+ ret =
-+ copy_to_user((void __user *)arg,
-+ &user_data_mem,
-+ sizeof(struct vpu_mem_desc));
-+ break;
-+ } else {
-+ if (copy_from_user(&user_data_mem,
-+ (struct vpu_mem_desc *)arg,
-+ sizeof(struct vpu_mem_desc)))
-+ return -EFAULT;
-+
-+ if (vpu_alloc_dma_buffer(&user_data_mem) == -1)
-+ ret = -EFAULT;
-+ else if (copy_to_user((void __user *)arg,
-+ &user_data_mem,
-+ sizeof(struct
-+ vpu_mem_desc)))
-+ ret = -EFAULT;
-+ }
-+ break;
-+ }
-+ case VPU_IOC_SYS_SW_RESET:
-+ {
-+ if (vpu_plat->reset)
-+ vpu_plat->reset();
-+
-+ break;
-+ }
-+ case VPU_IOC_REG_DUMP:
-+ break;
-+ case VPU_IOC_PHYMEM_DUMP:
-+ break;
-+ default:
-+ {
-+ printk(KERN_ERR "No such IOCTL, cmd is %d\n", cmd);
-+ break;
-+ }
-+ }
-+ return ret;
-+}
-+
-+/*!
-+ * @brief Release function for vpu file operation
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_release(struct inode *inode, struct file *filp)
-+{
-+ spin_lock(&vpu_lock);
-+ if (open_count > 0 && !(--open_count)) {
-+ vpu_free_buffers();
-+
-+ if (cpu_is_mx32())
-+ vl2cc_disable();
-+
-+ /* Free shared memory when vpu device is idle */
-+ vpu_free_dma_buffer(&share_mem);
-+ share_mem.cpu_addr = 0;
-+ }
-+ spin_unlock(&vpu_lock);
-+
-+ return 0;
-+}
-+
-+/*!
-+ * @brief fasync function for vpu file operation
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_fasync(int fd, struct file *filp, int mode)
-+{
-+ struct vpu_priv *dev = (struct vpu_priv *)filp->private_data;
-+ return fasync_helper(fd, filp, mode, &dev->async_queue);
-+}
-+
-+/*!
-+ * @brief memory map function of harware registers for vpu file operation
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm)
-+{
-+ unsigned long pfn;
-+
-+ vm->vm_flags |= VM_IO | VM_RESERVED;
-+ vm->vm_page_prot = pgprot_noncached(vm->vm_page_prot);
-+ pfn = phy_vpu_base_addr >> PAGE_SHIFT;
-+ pr_debug("size=0x%x, page no.=0x%x\n",
-+ (int)(vm->vm_end - vm->vm_start), (int)pfn);
-+ return remap_pfn_range(vm, vm->vm_start, pfn, vm->vm_end - vm->vm_start,
-+ vm->vm_page_prot) ? -EAGAIN : 0;
-+}
-+
-+/*!
-+ * @brief memory map function of memory for vpu file operation
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_map_mem(struct file *fp, struct vm_area_struct *vm)
-+{
-+ int request_size;
-+ request_size = vm->vm_end - vm->vm_start;
-+
-+ pr_debug(" start=0x%x, pgoff=0x%x, size=0x%x\n",
-+ (unsigned int)(vm->vm_start), (unsigned int)(vm->vm_pgoff),
-+ request_size);
-+
-+ vm->vm_flags |= VM_IO | VM_RESERVED;
-+ vm->vm_page_prot = pgprot_noncached(vm->vm_page_prot);
-+
-+ return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff,
-+ request_size, vm->vm_page_prot) ? -EAGAIN : 0;
-+
-+}
-+
-+/*!
-+ * @brief memory map interface for vpu file operation
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_mmap(struct file *fp, struct vm_area_struct *vm)
-+{
-+ if (vm->vm_pgoff)
-+ return vpu_map_mem(fp, vm);
-+ else
-+ return vpu_map_hwregs(fp, vm);
-+}
-+
-+struct file_operations vpu_fops = {
-+ .owner = THIS_MODULE,
-+ .open = vpu_open,
-+ .ioctl = vpu_ioctl,
-+ .release = vpu_release,
-+ .fasync = vpu_fasync,
-+ .mmap = vpu_mmap,
-+};
-+
-+/*!
-+ * This function is called by the driver framework to initialize the vpu device.
-+ * @param dev The device structure for the vpu passed in by the framework.
-+ * @return 0 on success or negative error code on error
-+ */
-+static int vpu_dev_probe(struct platform_device *pdev)
-+{
-+ int err = 0;
-+ struct device *temp_class;
-+ struct resource *res;
-+ unsigned long addr = 0;
-+
-+ vpu_plat = pdev->dev.platform_data;
-+
-+ iram_alloc(VPU_IRAM_SIZE, &addr);
-+ if (addr == 0)
-+ iram.start = iram.end = 0;
-+ else {
-+ iram.start = addr;
-+ iram.end = addr + VPU_IRAM_SIZE - 1;
-+ }
-+
-+ if (cpu_is_mx32()) {
-+ err = vl2cc_init(iram.start);
-+ if (err != 0)
-+ return err;
-+ }
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ printk(KERN_ERR "vpu: unable to get vpu base addr\n");
-+ return -ENODEV;
-+ }
-+ phy_vpu_base_addr = res->start;
-+ vpu_base = ioremap(res->start, res->end - res->start);
-+
-+ vpu_major = register_chrdev(vpu_major, "mxc_vpu", &vpu_fops);
-+ if (vpu_major < 0) {
-+ printk(KERN_ERR "vpu: unable to get a major for VPU\n");
-+ err = -EBUSY;
-+ goto error;
-+ }
-+
-+ vpu_class = class_create(THIS_MODULE, "mxc_vpu");
-+ if (IS_ERR(vpu_class)) {
-+ err = PTR_ERR(vpu_class);
-+ goto err_out_chrdev;
-+ }
-+
-+ temp_class = device_create(vpu_class, NULL, MKDEV(vpu_major, 0),
-+ NULL, "mxc_vpu");
-+ if (IS_ERR(temp_class)) {
-+ err = PTR_ERR(temp_class);
-+ goto err_out_class;
-+ }
-+
-+ vpu_clk = clk_get(&pdev->dev, "vpu_clk");
-+ if (IS_ERR(vpu_clk)) {
-+ err = -ENOENT;
-+ goto err_out_class;
-+ }
-+
-+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ if (!res) {
-+ printk(KERN_ERR "vpu: unable to get vpu interrupt\n");
-+ err = -ENXIO;
-+ goto err_out_class;
-+ }
-+ vpu_irq = res->start;
-+
-+ err = request_irq(vpu_irq, vpu_irq_handler, 0, "VPU_CODEC_IRQ",
-+ (void *)(&vpu_data));
-+ if (err)
-+ goto err_out_class;
-+
-+ printk(KERN_INFO "VPU initialized\n");
-+ goto out;
-+
-+ err_out_class:
-+ device_destroy(vpu_class, MKDEV(vpu_major, 0));
-+ class_destroy(vpu_class);
-+ err_out_chrdev:
-+ unregister_chrdev(vpu_major, "mxc_vpu");
-+ error:
-+ iounmap(vpu_base);
-+ if (cpu_is_mx32()) {
-+ vl2cc_cleanup();
-+ }
-+ out:
-+ return err;
-+}
-+
-+static int vpu_dev_remove(struct platform_device *pdev)
-+{
-+ free_irq(vpu_irq, &vpu_data);
-+ iounmap(vpu_base);
-+ iram_free(iram.start, VPU_IRAM_SIZE);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
-+{
-+ int i;
-+ unsigned long timeout;
-+
-+ /* Wait for vpu go to idle state, suspect vpu cannot be changed
-+ to idle state after about 1 sec */
-+ if (open_count > 0) {
-+ timeout = jiffies + HZ;
-+ clk_enable(vpu_clk);
-+ while (READ_REG(BIT_BUSY_FLAG)) {
-+ msleep(1);
-+ if (time_after(jiffies, timeout))
-+ goto out;
-+ }
-+ clk_disable(vpu_clk);
-+ }
-+
-+ /* Make sure clock is disabled before suspend */
-+ vpu_clk_usercount = clk_get_usecount(vpu_clk);
-+ for (i = 0; i < vpu_clk_usercount; i++)
-+ clk_disable(vpu_clk);
-+
-+ if (!cpu_is_mx53()) {
-+ clk_enable(vpu_clk);
-+ if (bitwork_mem.cpu_addr != 0) {
-+ SAVE_WORK_REGS;
-+ SAVE_CTRL_REGS;
-+ SAVE_RDWR_PTR_REGS;
-+ SAVE_DIS_FLAG_REGS;
-+
-+ WRITE_REG(0x1, BIT_BUSY_FLAG);
-+ WRITE_REG(VPU_SLEEP_REG_VALUE, BIT_RUN_COMMAND);
-+ while (READ_REG(BIT_BUSY_FLAG))
-+ ;
-+ }
-+ clk_disable(vpu_clk);
-+ }
-+
-+ if (cpu_is_mx37() || cpu_is_mx51())
-+ mxc_pg_enable(pdev);
-+
-+ return 0;
-+
-+out:
-+ clk_disable(vpu_clk);
-+ return -EAGAIN;
-+
-+}
-+
-+static int vpu_resume(struct platform_device *pdev)
-+{
-+ int i;
-+
-+ if (cpu_is_mx37() || cpu_is_mx51())
-+ mxc_pg_disable(pdev);
-+
-+ if (cpu_is_mx53())
-+ goto recover_clk;
-+
-+ clk_enable(vpu_clk);
-+ if (bitwork_mem.cpu_addr != 0) {
-+ u32 *p = (u32 *) bitwork_mem.cpu_addr;
-+ u32 data;
-+ u16 data_hi;
-+ u16 data_lo;
-+
-+ RESTORE_WORK_REGS;
-+
-+ WRITE_REG(0x0, BIT_RESET_CTRL);
-+ WRITE_REG(0x0, BIT_CODE_RUN);
-+
-+ /*
-+ * Re-load boot code, from the codebuffer in external RAM.
-+ * Thankfully, we only need 4096 bytes, same for all platforms.
-+ */
-+ if (cpu_is_mx51()) {
-+ for (i = 0; i < 2048; i += 4) {
-+ data = p[(i / 2) + 1];
-+ data_hi = (data >> 16) & 0xFFFF;
-+ data_lo = data & 0xFFFF;
-+ WRITE_REG((i << 16) | data_hi, BIT_CODE_DOWN);
-+ WRITE_REG(((i + 1) << 16) | data_lo,
-+ BIT_CODE_DOWN);
-+
-+ data = p[i / 2];
-+ data_hi = (data >> 16) & 0xFFFF;
-+ data_lo = data & 0xFFFF;
-+ WRITE_REG(((i + 2) << 16) | data_hi,
-+ BIT_CODE_DOWN);
-+ WRITE_REG(((i + 3) << 16) | data_lo,
-+ BIT_CODE_DOWN);
-+ }
-+ } else {
-+ for (i = 0; i < 2048; i += 2) {
-+ if (cpu_is_mx37())
-+ data = swab32(p[i / 2]);
-+ else
-+ data = p[i / 2];
-+ data_hi = (data >> 16) & 0xFFFF;
-+ data_lo = data & 0xFFFF;
-+
-+ WRITE_REG((i << 16) | data_hi, BIT_CODE_DOWN);
-+ WRITE_REG(((i + 1) << 16) | data_lo,
-+ BIT_CODE_DOWN);
-+ }
-+ }
-+
-+ RESTORE_CTRL_REGS;
-+
-+ WRITE_REG(BITVAL_PIC_RUN, BIT_INT_ENABLE);
-+
-+ WRITE_REG(0x1, BIT_BUSY_FLAG);
-+ WRITE_REG(0x1, BIT_CODE_RUN);
-+ while (READ_REG(BIT_BUSY_FLAG))
-+ ;
-+
-+ RESTORE_RDWR_PTR_REGS;
-+ RESTORE_DIS_FLAG_REGS;
-+
-+ WRITE_REG(0x1, BIT_BUSY_FLAG);
-+ WRITE_REG(VPU_WAKE_REG_VALUE, BIT_RUN_COMMAND);
-+ while (READ_REG(BIT_BUSY_FLAG))
-+ ;
-+ }
-+ clk_disable(vpu_clk);
-+
-+recover_clk:
-+ /* Recover vpu clock */
-+ for (i = 0; i < vpu_clk_usercount; i++)
-+ clk_enable(vpu_clk);
-+
-+ return 0;
-+}
-+#else
-+#define vpu_suspend NULL
-+#define vpu_resume NULL
-+#endif /* !CONFIG_PM */
-+
-+/*! Driver definition
-+ *
-+ */
-+static struct platform_driver mxcvpu_driver = {
-+ .driver = {
-+ .name = "mxc_vpu",
-+ },
-+ .probe = vpu_dev_probe,
-+ .remove = vpu_dev_remove,
-+ .suspend = vpu_suspend,
-+ .resume = vpu_resume,
-+};
-+
-+static int __init vpu_init(void)
-+{
-+ int ret = platform_driver_register(&mxcvpu_driver);
-+
-+ init_waitqueue_head(&vpu_queue);
-+
-+ return ret;
-+}
-+
-+static void __exit vpu_exit(void)
-+{
-+ if (vpu_major > 0) {
-+ device_destroy(vpu_class, MKDEV(vpu_major, 0));
-+ class_destroy(vpu_class);
-+ unregister_chrdev(vpu_major, "mxc_vpu");
-+ vpu_major = 0;
-+ }
-+
-+ if (cpu_is_mx32()) {
-+ vl2cc_cleanup();
-+ }
-+
-+ vpu_free_dma_buffer(&bitwork_mem);
-+ vpu_free_dma_buffer(&pic_para_mem);
-+ vpu_free_dma_buffer(&user_data_mem);
-+
-+ clk_put(vpu_clk);
-+
-+ platform_driver_unregister(&mxcvpu_driver);
-+ return;
-+}
-+
-+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-+MODULE_DESCRIPTION("Linux VPU driver for Freescale i.MX/MXC");
-+MODULE_LICENSE("GPL");
-+
-+module_init(vpu_init);
-+module_exit(vpu_exit);
Index: linux-2.6.38.8/drivers/rtc/Kconfig
===================================================================
--- linux-2.6.38.8.orig/drivers/rtc/Kconfig 2011-06-03 03:35:11.000000000 +0200
-+++ linux-2.6.38.8/drivers/rtc/Kconfig 2011-10-20 19:28:29.000000000 +0200
++++ linux-2.6.38.8/drivers/rtc/Kconfig 2012-03-13 11:32:42.000000000 +0100
@@ -600,6 +600,13 @@
This driver can also be built as a module, if so, the module
will be called "rtc-mxc".
@@ -1394,7 +344,7 @@ Index: linux-2.6.38.8/drivers/rtc/Kconfig
Index: linux-2.6.38.8/drivers/rtc/Makefile
===================================================================
--- linux-2.6.38.8.orig/drivers/rtc/Makefile 2011-06-03 03:35:11.000000000 +0200
-+++ linux-2.6.38.8/drivers/rtc/Makefile 2011-10-20 19:28:29.000000000 +0200
++++ linux-2.6.38.8/drivers/rtc/Makefile 2012-03-13 11:32:42.000000000 +0100
@@ -101,3 +101,4 @@
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
@@ -1403,7 +353,7 @@ Index: linux-2.6.38.8/drivers/rtc/Makefile
Index: linux-2.6.38.8/drivers/rtc/rtc-mxc_v2.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/rtc/rtc-mxc_v2.c 2011-10-20 19:28:29.000000000 +0200
++++ linux-2.6.38.8/drivers/rtc/rtc-mxc_v2.c 2012-03-13 11:32:42.000000000 +0100
@@ -0,0 +1,766 @@
+/*
+ * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
@@ -2173,14 +1123,13 @@ Index: linux-2.6.38.8/drivers/rtc/rtc-mxc_v2.c
+MODULE_LICENSE("GPL");
Index: linux-2.6.38.8/drivers/mxc/Kconfig
===================================================================
---- linux-2.6.38.8.orig/drivers/mxc/Kconfig 2011-10-20 19:28:29.000000000 +0200
-+++ linux-2.6.38.8/drivers/mxc/Kconfig 2011-10-20 19:42:54.000000000 +0200
-@@ -4,6 +4,9 @@
+--- linux-2.6.38.8.orig/drivers/mxc/Kconfig 2012-03-13 11:32:42.000000000 +0100
++++ linux-2.6.38.8/drivers/mxc/Kconfig 2012-03-13 17:43:40.000000000 +0100
+@@ -4,6 +4,8 @@
menu "MXC support drivers"
+source "drivers/mxc/hw_event/Kconfig"
-+source "drivers/mxc/vpu/Kconfig"
+
endmenu
@@ -2188,14 +1137,13 @@ Index: linux-2.6.38.8/drivers/mxc/Kconfig
Index: linux-2.6.38.8/drivers/mxc/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/drivers/mxc/Makefile 2011-10-20 19:42:54.000000000 +0200
-@@ -0,0 +1,2 @@
-+obj-$(CONFIG_MXC_VPU) += vpu/
++++ linux-2.6.38.8/drivers/mxc/Makefile 2012-03-13 17:43:40.000000000 +0100
+@@ -0,0 +1,1 @@
+obj-$(CONFIG_MXC_HWEVENT) += hw_event/
Index: linux-2.6.38.8/arch/arm/plat-mxc/include/mach/hw_events.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.38.8/arch/arm/plat-mxc/include/mach/hw_events.h 2011-10-20 19:45:54.000000000 +0200
++++ linux-2.6.38.8/arch/arm/plat-mxc/include/mach/hw_events.h 2012-03-13 11:32:42.000000000 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2010 Freescale Semiconductor, Inc. All Rights Reserved.
diff --git a/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-vpu_driver.patch b/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-vpu_driver.patch
new file mode 100644
index 0000000..e7855fe
--- /dev/null
+++ b/patches/linux/2.6.38/442-freescale-0034-ENGR00126692-3-add_hw-vpu_driver.patch
@@ -0,0 +1,1117 @@
+From 3eb9039c5392abaabd96d08c0006ea4066346a60 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <Din...@fr...>
+Date: Tue, 17 Aug 2010 16:46:40 -0500
+Subject: [PATCH] ENGR00126692-3: Upgrade kernel to 2.6.35
+
+This patch contains changes to /drivers files
+Contains all checkpatch and copyright fixes.
+
+Acked-by: Rob Herring <r.h...@fr...>
+Signed-off-by: Dinh Nguyen <Din...@fr...>
+---
+ Changes by Armadeus systems:
+ - extracted from original patch
+
+ drivers/mxc/Kconfig | 39 +
+ drivers/mxc/Makefile | 17 +
+ drivers/mxc/vpu/Kconfig | 30 +
+ drivers/mxc/vpu/Makefile | 10 +
+ drivers/mxc/vpu/mxc_vl2cc.c | 124 +
+ drivers/mxc/vpu/mxc_vpu.c | 862 ++
+
+ - plus:
+ arch/arm/mach-mx5/system.c
+
+Index: linux-2.6.38.8/drivers/mxc/vpu/Kconfig
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.38.8/drivers/mxc/vpu/Kconfig 2012-03-15 15:50:48.000000000 +0100
+@@ -0,0 +1,22 @@
++#
++# Codec configuration
++#
++
++menu "MXC VPU(Video Processing Unit) support"
++
++config MXC_VPU
++ tristate "Support for MXC VPU(Video Processing Unit)"
++ depends on (ARCH_MX3 || ARCH_MX27 || ARCH_MX37 || ARCH_MX5)
++ default y
++ ---help---
++ The VPU codec device provides codec function for H.264/MPEG4/H.263,
++ as well as MPEG2/VC-1/DivX on some platforms.
++
++config MXC_VPU_DEBUG
++ bool "MXC VPU debugging"
++ depends on MXC_VPU != n
++ help
++ This is an option for the developers; most people should
++ say N here. This enables MXC VPU driver debugging.
++
++endmenu
+Index: linux-2.6.38.8/drivers/mxc/vpu/Makefile
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.38.8/drivers/mxc/vpu/Makefile 2012-03-14 22:37:24.000000000 +0100
+@@ -0,0 +1,9 @@
++#
++# Makefile for the VPU drivers.
++#
++
++obj-$(CONFIG_MXC_VPU) += mxc_vpu.o
++
++ifeq ($(CONFIG_MXC_VPU_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+Index: linux-2.6.38.8/drivers/mxc/vpu/mxc_vpu.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.38.8/drivers/mxc/vpu/mxc_vpu.c 2012-03-15 16:03:13.000000000 +0100
+@@ -0,0 +1,868 @@
++/*
++ * Copyright 2006-2011 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*!
++ * @file mxc_vpu.c
++ *
++ * @brief VPU system initialization and file operation implementation
++ *
++ * @ingroup VPU
++ */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/stat.h>
++#include <linux/platform_device.h>
++#include <linux/kdev_t.h>
++#include <linux/dma-mapping.h>
++#include <linux/wait.h>
++#include <linux/list.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/fsl_devices.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++#include <linux/sched.h>
++#include <linux/vmalloc.h>
++#include <asm/sizes.h>
++#include <mach/clock.h>
++#include <mach/hardware.h>
++#include <mach/iram.h>
++
++#include <mach/mxc_vpu.h>
++
++struct vpu_priv {
++ struct fasync_struct *async_queue;
++ struct work_struct work;
++ struct workqueue_struct *workqueue;
++};
++
++/* To track the allocated memory buffer */
++typedef struct memalloc_record {
++ struct list_head list;
++ struct vpu_mem_desc mem;
++} memalloc_record;
++
++struct iram_setting {
++ u32 start;
++ u32 end;
++};
++
++static DEFINE_SPINLOCK(vpu_lock);
++static LIST_HEAD(head);
++
++static int vpu_major;
++static int vpu_clk_usercount;
++static struct class *vpu_class;
++static struct vpu_priv vpu_data;
++static u8 open_count;
++static struct clk *vpu_clk;
++static struct vpu_mem_desc bitwork_mem = { 0 };
++static struct vpu_mem_desc pic_para_mem = { 0 };
++static struct vpu_mem_desc user_data_mem = { 0 };
++static struct vpu_mem_desc share_mem = { 0 };
++static struct vpu_mem_desc vshare_mem = { 0 };
++
++static void __iomem *vpu_base;
++static int vpu_irq;
++static u32 phy_vpu_base_addr;
++static struct mxc_vpu_platform_data *vpu_plat;
++
++/* IRAM setting */
++static struct iram_setting iram;
++
++/* implement the blocking ioctl */
++static int codec_done;
++static wait_queue_head_t vpu_queue;
++
++static u32 workctrl_regsave[6];
++static u32 rd_ptr_regsave[4];
++static u32 wr_ptr_regsave[4];
++static u32 dis_flag_regsave[4];
++
++#define READ_REG(x) __raw_readl(vpu_base + x)
++#define WRITE_REG(val, x) __raw_writel(val, vpu_base + x)
++#define SAVE_WORK_REGS do { \
++ int i; \
++ for (i = 0; i < ARRAY_SIZE(workctrl_regsave)/2; i++) \
++ workctrl_regsave[i] = READ_REG(BIT_WORK_CTRL_BUF_REG(i));\
++} while (0)
++#define RESTORE_WORK_REGS do { \
++ int i; \
++ for (i = 0; i < ARRAY_SIZE(workctrl_regsave)/2; i++) \
++ WRITE_REG(workctrl_regsave[i], BIT_WORK_CTRL_BUF_REG(i));\
++} while (0)
++#define SAVE_CTRL_REGS do { \
++ int i; \
++ for (i = ARRAY_SIZE(workctrl_regsave)/2; \
++ i < ARRAY_SIZE(workctrl_regsave); i++) \
++ workctrl_regsave[i] = READ_REG(BIT_WORK_CTRL_BUF_REG(i));\
++} while (0)
++#define RESTORE_CTRL_REGS do { \
++ int i; \
++ for (i = ARRAY_SIZE(workctrl_regsave)/2; \
++ i < ARRAY_SIZE(workctrl_regsave); i++) \
++ WRITE_REG(workctrl_regsave[i], BIT_WORK_CTRL_BUF_REG(i));\
++} while (0)
++#define SAVE_RDWR_PTR_REGS do { \
++ int i; \
++ for (i = 0; i < ARRAY_SIZE(rd_ptr_regsave); i++) \
++ rd_ptr_regsave[i] = READ_REG(BIT_RD_PTR_REG(i)); \
++ for (i = 0; i < ARRAY_SIZE(wr_ptr_regsave); i++) \
++ wr_ptr_regsave[i] = READ_REG(BIT_WR_PTR_REG(i)); \
++} while (0)
++#define RESTORE_RDWR_PTR_REGS do { \
++ int i; \
++ for (i = 0; i < ARRAY_SIZE(rd_ptr_regsave); i++) \
++ WRITE_REG(rd_ptr_regsave[i], BIT_RD_PTR_REG(i)); \
++ for (i = 0; i < ARRAY_SIZE(wr_ptr_regsave); i++) \
++ WRITE_REG(wr_ptr_regsave[i], BIT_WR_PTR_REG(i)); \
++} while (0)
++#define SAVE_DIS_FLAG_REGS do { \
++ int i; \
++ for (i = 0; i < ARRAY_SIZE(dis_flag_regsave); i++) \
++ dis_flag_regsave[i] = READ_REG(BIT_FRM_DIS_FLG_REG(i)); \
++} while (0)
++#define RESTORE_DIS_FLAG_REGS do { \
++ int i; \
++ for (i = 0; i < ARRAY_SIZE(dis_flag_regsave); i++) \
++ WRITE_REG(dis_flag_regsave[i], BIT_FRM_DIS_FLG_REG(i)); \
++} while (0)
++
++/*!
++ * Private function to alloc dma buffer
++ * @return status 0 success.
++ */
++static int vpu_alloc_dma_buffer(struct vpu_mem_desc *mem)
++{
++ mem->cpu_addr = (unsigned long)
++ dma_alloc_coherent(NULL, PAGE_ALIGN(mem->size),
++ (dma_addr_t *) (&mem->phy_addr),
++ GFP_DMA | GFP_KERNEL);
++ pr_debug("[ALLOC] mem alloc cpu_addr = 0x%x\n", mem->cpu_addr);
++ if ((void *)(mem->cpu_addr) == NULL) {
++ printk(KERN_ERR "Physical memory allocation error!\n");
++ return -1;
++ }
++ return 0;
++}
++
++/*!
++ * Private function to free dma buffer
++ */
++static void vpu_free_dma_buffer(struct vpu_mem_desc *mem)
++{
++ if (mem->cpu_addr != 0) {
++ dma_free_coherent(0, PAGE_ALIGN(mem->size),
++ (void *)mem->cpu_addr, mem->phy_addr);
++ }
++}
++
++/*!
++ * Private function to free buffers
++ * @return status 0 success.
++ */
++static int vpu_free_buffers(void)
++{
++ struct memalloc_record *rec, *n;
++ struct vpu_mem_desc mem;
++
++ list_for_each_entry_safe(rec, n, &head, list) {
++ mem = rec->mem;
++ if (mem.cpu_addr != 0) {
++ vpu_free_dma_buffer(&mem);
++ pr_debug("[FREE] freed paddr=0x%08X\n", mem.phy_addr);
++ /* delete from list */
++ list_del(&rec->list);
++ kfree(rec);
++ }
++ }
++
++ return 0;
++}
++
++static inline void vpu_worker_callback(struct work_struct *w)
++{
++ struct vpu_priv *dev = container_of(w, struct vpu_priv,
++ work);
++
++ if (dev->async_queue)
++ kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
++
++ codec_done = 1;
++ wake_up_interruptible(&vpu_queue);
++
++ /*
++ * Clock is gated on when dec/enc started, gate it off when
++ * interrupt is received.
++ */
++ clk_disable(vpu_clk);
++}
++
++/*!
++ * @brief vpu interrupt handler
++ */
++static irqreturn_t vpu_irq_handler(int irq, void *dev_id)
++{
++ struct vpu_priv *dev = dev_id;
++
++ READ_REG(BIT_INT_STATUS);
++ WRITE_REG(0x1, BIT_INT_CLEAR);
++
++ queue_work(dev->workqueue, &dev->work);
++
++ return IRQ_HANDLED;
++}
++
++/*!
++ * @brief open function for vpu file operation
++ *
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_open(struct inode *inode, struct file *filp)
++{
++ spin_lock(&vpu_lock);
++ open_count++;
++ filp->private_data = (void *)(&vpu_data);
++ spin_unlock(&vpu_lock);
++ return 0;
++}
++
++/*!
++ * @brief IO ctrl function for vpu file operation
++ * @param cmd IO ctrl command
++ * @return 0 on success or negative error code on error
++ */
++static long vpu_ioctl(struct file *filp, u_int cmd, u_long arg)
++{
++ int ret = 0;
++
++ switch (cmd) {
++ case VPU_IOC_PHYMEM_ALLOC:
++ {
++ struct memalloc_record *rec;
++
++ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
++ if (!rec)
++ return -ENOMEM;
++
++ ret = copy_from_user(&(rec->mem),
++ (struct vpu_mem_desc *)arg,
++ sizeof(struct vpu_mem_desc));
++ if (ret) {
++ kfree(rec);
++ return -EFAULT;
++ }
++
++ pr_debug("[ALLOC] mem alloc size = 0x%x\n",
++ rec->mem.size);
++
++ ret = vpu_alloc_dma_buffer(&(rec->mem));
++ if (ret == -1) {
++ kfree(rec);
++ printk(KERN_ERR
++ "Physical memory allocation error!\n");
++ break;
++ }
++ ret = copy_to_user((void __user *)arg, &(rec->mem),
++ sizeof(struct vpu_mem_desc));
++ if (ret) {
++ kfree(rec);
++ ret = -EFAULT;
++ break;
++ }
++
++ spin_lock(&vpu_lock);
++ list_add(&rec->list, &head);
++ spin_unlock(&vpu_lock);
++
++ break;
++ }
++ case VPU_IOC_PHYMEM_FREE:
++ {
++ struct memalloc_record *rec, *n;
++ struct vpu_mem_desc vpu_mem;
++
++ ret = copy_from_user(&vpu_mem,
++ (struct vpu_mem_desc *)arg,
++ sizeof(struct vpu_mem_desc));
++ if (ret)
++ return -EACCES;
++
++ pr_debug("[FREE] mem freed cpu_addr = 0x%x\n",
++ vpu_mem.cpu_addr);
++ if ((void *)vpu_mem.cpu_addr != NULL) {
++ vpu_free_dma_buffer(&vpu_mem);
++ }
++
++ spin_lock(&vpu_lock);
++ list_for_each_entry_safe(rec, n, &head, list) {
++ if (rec->mem.cpu_addr == vpu_mem.cpu_addr) {
++ /* delete from list */
++ list_del(&rec->list);
++ kfree(rec);
++ break;
++ }
++ }
++ spin_unlock(&vpu_lock);
++
++ break;
++ }
++ case VPU_IOC_WAIT4INT:
++ {
++ u_long timeout = (u_long) arg;
++ if (!wait_event_interruptible_timeout
++ (vpu_queue, codec_done != 0,
++ msecs_to_jiffies(timeout))) {
++ printk(KERN_WARNING "VPU blocking: timeout.\n");
++ ret = -ETIME;
++ } else if (signal_pending(current)) {
++ printk(KERN_WARNING
++ "VPU interrupt received.\n");
++ ret = -ERESTARTSYS;
++ } else
++ codec_done = 0;
++ break;
++ }
++ case VPU_IOC_IRAM_SETTING:
++ {
++ ret = copy_to_user((void __user *)arg, &iram,
++ sizeof(struct iram_setting));
++ if (ret)
++ ret = -EFAULT;
++
++ break;
++ }
++ case VPU_IOC_CLKGATE_SETTING:
++ {
++ u32 clkgate_en;
++
++ if (get_user(clkgate_en, (u32 __user *) arg))
++ return -EFAULT;
++
++ if (clkgate_en) {
++ clk_enable(vpu_clk);
++ } else {
++ clk_disable(vpu_clk);
++ }
++
++ break;
++ }
++ case VPU_IOC_GET_SHARE_MEM:
++ {
++ spin_lock(&vpu_lock);
++ if (share_mem.cpu_addr != 0) {
++ ret = copy_to_user((void __user *)arg,
++ &share_mem,
++ sizeof(struct vpu_mem_desc));
++ spin_unlock(&vpu_lock);
++ break;
++ } else {
++ if (copy_from_user(&share_mem,
++ (struct vpu_mem_desc *)arg,
++ sizeof(struct vpu_mem_desc))) {
++ spin_unlock(&vpu_lock);
++ return -EFAULT;
++ }
++ if (vpu_alloc_dma_buffer(&share_mem) == -1)
++ ret = -EFAULT;
++ else {
++ if (copy_to_user((void __user *)arg,
++ &share_mem,
++ sizeof(struct
++ vpu_mem_desc)))
++ ret = -EFAULT;
++ }
++ }
++ spin_unlock(&vpu_lock);
++ break;
++ }
++ case VPU_IOC_REQ_VSHARE_MEM:
++ {
++ spin_lock(&vpu_lock);
++ if (vshare_mem.cpu_addr != 0) {
++ ret = copy_to_user((void __user *)arg,
++ &vshare_mem,
++ sizeof(struct vpu_mem_desc));
++ spin_unlock(&vpu_lock);
++ break;
++ } else {
++ if (copy_from_user(&vshare_mem,
++ (struct vpu_mem_desc *)arg,
++ sizeof(struct
++ vpu_mem_desc))) {
++ spin_unlock(&vpu_lock);
++ return -EFAULT;
++ }
++ /* vmalloc shared memory if not allocated */
++ if (!vshare_mem.cpu_addr)
++ vshare_mem.cpu_addr =
++ (unsigned long)
++ vmalloc_user(vshare_mem.size);
++ if (copy_to_user
++ ((void __user *)arg, &vshare_mem,
++ sizeof(struct vpu_mem_desc)))
++ ret = -EFAULT;
++ }
++ spin_unlock(&vpu_lock);
++ break;
++ }
++ case VPU_IOC_GET_WORK_ADDR:
++ {
++ if (bitwork_mem.cpu_addr != 0) {
++ ret =
++ copy_to_user((void __user *)arg,
++ &bitwork_mem,
++ sizeof(struct vpu_mem_desc));
++ break;
++ } else {
++ if (copy_from_user(&bitwork_mem,
++ (struct vpu_mem_desc *)arg,
++ sizeof(struct vpu_mem_desc)))
++ return -EFAULT;
++
++ if (vpu_alloc_dma_buffer(&bitwork_mem) == -1)
++ ret = -EFAULT;
++ else if (copy_to_user((void __user *)arg,
++ &bitwork_mem,
++ sizeof(struct
++ vpu_mem_desc)))
++ ret = -EFAULT;
++ }
++ break;
++ }
++ /*
++ * The following two ioctl is used when user allocates working buffer
++ * and register it to vpu driver.
++ */
++ case VPU_IOC_QUERY_BITWORK_MEM:
++ {
++ if (copy_to_user((void __user *)arg,
++ &bitwork_mem,
++ sizeof(struct vpu_mem_desc)))
++ ret = -EFAULT;
++ break;
++ }
++ case VPU_IOC_SET_BITWORK_MEM:
++ {
++ if (copy_from_user(&bitwork_mem,
++ (struct vpu_mem_desc *)arg,
++ sizeof(struct vpu_mem_desc)))
++ ret = -EFAULT;
++ break;
++ }
++ case VPU_IOC_SYS_SW_RESET:
++ {
++ if (vpu_plat->reset)
++ vpu_plat->reset();
++
++ break;
++ }
++ case VPU_IOC_REG_DUMP:
++ break;
++ case VPU_IOC_PHYMEM_DUMP:
++ break;
++ default:
++ {
++ printk(KERN_ERR "No such IOCTL, cmd is %d\n", cmd);
++ break;
++ }
++ }
++ return ret;
++}
++
++/*!
++ * @brief Release function for vpu file operation
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_release(struct inode *inode, struct file *filp)
++{
++ spin_lock(&vpu_lock);
++ if (open_count > 0 && !(--open_count)) {
++ vpu_free_buffers();
++
++ /* Free shared memory when vpu device is idle */
++ vpu_free_dma_buffer(&share_mem);
++ share_mem.cpu_addr = 0;
++ vfree((void *)vshare_mem.cpu_addr);
++ vshare_mem.cpu_addr = 0;
++ }
++ spin_unlock(&vpu_lock);
++
++ return 0;
++}
++
++/*!
++ * @brief fasync function for vpu file operation
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_fasync(int fd, struct file *filp, int mode)
++{
++ struct vpu_priv *dev = (struct vpu_priv *)filp->private_data;
++ return fasync_helper(fd, filp, mode, &dev->async_queue);
++}
++
++/*!
++ * @brief memory map function of harware registers for vpu file operation
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm)
++{
++ unsigned long pfn;
++
++ vm->vm_flags |= VM_IO | VM_RESERVED;
++ vm->vm_page_prot = pgprot_noncached(vm->vm_page_prot);
++ pfn = phy_vpu_base_addr >> PAGE_SHIFT;
++ pr_debug("size=0x%x, page no.=0x%x\n",
++ (int)(vm->vm_end - vm->vm_start), (int)pfn);
++ return remap_pfn_range(vm, vm->vm_start, pfn, vm->vm_end - vm->vm_start,
++ vm->vm_page_prot) ? -EAGAIN : 0;
++}
++
++/*!
++ * @brief memory map function of memory for vpu file operation
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_map_dma_mem(struct file *fp, struct vm_area_struct *vm)
++{
++ int request_size;
++ request_size = vm->vm_end - vm->vm_start;
++
++ pr_debug(" start=0x%x, pgoff=0x%x, size=0x%x\n",
++ (unsigned int)(vm->vm_start), (unsigned int)(vm->vm_pgoff),
++ request_size);
++
++ vm->vm_flags |= VM_IO | VM_RESERVED;
++ vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot);
++
++ return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff,
++ request_size, vm->vm_page_prot) ? -EAGAIN : 0;
++
++}
++
++/* !
++ * @brief memory map function of vmalloced share memory
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_map_vshare_mem(struct file *fp, struct vm_area_struct *vm)
++{
++ int ret = -EINVAL;
++
++ spin_lock(&vpu_lock);
++ ret = remap_vmalloc_range(vm, (void *)(vm->vm_pgoff << PAGE_SHIFT), 0);
++ vm->vm_flags |= VM_IO;
++ spin_unlock(&vpu_lock);
++
++ return ret;
++}
++/*!
++ * @brief memory map interface for vpu file operation
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_mmap(struct file *fp, struct vm_area_struct *vm)
++{
++ unsigned long offset;
++
++ offset = vshare_mem.cpu_addr >> PAGE_SHIFT;
++
++ if (vm->vm_pgoff && (vm->vm_pgoff == offset))
++ return vpu_map_vshare_mem(fp, vm);
++ else if (vm->vm_pgoff)
++ return vpu_map_dma_mem(fp, vm);
++ else
++ return vpu_map_hwregs(fp, vm);
++}
++
++struct file_operations vpu_fops = {
++ .owner = THIS_MODULE,
++ .open = vpu_open,
++ .unlocked_ioctl = vpu_ioctl,
++ .release = vpu_release,
++ .fasync = vpu_fasync,
++ .mmap = vpu_mmap,
++};
++
++/*!
++ * This function is called by the driver framework to initialize the vpu device.
++ * @param dev The device structure for the vpu passed in by the framework.
++ * @return 0 on success or negative error code on error
++ */
++static int vpu_dev_probe(struct platform_device *pdev)
++{
++ int err = 0;
++ struct device *temp_class;
++ struct resource *res;
++ unsigned long addr = 0;
++
++ vpu_plat = pdev->dev.platform_data;
++
++ if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
++ iram_alloc(vpu_plat->iram_size, &addr);
++ if (addr == 0)
++ iram.start = iram.end = 0;
++ else {
++ iram.start = addr;
++ iram.end = addr + vpu_plat->iram_size - 1;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ printk(KERN_ERR "vpu: unable to get vpu base addr\n");
++ return -ENODEV;
++ }
++ phy_vpu_base_addr = res->start;
++ vpu_base = ioremap(res->start, res->end - res->start);
++
++ vpu_major = register_chrdev(vpu_major, "mxc_vpu", &vpu_fops);
++ if (vpu_major < 0) {
++ printk(KERN_ERR "vpu: unable to get a major for VPU\n");
++ err = -EBUSY;
++ goto error;
++ }
++
++ vpu_class = class_create(THIS_MODULE, "mxc_vpu");
++ if (IS_ERR(vpu_class)) {
++ err = PTR_ERR(vpu_class);
++ goto err_out_chrdev;
++ }
++
++ temp_class = device_create(vpu_class, NULL, MKDEV(vpu_major, 0),
++ NULL, "mxc_vpu");
++ if (IS_ERR(temp_class)) {
++ err = PTR_ERR(temp_class);
++ goto err_out_class;
++ }
++
++ vpu_clk = clk_get(&pdev->dev, "vpu_clk");
++ if (IS_ERR(vpu_clk)) {
++ err = -ENOENT;
++ goto err_out_class;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!res) {
++ printk(KERN_ERR "vpu: unable to get vpu interrupt\n");
++ err = -ENXIO;
++ goto err_out_class;
++ }
++ vpu_irq = res->start;
++
++ err = request_irq(vpu_irq, vpu_irq_handler, 0, "VPU_CODEC_IRQ",
++ (void *)(&vpu_data));
++ if (err)
++ goto err_out_class;
++
++ vpu_data.workqueue = create_workqueue("vpu_wq");
++ INIT_WORK(&vpu_data.work, vpu_worker_callback);
++ printk(KERN_INFO "VPU initialized\n");
++ goto out;
++
++ err_out_class:
++ device_destroy(vpu_class, MKDEV(vpu_major, 0));
++ class_destroy(vpu_class);
++ err_out_chrdev:
++ unregister_chrdev(vpu_major, "mxc_vpu");
++ error:
++ iounmap(vpu_base);
++ out:
++ return err;
++}
++
++static int vpu_dev_remove(struct platform_device *pdev)
++{
++ free_irq(vpu_irq, &vpu_data);
++ cancel_work_sync(&vpu_data.work);
++ flush_workqueue(vpu_data.workqueue);
++ destroy_workqueue(vpu_data.workqueue);
++
++ iounmap(vpu_base);
++ if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
++ iram_free(iram.start, vpu_plat->iram_size);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ int i;
++ unsigned long timeout;
++
++ /* Wait for vpu go to idle state, suspect vpu cannot be changed
++ to idle state after about 1 sec */
++ if (open_count > 0) {
++ timeout = jiffies + HZ;
++ clk_enable(vpu_clk);
++ while (READ_REG(BIT_BUSY_FLAG)) {
++ msleep(1);
++ if (time_after(jiffies, timeout))
++ goto out;
++ }
++ clk_disable(vpu_clk);
++ }
++
++ /* Make sure clock is disabled before suspend */
++ vpu_clk_usercount = clk_get_usecount(vpu_clk);
++ for (i = 0; i < vpu_clk_usercount; i++)
++ clk_disable(vpu_clk);
++
++ if (cpu_is_mx51()) {
++ clk_enable(vpu_clk);
++ if (bitwork_mem.cpu_addr != 0) {
++ SAVE_WORK_REGS;
++ SAVE_CTRL_REGS;
++ SAVE_RDWR_PTR_REGS;
++ SAVE_DIS_FLAG_REGS;
++
++ WRITE_REG(0x1, BIT_BUSY_FLAG);
++ WRITE_REG(VPU_SLEEP_REG_VALUE, BIT_RUN_COMMAND);
++ while (READ_REG(BIT_BUSY_FLAG))
++ ;
++ }
++ clk_disable(vpu_clk);
++
++ mxc_pg_enable(pdev);
++ }
++
++ return 0;
++
++out:
++ clk_disable(vpu_clk);
++ return -EAGAIN;
++
++}
++
++static int vpu_resume(struct platform_device *pdev)
++{
++ int i;
++
++ if (cpu_is_mx53())
++ goto recover_clk;
++
++ mxc_pg_disable(pdev);
++
++ clk_enable(vpu_clk);
++ if (bitwork_mem.cpu_addr != 0) {
++ u32 *p = (u32 *) bitwork_mem.cpu_addr;
++ u32 data;
++ u16 data_hi;
++ u16 data_lo;
++
++ RESTORE_WORK_REGS;
++
++ WRITE_REG(0x0, BIT_RESET_CTRL);
++ WRITE_REG(0x0, BIT_CODE_RUN);
++
++ /*
++ * Re-load boot code, from the codebuffer in external RAM.
++ * Thankfully, we only need 4096 bytes, same for all platforms.
++ */
++ for (i = 0; i < 2048; i += 4) {
++ data = p[(i / 2) + 1];
++ data_hi = (data >> 16) & 0xFFFF;
++ data_lo = data & 0xFFFF;
++ WRITE_REG((i << 16) | data_hi, BIT_CODE_DOWN);
++ WRITE_REG(((i + 1) << 16) | data_lo,
++ BIT_CODE_DOWN);
++
++ data = p[i / 2];
++ data_hi = (data >> 16) & 0xFFFF;
++ data_lo = data & 0xFFFF;
++ WRITE_REG(((i + 2) << 16) | data_hi,
++ BIT_CODE_DOWN);
++ WRITE_REG(((i + 3) << 16) | data_lo,
++ BIT_CODE_DOWN);
++ }
++
++ RESTORE_CTRL_REGS;
++
++ WRITE_REG(BITVAL_PIC_RUN, BIT_INT_ENABLE);
++
++ WRITE_REG(0x1, BIT_BUSY_FLAG);
++ WRITE_REG(0x1, BIT_CODE_RUN);
++ while (READ_REG(BIT_BUSY_FLAG))
++ ;
++
++ RESTORE_RDWR_PTR_REGS;
++ RESTORE_DIS_FLAG_REGS;
++
++ WRITE_REG(0x1, BIT_BUSY_FLAG);
++ WRITE_REG(VPU_WAKE_REG_VALUE, BIT_RUN_COMMAND);
++ while (READ_REG(BIT_BUSY_FLAG))
++ ;
++ }
++ clk_disable(vpu_clk);
++
++recover_clk:
++ /* Recover vpu clock */
++ for (i = 0; i < vpu_clk_usercount; i++)
++ clk_enable(vpu_clk);
++
++ return 0;
++}
++#else
++#define vpu_suspend NULL
++#define vpu_resume NULL
++#endif /* !CONFIG_PM */
++
++/*! Driver definition
++ *
++ */
++static struct platform_driver mxcvpu_driver = {
++ .driver = {
++ .name = "mxc_vpu",
++ },
++ .probe = vpu_dev_probe,
++ .remove = vpu_dev_remove,
++ .suspend = vpu_suspend,
++ .resume = vpu_resume,
++};
++
++static int __init vpu_init(void)
++{
++ int ret = platform_driver_register(&mxcvpu_driver);
++
++ init_waitqueue_head(&vpu_queue);
++
++ return ret;
++}
++
++static void __exit vpu_exit(void)
++{
++ if (vpu_major > 0) {
++ device_destroy(vpu_class,...
[truncated message content] |