Commit 6147b032 authored by Paul Cercueil's avatar Paul Cercueil Committed by Vinod Koul

dmaengine: dma-jz4780: Avoid hardcoding number of channels

As part of the work to support various other Ingenic JZ47xx SoC versions,
which don't feature the same number of DMA channels per core, we now
deduce the number of DMA channels available from the devicetree
compatible string.
Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Tested-by: default avatarMathieu Malaterre <malat@debian.org>
Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 54f919a0
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h> #include <linux/of_dma.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -23,8 +24,6 @@ ...@@ -23,8 +24,6 @@
#include "dmaengine.h" #include "dmaengine.h"
#include "virt-dma.h" #include "virt-dma.h"
#define JZ_DMA_NR_CHANNELS 32
/* Global registers. */ /* Global registers. */
#define JZ_DMA_REG_DMAC 0x1000 #define JZ_DMA_REG_DMAC 0x1000
#define JZ_DMA_REG_DIRQP 0x1004 #define JZ_DMA_REG_DIRQP 0x1004
...@@ -135,14 +134,19 @@ struct jz4780_dma_chan { ...@@ -135,14 +134,19 @@ struct jz4780_dma_chan {
unsigned int curr_hwdesc; unsigned int curr_hwdesc;
}; };
struct jz4780_dma_soc_data {
unsigned int nb_channels;
};
struct jz4780_dma_dev { struct jz4780_dma_dev {
struct dma_device dma_device; struct dma_device dma_device;
void __iomem *base; void __iomem *base;
struct clk *clk; struct clk *clk;
unsigned int irq; unsigned int irq;
const struct jz4780_dma_soc_data *soc_data;
uint32_t chan_reserved; uint32_t chan_reserved;
struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS]; struct jz4780_dma_chan chan[];
}; };
struct jz4780_dma_filter_data { struct jz4780_dma_filter_data {
...@@ -648,7 +652,7 @@ static irqreturn_t jz4780_dma_irq_handler(int irq, void *data) ...@@ -648,7 +652,7 @@ static irqreturn_t jz4780_dma_irq_handler(int irq, void *data)
pending = jz4780_dma_readl(jzdma, JZ_DMA_REG_DIRQP); pending = jz4780_dma_readl(jzdma, JZ_DMA_REG_DIRQP);
for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) { for (i = 0; i < jzdma->soc_data->nb_channels; i++) {
if (!(pending & (1<<i))) if (!(pending & (1<<i)))
continue; continue;
...@@ -728,7 +732,7 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec, ...@@ -728,7 +732,7 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
data.channel = dma_spec->args[1]; data.channel = dma_spec->args[1];
if (data.channel > -1) { if (data.channel > -1) {
if (data.channel >= JZ_DMA_NR_CHANNELS) { if (data.channel >= jzdma->soc_data->nb_channels) {
dev_err(jzdma->dma_device.dev, dev_err(jzdma->dma_device.dev,
"device requested non-existent channel %u\n", "device requested non-existent channel %u\n",
data.channel); data.channel);
...@@ -755,6 +759,7 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec, ...@@ -755,6 +759,7 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
static int jz4780_dma_probe(struct platform_device *pdev) static int jz4780_dma_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct jz4780_dma_soc_data *soc_data;
struct jz4780_dma_dev *jzdma; struct jz4780_dma_dev *jzdma;
struct jz4780_dma_chan *jzchan; struct jz4780_dma_chan *jzchan;
struct dma_device *dd; struct dma_device *dd;
...@@ -766,10 +771,17 @@ static int jz4780_dma_probe(struct platform_device *pdev) ...@@ -766,10 +771,17 @@ static int jz4780_dma_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL); soc_data = device_get_match_data(dev);
if (!soc_data)
return -EINVAL;
jzdma = devm_kzalloc(dev, sizeof(*jzdma)
+ sizeof(*jzdma->chan) * soc_data->nb_channels,
GFP_KERNEL);
if (!jzdma) if (!jzdma)
return -ENOMEM; return -ENOMEM;
jzdma->soc_data = soc_data;
platform_set_drvdata(pdev, jzdma); platform_set_drvdata(pdev, jzdma);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -844,7 +856,7 @@ static int jz4780_dma_probe(struct platform_device *pdev) ...@@ -844,7 +856,7 @@ static int jz4780_dma_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&dd->channels); INIT_LIST_HEAD(&dd->channels);
for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) { for (i = 0; i < soc_data->nb_channels; i++) {
jzchan = &jzdma->chan[i]; jzchan = &jzdma->chan[i];
jzchan->id = i; jzchan->id = i;
...@@ -889,15 +901,19 @@ static int jz4780_dma_remove(struct platform_device *pdev) ...@@ -889,15 +901,19 @@ static int jz4780_dma_remove(struct platform_device *pdev)
free_irq(jzdma->irq, jzdma); free_irq(jzdma->irq, jzdma);
for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) for (i = 0; i < jzdma->soc_data->nb_channels; i++)
tasklet_kill(&jzdma->chan[i].vchan.task); tasklet_kill(&jzdma->chan[i].vchan.task);
dma_async_device_unregister(&jzdma->dma_device); dma_async_device_unregister(&jzdma->dma_device);
return 0; return 0;
} }
static const struct jz4780_dma_soc_data jz4780_dma_soc_data = {
.nb_channels = 32,
};
static const struct of_device_id jz4780_dma_dt_match[] = { static const struct of_device_id jz4780_dma_dt_match[] = {
{ .compatible = "ingenic,jz4780-dma", .data = NULL }, { .compatible = "ingenic,jz4780-dma", .data = &jz4780_dma_soc_data },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match); MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment