From 016b10f4ea76ba2189d476b4a5f7168e57a8d7ad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Jun 2014 01:59:28 -0700 Subject: dma: rcar-audmapp: enable .set_slave Current .set_slave callback did nothing, since it assumed src/dst address come from platform settings. But, it isn't good match to DT probing. This patch enables .set_slave callback to this issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- drivers/dma/sh/rcar-audmapp.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/dma') diff --git a/drivers/dma/sh/rcar-audmapp.c b/drivers/dma/sh/rcar-audmapp.c index 2de77289a2e9..858483bce719 100644 --- a/drivers/dma/sh/rcar-audmapp.c +++ b/drivers/dma/sh/rcar-audmapp.c @@ -47,6 +47,7 @@ struct audmapp_chan { struct shdma_chan shdma_chan; struct audmapp_slave_config *config; void __iomem *base; + dma_addr_t slave_addr; }; struct audmapp_device { @@ -56,7 +57,14 @@ struct audmapp_device { void __iomem *chan_reg; }; +struct audmapp_desc { + struct shdma_desc shdma_desc; + dma_addr_t src; + dma_addr_t dst; +}; + #define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan) +#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc) #define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device, \ struct audmapp_device, shdma_dev.dma_dev) @@ -90,19 +98,20 @@ static void audmapp_halt(struct shdma_chan *schan) } static void audmapp_start_xfer(struct shdma_chan *schan, - struct shdma_desc *sdecs) + struct shdma_desc *sdesc) { struct audmapp_chan *auchan = to_chan(schan); struct audmapp_device *audev = to_dev(auchan); + struct audmapp_desc *desc = to_desc(sdesc); struct audmapp_slave_config *cfg = auchan->config; struct device *dev = audev->dev; u32 chcr = cfg->chcr | PDMACHCR_DE; - dev_dbg(dev, "src/dst/chcr = %pad/%pad/%x\n", - &cfg->src, &cfg->dst, cfg->chcr); + dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n", + &desc->src, &desc->dst, chcr); - audmapp_write(auchan, cfg->src, PDMASAR); - audmapp_write(auchan, cfg->dst, PDMADAR); + audmapp_write(auchan, desc->src, PDMASAR); + audmapp_write(auchan, desc->dst, PDMADAR); audmapp_write(auchan, chcr, PDMACHCR); } @@ -137,14 +146,16 @@ static int audmapp_set_slave(struct shdma_chan *schan, int slave_id, return 0; auchan->config = cfg; + auchan->slave_addr = slave_addr ? : cfg->dst; return 0; } static int audmapp_desc_setup(struct shdma_chan *schan, - struct shdma_desc *sdecs, + struct shdma_desc *sdesc, dma_addr_t src, dma_addr_t dst, size_t *len) { + struct audmapp_desc *desc = to_desc(sdesc); struct audmapp_chan *auchan = to_chan(schan); struct audmapp_slave_config *cfg = auchan->config; @@ -154,6 +165,9 @@ static int audmapp_desc_setup(struct shdma_chan *schan, if (*len > (size_t)AUDMAPP_LEN_MAX) *len = (size_t)AUDMAPP_LEN_MAX; + desc->src = src; + desc->dst = dst; + return 0; } @@ -164,7 +178,9 @@ static void audmapp_setup_xfer(struct shdma_chan *schan, static dma_addr_t audmapp_slave_addr(struct shdma_chan *schan) { - return 0; /* always fixed address */ + struct audmapp_chan *auchan = to_chan(schan); + + return auchan->slave_addr; } static bool audmapp_channel_busy(struct shdma_chan *schan) @@ -183,7 +199,7 @@ static bool audmapp_desc_completed(struct shdma_chan *schan, static struct shdma_desc *audmapp_embedded_desc(void *buf, int i) { - return &((struct shdma_desc *)buf)[i]; + return &((struct audmapp_desc *)buf)[i].shdma_desc; } static const struct shdma_ops audmapp_shdma_ops = { @@ -260,7 +276,7 @@ static int audmapp_probe(struct platform_device *pdev) sdev = &audev->shdma_dev; sdev->ops = &audmapp_shdma_ops; - sdev->desc_size = sizeof(struct shdma_desc); + sdev->desc_size = sizeof(struct audmapp_desc); dma_dev = &sdev->dma_dev; dma_dev->copy_align = LOG2_DEFAULT_XFER_SIZE; -- cgit v1.2.3 From 75bfa5f60a368b1ccacaf71bfc0376b8d9eb2e9f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Jun 2014 01:59:35 -0700 Subject: dma: rcar-audmapp: don't keep audmapp_slave_config for each channeles Current audmapp driver is keeping audmapp_slave_config for each channeles, but, nessasary information is only "chcr". Current style (= keeping audmapp_slave_config) is not good match for DT support. Keep "chcr" instead of audmapp_slave_config Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- drivers/dma/sh/rcar-audmapp.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/dma') diff --git a/drivers/dma/sh/rcar-audmapp.c b/drivers/dma/sh/rcar-audmapp.c index 858483bce719..dd0077519e3e 100644 --- a/drivers/dma/sh/rcar-audmapp.c +++ b/drivers/dma/sh/rcar-audmapp.c @@ -45,9 +45,9 @@ struct audmapp_chan { struct shdma_chan shdma_chan; - struct audmapp_slave_config *config; void __iomem *base; dma_addr_t slave_addr; + u32 chcr; }; struct audmapp_device { @@ -103,9 +103,8 @@ static void audmapp_start_xfer(struct shdma_chan *schan, struct audmapp_chan *auchan = to_chan(schan); struct audmapp_device *audev = to_dev(auchan); struct audmapp_desc *desc = to_desc(sdesc); - struct audmapp_slave_config *cfg = auchan->config; struct device *dev = audev->dev; - u32 chcr = cfg->chcr | PDMACHCR_DE; + u32 chcr = auchan->chcr | PDMACHCR_DE; dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n", &desc->src, &desc->dst, chcr); @@ -145,7 +144,7 @@ static int audmapp_set_slave(struct shdma_chan *schan, int slave_id, if (try) return 0; - auchan->config = cfg; + auchan->chcr = cfg->chcr; auchan->slave_addr = slave_addr ? : cfg->dst; return 0; @@ -156,11 +155,6 @@ static int audmapp_desc_setup(struct shdma_chan *schan, dma_addr_t src, dma_addr_t dst, size_t *len) { struct audmapp_desc *desc = to_desc(sdesc); - struct audmapp_chan *auchan = to_chan(schan); - struct audmapp_slave_config *cfg = auchan->config; - - if (!cfg) - return -ENODEV; if (*len > (size_t)AUDMAPP_LEN_MAX) *len = (size_t)AUDMAPP_LEN_MAX; -- cgit v1.2.3 From caf18c27ddb2fb8ae2a7591b908e7efb7484e459 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Jun 2014 01:59:44 -0700 Subject: dma: rcar-audmapp: add DT support This patch adds DT support to Audio DMAC peri peri driver. Signed-off-by: Kuninori Morimoto [horms+renesas@verge.net.au: Do not add trailing blank line to rcar-audmapp.txt] [horms+renesas@verge.net.au: squashed patch to add NULL terminater to audmapp_of_match] Signed-off-by: Simon Horman Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- .../devicetree/bindings/dma/rcar-audmapp.txt | 29 +++++++++ drivers/dma/sh/rcar-audmapp.c | 72 +++++++++++++++++----- 2 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/rcar-audmapp.txt (limited to 'drivers/dma') diff --git a/Documentation/devicetree/bindings/dma/rcar-audmapp.txt b/Documentation/devicetree/bindings/dma/rcar-audmapp.txt new file mode 100644 index 000000000000..9f1d750d76de --- /dev/null +++ b/Documentation/devicetree/bindings/dma/rcar-audmapp.txt @@ -0,0 +1,29 @@ +* R-Car Audio DMAC peri peri Device Tree bindings + +Required properties: +- compatible: should be "renesas,rcar-audmapp" +- #dma-cells: should be <1>, see "dmas" property below + +Example: + audmapp: audio-dma-pp@0xec740000 { + compatible = "renesas,rcar-audmapp"; + #dma-cells = <1>; + + reg = <0 0xec740000 0 0x200>; + }; + + +* DMA client + +Required properties: +- dmas: a list of <[DMA multiplexer phandle] [SRS/DRS value]> pairs, + where SRS/DRS values are fixed handles, specified in the SoC + manual as the value that would be written into the PDMACHCR. +- dma-names: a list of DMA channel names, one per "dmas" entry + +Example: + + dmas = <&audmapp 0x2d00 + &audmapp 0x3700>; + dma-names = "src0_ssiu0", + "dvc0_ssiu0"; diff --git a/drivers/dma/sh/rcar-audmapp.c b/drivers/dma/sh/rcar-audmapp.c index dd0077519e3e..dabbf0aba2e9 100644 --- a/drivers/dma/sh/rcar-audmapp.c +++ b/drivers/dma/sh/rcar-audmapp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,8 @@ struct audmapp_desc { dma_addr_t dst; }; +#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan) + #define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan) #define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc) #define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device, \ @@ -114,38 +117,50 @@ static void audmapp_start_xfer(struct shdma_chan *schan, audmapp_write(auchan, chcr, PDMACHCR); } -static struct audmapp_slave_config * -audmapp_find_slave(struct audmapp_chan *auchan, int slave_id) +static void audmapp_get_config(struct audmapp_chan *auchan, int slave_id, + u32 *chcr, dma_addr_t *dst) { struct audmapp_device *audev = to_dev(auchan); struct audmapp_pdata *pdata = audev->pdata; struct audmapp_slave_config *cfg; int i; + *chcr = 0; + *dst = 0; + + if (!pdata) { /* DT */ + *chcr = ((u32)slave_id) << 16; + auchan->shdma_chan.slave_id = (slave_id) >> 8; + return; + } + + /* non-DT */ + if (slave_id >= AUDMAPP_SLAVE_NUMBER) - return NULL; + return; for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) - if (cfg->slave_id == slave_id) - return cfg; - - return NULL; + if (cfg->slave_id == slave_id) { + *chcr = cfg->chcr; + *dst = cfg->dst; + break; + } } static int audmapp_set_slave(struct shdma_chan *schan, int slave_id, dma_addr_t slave_addr, bool try) { struct audmapp_chan *auchan = to_chan(schan); - struct audmapp_slave_config *cfg = - audmapp_find_slave(auchan, slave_id); + u32 chcr; + dma_addr_t dst; + + audmapp_get_config(auchan, slave_id, &chcr, &dst); - if (!cfg) - return -ENODEV; if (try) return 0; - auchan->chcr = cfg->chcr; - auchan->slave_addr = slave_addr ? : cfg->dst; + auchan->chcr = chcr; + auchan->slave_addr = slave_addr ? : dst; return 0; } @@ -244,16 +259,39 @@ static void audmapp_chan_remove(struct audmapp_device *audev) dma_dev->chancnt = 0; } +static struct dma_chan *audmapp_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + dma_cap_mask_t mask; + struct dma_chan *chan; + u32 chcr = dma_spec->args[0]; + + if (dma_spec->args_count != 1) + return NULL; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + chan = dma_request_channel(mask, shdma_chan_filter, NULL); + if (chan) + to_shdma_chan(chan)->hw_req = chcr; + + return chan; +} + static int audmapp_probe(struct platform_device *pdev) { struct audmapp_pdata *pdata = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct audmapp_device *audev; struct shdma_dev *sdev; struct dma_device *dma_dev; struct resource *res; int err, i; - if (!pdata) + if (np) + of_dma_controller_register(np, audmapp_of_xlate, pdev); + else if (!pdata) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -315,12 +353,18 @@ static int audmapp_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id audmapp_of_match[] = { + { .compatible = "renesas,rcar-audmapp", }, + {}, +}; + static struct platform_driver audmapp_driver = { .probe = audmapp_probe, .remove = audmapp_remove, .driver = { .owner = THIS_MODULE, .name = "rcar-audmapp-engine", + .of_match_table = audmapp_of_match, }, }; module_platform_driver(audmapp_driver); -- cgit v1.2.3