From d4bdc39f5bd00a2fbeb0fbd29c9cb3b595df38a2 Mon Sep 17 00:00:00 2001 From: Youlin Wang Date: Thu, 24 Jan 2019 12:24:18 -0800 Subject: dmaengine: k3dma: Upgrade k3dma driver to support hisi_asp_dma hardware On the hi3660 hardware there are two (at least) DMA controllers, the DMA-P (Peripheral DMA) and the DMA-A (Audio DMA). The two blocks are similar, but have some slight differences. This resulted in the vendor implementing two separate drivers, which after review, they have been able to condense and re-use the existing k3dma driver. Thus, this patch adds support for the new "hisi-pcm-asp-dma-1.0" compatible string in the binding. One difference with the DMA-A controller, is that it does not need to initialize a clock. So we skip this by adding and using soc data flags. After above this driver will support both k3 and hisi_asp dma hardware. Cc: Dan Williams Cc: Vinod Koul Cc: Zhuangluan Su Cc: Ryan Grachek Cc: Manivannan Sadhasivam Cc: dmaengine@vger.kernel.org Acked-by: Manivannan Sadhasivam Signed-off-by: Youlin Wang Signed-off-by: Tanglei Han [jstultz: Reworked to use of_match_data, commit msg improvements] Signed-off-by: John Stultz Signed-off-by: Vinod Koul --- drivers/dma/k3dma.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'drivers/dma') diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index fdec2b6cfbb0..4dce53227274 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -116,6 +116,14 @@ struct k3_dma_dev { unsigned int irq; }; + +#define K3_FLAG_NOCLK BIT(1) + +struct k3dma_soc_data { + unsigned long flags; +}; + + #define to_k3_dma(dmadev) container_of(dmadev, struct k3_dma_dev, slave) static int k3_dma_config_write(struct dma_chan *chan, @@ -790,8 +798,21 @@ static int k3_dma_transfer_resume(struct dma_chan *chan) return 0; } +static const struct k3dma_soc_data k3_v1_dma_data = { + .flags = 0, +}; + +static const struct k3dma_soc_data asp_v1_dma_data = { + .flags = K3_FLAG_NOCLK, +}; + static const struct of_device_id k3_pdma_dt_ids[] = { - { .compatible = "hisilicon,k3-dma-1.0", }, + { .compatible = "hisilicon,k3-dma-1.0", + .data = &k3_v1_dma_data + }, + { .compatible = "hisilicon,hisi-pcm-asp-dma-1.0", + .data = &asp_v1_dma_data + }, {} }; MODULE_DEVICE_TABLE(of, k3_pdma_dt_ids); @@ -810,6 +831,7 @@ static struct dma_chan *k3_of_dma_simple_xlate(struct of_phandle_args *dma_spec, static int k3_dma_probe(struct platform_device *op) { + const struct k3dma_soc_data *soc_data; struct k3_dma_dev *d; const struct of_device_id *of_id; struct resource *iores; @@ -823,6 +845,10 @@ static int k3_dma_probe(struct platform_device *op) if (!d) return -ENOMEM; + soc_data = device_get_match_data(&op->dev); + if (!soc_data) + return -EINVAL; + d->base = devm_ioremap_resource(&op->dev, iores); if (IS_ERR(d->base)) return PTR_ERR(d->base); @@ -835,10 +861,12 @@ static int k3_dma_probe(struct platform_device *op) "dma-requests", &d->dma_requests); } - d->clk = devm_clk_get(&op->dev, NULL); - if (IS_ERR(d->clk)) { - dev_err(&op->dev, "no dma clk\n"); - return PTR_ERR(d->clk); + if (!(soc_data->flags & K3_FLAG_NOCLK)) { + d->clk = devm_clk_get(&op->dev, NULL); + if (IS_ERR(d->clk)) { + dev_err(&op->dev, "no dma clk\n"); + return PTR_ERR(d->clk); + } } irq = platform_get_irq(op, 0); -- cgit v1.2.3-59-g8ed1b From 1200e070d6cc5ae4ab702c460b48fefc6668eafa Mon Sep 17 00:00:00 2001 From: Li Yu Date: Thu, 24 Jan 2019 12:24:19 -0800 Subject: dmaengine: k3dma: Delete axi_config Axi_config controls whether DMA resources can be accessed in non-secure mode, such as linux kernel. The register should be set by the bootloader stage and depends on the device. Thus, this patch removes axi_config from k3dma driver. Cc: Dan Williams Cc: Vinod Koul Cc: Tanglei Han Cc: Zhuangluan Su Cc: Ryan Grachek Cc: Manivannan Sadhasivam Cc: dmaengine@vger.kernel.org Acked-by: Manivannan Sadhasivam Signed-off-by: Li Yu Signed-off-by: Guodong Xu [jstultz: Minor tweaks to commit message] Signed-off-by: John Stultz Signed-off-by: Vinod Koul --- drivers/dma/k3dma.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/dma') diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index 4dce53227274..e415c854e291 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -52,8 +52,6 @@ #define CX_SRC 0x814 #define CX_DST 0x818 #define CX_CFG 0x81c -#define AXI_CFG 0x820 -#define AXI_CFG_DEFAULT 0x201201 #define CX_LLI_CHAIN_EN 0x2 #define CX_CFG_EN 0x1 @@ -169,7 +167,6 @@ static void k3_dma_set_desc(struct k3_dma_phy *phy, struct k3_desc_hw *hw) writel_relaxed(hw->count, phy->base + CX_CNT0); writel_relaxed(hw->saddr, phy->base + CX_SRC); writel_relaxed(hw->daddr, phy->base + CX_DST); - writel_relaxed(AXI_CFG_DEFAULT, phy->base + AXI_CFG); writel_relaxed(hw->config, phy->base + CX_CFG); } -- cgit v1.2.3-59-g8ed1b From c4994a98faf2797d8977c0d075222962d71c4112 Mon Sep 17 00:00:00 2001 From: Li Yu Date: Thu, 24 Jan 2019 12:24:20 -0800 Subject: dmaengine: k3dma: Add support for dma-channel-mask Add dma-channel-mask as a property for k3dma, it defines available dma channels which a non-secure mode driver can use. One sample usage of this is in Hi3660 SoC. DMA channel 0 is reserved to lpm3, which is a coprocessor for power management. So as a result, any request in kernel (which runs on main processor and in non-secure mode) should start from at least channel 1. Cc: Dan Williams Cc: Vinod Koul Cc: Tanglei Han Cc: Zhuangluan Su Cc: Ryan Grachek Cc: Manivannan Sadhasivam Cc: Guodong Xu Cc: dmaengine@vger.kernel.org Signed-off-by: Li Yu [jstultz: Reworked to use a channel mask] Signed-off-by: John Stultz Signed-off-by: Vinod Koul --- drivers/dma/k3dma.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/dma') diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index e415c854e291..5737d92eaeeb 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -111,6 +111,7 @@ struct k3_dma_dev { struct dma_pool *pool; u32 dma_channels; u32 dma_requests; + u32 dma_channel_mask; unsigned int irq; }; @@ -319,6 +320,9 @@ static void k3_dma_tasklet(unsigned long arg) /* check new channel request in d->chan_pending */ spin_lock_irq(&d->lock); for (pch = 0; pch < d->dma_channels; pch++) { + if (!(d->dma_channel_mask & (1 << pch))) + continue; + p = &d->phy[pch]; if (p->vchan == NULL && !list_empty(&d->chan_pending)) { @@ -336,6 +340,9 @@ static void k3_dma_tasklet(unsigned long arg) spin_unlock_irq(&d->lock); for (pch = 0; pch < d->dma_channels; pch++) { + if (!(d->dma_channel_mask & (1 << pch))) + continue; + if (pch_alloc & (1 << pch)) { p = &d->phy[pch]; c = p->vchan; @@ -856,6 +863,13 @@ static int k3_dma_probe(struct platform_device *op) "dma-channels", &d->dma_channels); of_property_read_u32((&op->dev)->of_node, "dma-requests", &d->dma_requests); + ret = of_property_read_u32((&op->dev)->of_node, + "dma-channel-mask", &d->dma_channel_mask); + if (ret) { + dev_warn(&op->dev, + "dma-channel-mask doesn't exist, considering all as available.\n"); + d->dma_channel_mask = (u32)~0UL; + } } if (!(soc_data->flags & K3_FLAG_NOCLK)) { @@ -887,8 +901,12 @@ static int k3_dma_probe(struct platform_device *op) return -ENOMEM; for (i = 0; i < d->dma_channels; i++) { - struct k3_dma_phy *p = &d->phy[i]; + struct k3_dma_phy *p; + + if (!(d->dma_channel_mask & BIT(i))) + continue; + p = &d->phy[i]; p->idx = i; p->base = d->base + i * 0x40; } -- cgit v1.2.3-59-g8ed1b