summaryrefslogtreecommitdiff
path: root/drivers/uio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/uio')
-rw-r--r--drivers/uio/fsl_dma_uio.c61
1 files changed, 38 insertions, 23 deletions
diff --git a/drivers/uio/fsl_dma_uio.c b/drivers/uio/fsl_dma_uio.c
index fca99bf..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,7 +83,33 @@ static irqreturn_t dma_uio_irq_handler(int irq, struct uio_info *dev_info)
return IRQ_HANDLED;
}
-static int __init dma_chan_uio_setup(struct dma_chan *dma_ch)
+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;
struct dma_uio_info *info;
@@ -112,8 +139,8 @@ static int __init 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) {
dev_err(dma_ch->dev, "dma_uio: UIO registration failed\n");
@@ -124,13 +151,13 @@ static int __init dma_chan_uio_setup(struct dma_chan *dma_ch)
}
static int fsl_dma_chan_probe(struct fsldma_device *fdev,
- struct device_node *node)
+ struct device_node *node,
+ u32 chanid)
{
struct resource regs;
struct dma_chan *dma_ch;
struct device_node *dma_node;
int err;
- u32 *cell;
struct platform_device *dev = fdev->dev;
dma_node = node;
@@ -142,14 +169,9 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
return -ENOMEM;
}
- cell = (u32 *)of_get_property(dma_node, "cell-index", NULL);
- if (!cell) {
- dev_err(&dev->dev, "Can't get property 'cell-index'\n");
- return -EFAULT;
- }
dma_ch->dma_id = fdev->dma_id;
- dma_ch->ch_id = *cell;
+ dma_ch->ch_id = chanid;
dma_ch->dev = &dev->dev;
err = of_address_to_resource(dma_node, 0, &regs);
@@ -201,13 +223,8 @@ static int fsl_dma_uio_probe(struct platform_device *dev)
{
struct device_node *child;
struct fsldma_device *fdev;
- u32 *cell;
-
- cell = (u32 *)of_get_property(dev->dev.of_node, "cell-index", NULL);
- if (!cell) {
- dev_err(&dev->dev, "Can't get property 'cell-index'\n");
- return -ENODEV;
- }
+ static u32 dmaid;
+ u32 chanid = 0;
fdev = devm_kzalloc(&dev->dev, sizeof(struct fsldma_device),
GFP_KERNEL);
@@ -216,15 +233,14 @@ static int fsl_dma_uio_probe(struct platform_device *dev)
return -ENOMEM;
}
- fdev->dma_id = *cell;
+ fdev->dma_id = dmaid++;
fdev->dev = dev;
INIT_LIST_HEAD(&fdev->ch_list);
dev_set_drvdata(&dev->dev, fdev);
for_each_child_of_node(dev->dev.of_node, child)
if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
- fsl_dma_chan_probe(fdev, child);
-
+ fsl_dma_chan_probe(fdev, child, chanid++);
return 0;
}
@@ -244,9 +260,8 @@ static int fsl_dma_uio_remove(struct platform_device *dev)
static const struct of_device_id fsl_of_dma_match[] = {
- {
- .compatible = "fsl,eloplus-dma",
- },
+ { .compatible = "fsl,elo3-dma", },
+ { .compatible = "fsl,eloplus-dma", },
{}
};