summaryrefslogtreecommitdiff
path: root/drivers/uio
diff options
context:
space:
mode:
authorLiu Gang <gang.liu@freescale.com>2014-04-17 10:19:16 (GMT)
committerJose Rivera <German.Rivera@freescale.com>2014-04-18 04:01:01 (GMT)
commit153f2d27a28a543f722fdef20553dd65e8decac1 (patch)
treece4da2534869a2295a11d56c9fb64b61af7b8d6d /drivers/uio
parent0dfc5833cea4f87c5a640aff8a8ecb079af4dde2 (diff)
downloadlinux-fsl-qoriq-153f2d27a28a543f722fdef20553dd65e8decac1.tar.xz
UIO/DMA: Add dma uio private mmap function
UIO mmap cannot map an unaligned page address, and the PowerPC DMA register space has an unaligned page base address. So the mmap for DMA register address should be supported via a private function. Signed-off-by: Liu Gang <gang.liu@freescale.com> Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com> Change-Id: Ic5672dd4f86031fab34830d47e231fb1c46b2070 Reviewed-on: http://git.am.freescale.net:8181/11081 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Mingkai Hu <Mingkai.Hu@freescale.com> Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/uio')
-rw-r--r--drivers/uio/fsl_dma_uio.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/uio/fsl_dma_uio.c b/drivers/uio/fsl_dma_uio.c
index f16a009..899523f 100644
--- a/drivers/uio/fsl_dma_uio.c
+++ b/drivers/uio/fsl_dma_uio.c
@@ -25,6 +25,7 @@
#include <linux/uio_driver.h>
#include <linux/list.h>
#include <linux/io.h>
+#include <linux/mm.h>
static const char dma_uio_version[] = "DMA UIO driver v1.0";
@@ -82,6 +83,32 @@ static irqreturn_t dma_uio_irq_handler(int irq, struct uio_info *dev_info)
return IRQ_HANDLED;
}
+static int dma_uio_mmap(struct uio_info *info, struct vm_area_struct *vma)
+{
+ int mi;
+ struct uio_mem *mem;
+
+ if (vma->vm_pgoff < MAX_UIO_MAPS) {
+ if (info->mem[vma->vm_pgoff].size == 0)
+ return -EINVAL;
+ mi = (int)vma->vm_pgoff;
+ } else
+ return -EINVAL;
+
+ mem = info->mem + mi;
+
+ if (vma->vm_end - vma->vm_start > mem->size)
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ return remap_pfn_range(vma,
+ vma->vm_start,
+ mem->addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
static int dma_chan_uio_setup(struct dma_chan *dma_ch)
{
int ret;
@@ -112,6 +139,7 @@ static int dma_chan_uio_setup(struct dma_chan *dma_ch)
info->uio.handler = dma_uio_irq_handler;
info->uio.open = dma_uio_open;
info->uio.release = dma_uio_release;
+ info->uio.mmap = dma_uio_mmap;
info->uio.priv = dma_ch;
ret = uio_register_device(dma_ch->dev, &info->uio);
if (ret) {