Commit 4981c4dc authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Vinod Koul

DMA: shdma: switch DT mode to use configuration data from a match table

This facilitates DMAC DT support by eliminating the need in AUXDATA and
avoiding creating complex DT data. This also fits well with DMAC devices,
of which SoCs often have multiple identical copies and it is perfectly
valid to use a single configuration data set for all of them.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski+renesas@gmail.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 2833c47e
...@@ -22,42 +22,51 @@ Optional properties (currently unused): ...@@ -22,42 +22,51 @@ Optional properties (currently unused):
* DMA controller * DMA controller
Required properties: Required properties:
- compatible: should be "renesas,shdma" - compatible: should be of the form "renesas,shdma-<soc>", where <soc> should
be replaced with the desired SoC model, e.g.
"renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
Example: Example:
dmac: dma-mux0 { dmac: dma-multiplexer@0 {
compatible = "renesas,shdma-mux"; compatible = "renesas,shdma-mux";
#dma-cells = <1>; #dma-cells = <1>;
dma-channels = <6>; dma-channels = <20>;
dma-requests = <256>; dma-requests = <256>;
reg = <0 0>; /* Needed for AUXDATA */ #address-cells = <2>;
#address-cells = <1>; #size-cells = <2>;
#size-cells = <1>;
ranges; ranges;
dma0: shdma@fe008020 { dma0: dma-controller@e6700020 {
compatible = "renesas,shdma"; compatible = "renesas,shdma-r8a73a4";
reg = <0xfe008020 0x270>, reg = <0 0xe6700020 0 0x89e0>;
<0xfe009000 0xc>;
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 34 4 interrupts = <0 220 4
0 28 4 0 200 4
0 29 4 0 201 4
0 30 4 0 202 4
0 31 4 0 203 4
0 32 4 0 204 4
0 33 4>; 0 205 4
0 206 4
0 207 4
0 208 4
0 209 4
0 210 4
0 211 4
0 212 4
0 213 4
0 214 4
0 215 4
0 216 4
0 217 4
0 218 4
0 219 4>;
interrupt-names = "error", interrupt-names = "error",
"ch0", "ch1", "ch2", "ch3", "ch0", "ch1", "ch2", "ch3",
"ch4", "ch5"; "ch4", "ch5", "ch6", "ch7",
}; "ch8", "ch9", "ch10", "ch11",
"ch12", "ch13", "ch14", "ch15",
dma1: shdma@fe018020 { "ch16", "ch17", "ch18", "ch19";
...
};
dma2: shdma@fe028020 {
...
}; };
}; };
......
obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o
obj-$(CONFIG_SH_DMAE) += shdma.o obj-$(CONFIG_SH_DMAE) += shdma.o
shdma-y := shdmac.o
shdma-objs := $(shdma-y)
obj-$(CONFIG_SUDMAC) += sudmac.o obj-$(CONFIG_SUDMAC) += sudmac.o
...@@ -171,7 +171,8 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan) ...@@ -171,7 +171,8 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
return NULL; return NULL;
} }
static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
dma_addr_t slave_addr)
{ {
struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
const struct shdma_ops *ops = sdev->ops; const struct shdma_ops *ops = sdev->ops;
...@@ -179,7 +180,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) ...@@ -179,7 +180,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
if (schan->dev->of_node) { if (schan->dev->of_node) {
match = schan->hw_req; match = schan->hw_req;
ret = ops->set_slave(schan, match, true); ret = ops->set_slave(schan, match, slave_addr, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -194,7 +195,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) ...@@ -194,7 +195,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
if (test_and_set_bit(slave_id, shdma_slave_used)) if (test_and_set_bit(slave_id, shdma_slave_used))
return -EBUSY; return -EBUSY;
ret = ops->set_slave(schan, match, false); ret = ops->set_slave(schan, match, slave_addr, false);
if (ret < 0) { if (ret < 0) {
clear_bit(slave_id, shdma_slave_used); clear_bit(slave_id, shdma_slave_used);
return ret; return ret;
...@@ -236,7 +237,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg) ...@@ -236,7 +237,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
if (!schan->dev->of_node && match >= slave_num) if (!schan->dev->of_node && match >= slave_num)
return false; return false;
ret = ops->set_slave(schan, match, true); ret = ops->set_slave(schan, match, 0, true);
if (ret < 0) if (ret < 0)
return false; return false;
...@@ -259,7 +260,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) ...@@ -259,7 +260,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
*/ */
if (slave) { if (slave) {
/* Legacy mode: .private is set in filter */ /* Legacy mode: .private is set in filter */
ret = shdma_setup_slave(schan, slave->slave_id); ret = shdma_setup_slave(schan, slave->slave_id, 0);
if (ret < 0) if (ret < 0)
goto esetslave; goto esetslave;
} else { } else {
...@@ -680,7 +681,9 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ...@@ -680,7 +681,9 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
* channel, while using it... * channel, while using it...
*/ */
config = (struct dma_slave_config *)arg; config = (struct dma_slave_config *)arg;
ret = shdma_setup_slave(schan, config->slave_id); ret = shdma_setup_slave(schan, config->slave_id,
config->direction == DMA_DEV_TO_MEM ?
config->src_addr : config->dst_addr);
if (ret < 0) if (ret < 0)
return ret; return ret;
break; break;
......
...@@ -45,9 +45,6 @@ static int shdma_of_probe(struct platform_device *pdev) ...@@ -45,9 +45,6 @@ static int shdma_of_probe(struct platform_device *pdev)
const struct of_dev_auxdata *lookup = pdev->dev.platform_data; const struct of_dev_auxdata *lookup = pdev->dev.platform_data;
int ret; int ret;
if (!lookup)
return -EINVAL;
ret = of_dma_controller_register(pdev->dev.of_node, ret = of_dma_controller_register(pdev->dev.of_node,
shdma_of_xlate, pdev); shdma_of_xlate, pdev);
if (ret < 0) if (ret < 0)
......
...@@ -31,6 +31,7 @@ struct sh_dmae_chan { ...@@ -31,6 +31,7 @@ struct sh_dmae_chan {
void __iomem *base; void __iomem *base;
char dev_id[16]; /* unique name per DMAC of channel */ char dev_id[16]; /* unique name per DMAC of channel */
int pm_error; int pm_error;
dma_addr_t slave_addr;
}; };
struct sh_dmae_device { struct sh_dmae_device {
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
...@@ -333,7 +335,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave( ...@@ -333,7 +335,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
} else { } else {
for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
if (cfg->mid_rid == match) { if (cfg->mid_rid == match) {
sh_chan->shdma_chan.slave_id = cfg->slave_id; sh_chan->shdma_chan.slave_id = i;
return cfg; return cfg;
} }
} }
...@@ -342,7 +344,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave( ...@@ -342,7 +344,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
} }
static int sh_dmae_set_slave(struct shdma_chan *schan, static int sh_dmae_set_slave(struct shdma_chan *schan,
int slave_id, bool try) int slave_id, dma_addr_t slave_addr, bool try)
{ {
struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
shdma_chan); shdma_chan);
...@@ -350,8 +352,10 @@ static int sh_dmae_set_slave(struct shdma_chan *schan, ...@@ -350,8 +352,10 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
if (!cfg) if (!cfg)
return -ENXIO; return -ENXIO;
if (!try) if (!try) {
sh_chan->config = cfg; sh_chan->config = cfg;
sh_chan->slave_addr = slave_addr ? : cfg->addr;
}
return 0; return 0;
} }
...@@ -641,7 +645,7 @@ static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan) ...@@ -641,7 +645,7 @@ static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
* This is an exclusive slave DMA operation, may only be called after a * This is an exclusive slave DMA operation, may only be called after a
* successful slave configuration. * successful slave configuration.
*/ */
return sh_chan->config->addr; return sh_chan->slave_addr;
} }
static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i) static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
...@@ -663,9 +667,14 @@ static const struct shdma_ops sh_dmae_shdma_ops = { ...@@ -663,9 +667,14 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
.get_partial = sh_dmae_get_partial, .get_partial = sh_dmae_get_partial,
}; };
static const struct of_device_id sh_dmae_of_match[] = {
{}
};
MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
static int sh_dmae_probe(struct platform_device *pdev) static int sh_dmae_probe(struct platform_device *pdev)
{ {
const struct sh_dmae_pdata *pdata = pdev->dev.platform_data; const struct sh_dmae_pdata *pdata;
unsigned long irqflags = IRQF_DISABLED, unsigned long irqflags = IRQF_DISABLED,
chan_flag[SH_DMAE_MAX_CHANNELS] = {}; chan_flag[SH_DMAE_MAX_CHANNELS] = {};
int errirq, chan_irq[SH_DMAE_MAX_CHANNELS]; int errirq, chan_irq[SH_DMAE_MAX_CHANNELS];
...@@ -674,6 +683,11 @@ static int sh_dmae_probe(struct platform_device *pdev) ...@@ -674,6 +683,11 @@ static int sh_dmae_probe(struct platform_device *pdev)
struct dma_device *dma_dev; struct dma_device *dma_dev;
struct resource *chan, *dmars, *errirq_res, *chanirq_res; struct resource *chan, *dmars, *errirq_res, *chanirq_res;
if (pdev->dev.of_node)
pdata = of_match_device(sh_dmae_of_match, &pdev->dev)->data;
else
pdata = pdev->dev.platform_data;
/* get platform data */ /* get platform data */
if (!pdata || !pdata->channel_num) if (!pdata || !pdata->channel_num)
return -ENODEV; return -ENODEV;
...@@ -902,12 +916,6 @@ static int sh_dmae_remove(struct platform_device *pdev) ...@@ -902,12 +916,6 @@ static int sh_dmae_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id sh_dmae_of_match[] = {
{ .compatible = "renesas,shdma", },
{ }
};
MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
static struct platform_driver sh_dmae_driver = { static struct platform_driver sh_dmae_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -150,7 +150,8 @@ static const struct sudmac_slave_config *sudmac_find_slave( ...@@ -150,7 +150,8 @@ static const struct sudmac_slave_config *sudmac_find_slave(
return NULL; return NULL;
} }
static int sudmac_set_slave(struct shdma_chan *schan, int slave_id, bool try) static int sudmac_set_slave(struct shdma_chan *schan, int slave_id,
dma_addr_t slave_addr, bool try)
{ {
struct sudmac_chan *sc = to_chan(schan); struct sudmac_chan *sc = to_chan(schan);
const struct sudmac_slave_config *cfg = sudmac_find_slave(sc, slave_id); const struct sudmac_slave_config *cfg = sudmac_find_slave(sc, slave_id);
......
...@@ -96,7 +96,7 @@ struct shdma_ops { ...@@ -96,7 +96,7 @@ struct shdma_ops {
dma_addr_t (*slave_addr)(struct shdma_chan *); dma_addr_t (*slave_addr)(struct shdma_chan *);
int (*desc_setup)(struct shdma_chan *, struct shdma_desc *, int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
dma_addr_t, dma_addr_t, size_t *); dma_addr_t, dma_addr_t, size_t *);
int (*set_slave)(struct shdma_chan *, int, bool); int (*set_slave)(struct shdma_chan *, int, dma_addr_t, bool);
void (*setup_xfer)(struct shdma_chan *, int); void (*setup_xfer)(struct shdma_chan *, int);
void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
struct shdma_desc *(*embedded_desc)(void *, int); struct shdma_desc *(*embedded_desc)(void *, int);
......
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