From 9d31821fa9ca9a12e22e1238901ab12e295eec86 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 15 Feb 2018 12:25:07 +0000 Subject: [PATCH 1/5] dmaengine: qcom: bam_dma: make bam clk optional When BAM is remotely controlled it does not sound correct to control its clk on Linux side. Make it optional, so that its not mandatory for remote controlled BAM instances. Signed-off-by: Srinivas Kandagatla Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index d076940e0c69..b79691fcc82d 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1233,8 +1233,12 @@ static int bam_dma_probe(struct platform_device *pdev) "qcom,controlled-remotely"); bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); - if (IS_ERR(bdev->bamclk)) - return PTR_ERR(bdev->bamclk); + if (IS_ERR(bdev->bamclk)) { + if (!bdev->controlled_remotely) + return PTR_ERR(bdev->bamclk); + + bdev->bamclk = NULL; + } ret = clk_prepare_enable(bdev->bamclk); if (ret) { From d545afc907fa66b779699b88ec24f7fe7498cbba Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 15 Feb 2018 12:25:08 +0000 Subject: [PATCH 2/5] dt-bindings: dmaengine: bam_dma: add remote controlled bindings This patch adds 2 new properties for remote controlled bam dt bindings. 1. num-channels to indicate number of dma channels. 2. qcom,num-ees to indicate number of Execution Environments. Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/qcom_bam_dma.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt index 9cbf5d9df8fd..cf5b9e44432c 100644 --- a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt +++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt @@ -15,6 +15,10 @@ Required properties: the secure world. - qcom,controlled-remotely : optional, indicates that the bam is controlled by remote proccessor i.e. execution environment. +- num-channels : optional, indicates supported number of DMA channels in a + remotely controlled bam. +- qcom,num-ees : optional, indicates supported number of Execution Environments + in a remotely controlled bam. Example: From 48d163b1aa6e7f650c0b7a4f9c61c387a6def868 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 15 Feb 2018 12:25:09 +0000 Subject: [PATCH 3/5] dmaengine: qcom: bam_dma: get num-channels and num-ees from dt When Linux is master of BAM, it can directly read registers to know number of supported channels, however when its remotely controlled reading these registers would trigger a crash if the BAM is not yet initialized or powered up on the remote side. This patch allows driver to read num-channels and num-ees from Device Tree for remotely controlled BAM. Signed-off-by: Srinivas Kandagatla Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index b79691fcc82d..139e9f5e47a9 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -393,6 +393,7 @@ struct bam_device { struct device_dma_parameters dma_parms; struct bam_chan *channels; u32 num_channels; + u32 num_ees; /* execution environment ID, from DT */ u32 ee; @@ -1128,15 +1129,19 @@ static int bam_init(struct bam_device *bdev) u32 val; /* read revision and configuration information */ - val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION)) >> NUM_EES_SHIFT; - val &= NUM_EES_MASK; + if (!bdev->num_ees) { + val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION)); + bdev->num_ees = (val >> NUM_EES_SHIFT) & NUM_EES_MASK; + } /* check that configured EE is within range */ - if (bdev->ee >= val) + if (bdev->ee >= bdev->num_ees) return -EINVAL; - val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); - bdev->num_channels = val & BAM_NUM_PIPES_MASK; + if (!bdev->num_channels) { + val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); + bdev->num_channels = val & BAM_NUM_PIPES_MASK; + } if (bdev->controlled_remotely) return 0; @@ -1232,6 +1237,18 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, "qcom,controlled-remotely"); + if (bdev->controlled_remotely) { + ret = of_property_read_u32(pdev->dev.of_node, "num-channels", + &bdev->num_channels); + if (ret) + dev_err(bdev->dev, "num-channels unspecified in dt\n"); + + ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees", + &bdev->num_ees); + if (ret) + dev_err(bdev->dev, "num-ees unspecified in dt\n"); + } + bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); if (IS_ERR(bdev->bamclk)) { if (!bdev->controlled_remotely) From 54eb5e26cbb72ba77588098385bf5f492b8323ae Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 15 Feb 2018 12:25:10 +0000 Subject: [PATCH 4/5] dmaengine: qcom: bam_dma: do not write to global regs in remote mode BAM_DESC_CNT_TRSHLD register is global register, which can only be written when BAM is in master mode, So check the mode of operation before writing it. Without this check SOC's xPU would catch such access and crash the system. First noticed on DB820c while testing SLIMBus BAM. Signed-off-by: Srinivas Kandagatla Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 139e9f5e47a9..6919f501b9f3 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -935,12 +935,15 @@ static void bam_apply_new_config(struct bam_chan *bchan, struct bam_device *bdev = bchan->bdev; u32 maxburst; - if (dir == DMA_DEV_TO_MEM) - maxburst = bchan->slave.src_maxburst; - else - maxburst = bchan->slave.dst_maxburst; + if (!bdev->controlled_remotely) { + if (dir == DMA_DEV_TO_MEM) + maxburst = bchan->slave.src_maxburst; + else + maxburst = bchan->slave.dst_maxburst; - writel_relaxed(maxburst, bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD)); + writel_relaxed(maxburst, + bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD)); + } bchan->reconfigure = 0; } From 5b4a68952a89e7decf4ff5e86406975cc730575d Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 15 Feb 2018 12:25:11 +0000 Subject: [PATCH 5/5] dmaengine: qcom: bam_dma: disable runtime pm on remote controlled Remotely controlled BAM instance should not do any power management from CPU side, as cpu can not reliably say if the BAM is busy or not. Disable it for such instances. Signed-off-by: Srinivas Kandagatla Signed-off-by: Vinod Koul --- drivers/dma/qcom/bam_dma.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 6919f501b9f3..d29275b97e84 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1333,6 +1333,11 @@ static int bam_dma_probe(struct platform_device *pdev) if (ret) goto err_unregister_dma; + if (bdev->controlled_remotely) { + pm_runtime_disable(&pdev->dev); + return 0; + } + pm_runtime_irq_safe(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, BAM_DMA_AUTOSUSPEND_DELAY); pm_runtime_use_autosuspend(&pdev->dev); @@ -1416,7 +1421,8 @@ static int __maybe_unused bam_dma_suspend(struct device *dev) { struct bam_device *bdev = dev_get_drvdata(dev); - pm_runtime_force_suspend(dev); + if (!bdev->controlled_remotely) + pm_runtime_force_suspend(dev); clk_unprepare(bdev->bamclk); @@ -1432,7 +1438,8 @@ static int __maybe_unused bam_dma_resume(struct device *dev) if (ret) return ret; - pm_runtime_force_resume(dev); + if (!bdev->controlled_remotely) + pm_runtime_force_resume(dev); return 0; }