From patchwork Mon Dec 27 12:05:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 528345 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4FC6DC433FE for ; Mon, 27 Dec 2021 12:06:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236576AbhL0MGb (ORCPT ); Mon, 27 Dec 2021 07:06:31 -0500 Received: from mout.kundenserver.de ([212.227.126.130]:39783 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236567AbhL0MG3 (ORCPT ); Mon, 27 Dec 2021 07:06:29 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MbAYi-1mQH5p0GU4-00bYZk; Mon, 27 Dec 2021 13:06:13 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 01/11] ARM: dts: bcm283x: Update DMA node name per DT schema Date: Mon, 27 Dec 2021 13:05:35 +0100 Message-Id: <1640606743-10993-2-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:QsLR+z93AKo6AfD9jM0srmnL0tQKImMhzR3cNKAgAGjForfGuod Yg9gBdi2W4vHIE2ALR3JukzB3jfl1GxHz53lydrHC6+rJk34XUpTOuITgJz2AfMkYXYCzp7 CGZ9a1DqSVHL9Vuf38XBU4PE6PQuJIKCqJ+SVYelDkG14dgZNpSpa9n8TnjHsXtmatHg+VB 46o6u53LAZJdEB3wZaPVQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:nj9JkdBgdtU=:xKmKl0NaHCN79XXy53psHL 84Gy/AARBkADNSPwprmulHXGe8yhsF/PUQt8aJm2gW6xRXNsbAFbjG1FOmH6m0xu/ObbRFebR cvLkKGZXD0i/cwekMWegTqhniXJ7gwQI22Ln3HafnV7NCMqiaeYmIGyrAxc3pG1FZM06sqTKd +FDy26NdAA150zZWB2GvDieJxhf/a8Mf9FvOxhwWi8xZKM8T7CYWwwk/V+Z8BGNis/AYBkgpv GDUoLvih3ALW+Nwxumxuq/wQ6m4m8iqgLl2XDx0UvHaZlMx0bzI8RYMdHwcjAveFy4yqdCs6L 5GDKzByp09MRFeEgYn+bO70UfZECiF5vpgtw3uqphDO5YT+EiamxUQ19TSldUVgRMyYRNa/oo /zc/fFH67o1nyG3ixGOiwdd2T69Ai5gEUvgj8WRMxQazVqzhIDYw827jpNciIQDFMjzOYtFG8 mEGGKjjfOEuuLAbH9b1wSOXA502ZIT6cPBi+RVRvaNxtLDPjk7oRp2r4ct7EgrQ3DwF12Pv6B PCpaVb5XB+0WsOwcBzTNXzofwIXSCCp+ORnVO8HAlsTKhBp4T4szOMZTrJNppJAK55Qz6MB9S Qp4Ga/Lq2i52wvofouNGkg+z4uUAqgCUmDqaQvsLL3ByKOl7s7IeWJezpGe6NwqE6evSeBgu8 c2WM+WUz3F7IGVmOL8583lKoshBeTO86PVuO+c+dGQVDnn5sz2Hwf8JETQev5dSyQYf5X/ir0 OZPmezhMe0UaQF21 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Follow dma-controller.yaml schema to use 'dma-controller' as node name for BCM2835 DMA controller. Signed-off-by: Stefan Wahren --- arch/arm/boot/dts/bcm2711.dtsi | 2 +- arch/arm/boot/dts/bcm2835-common.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi index b8a4096..590068b 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -76,7 +76,7 @@ }; }; - dma: dma@7e007000 { + dma: dma-controller@7e007000 { compatible = "brcm,bcm2835-dma"; reg = <0x7e007000 0xb00>; interrupts = , diff --git a/arch/arm/boot/dts/bcm2835-common.dtsi b/arch/arm/boot/dts/bcm2835-common.dtsi index 4119271..f540140 100644 --- a/arch/arm/boot/dts/bcm2835-common.dtsi +++ b/arch/arm/boot/dts/bcm2835-common.dtsi @@ -8,7 +8,7 @@ interrupt-parent = <&intc>; soc { - dma: dma@7e007000 { + dma: dma-controller@7e007000 { compatible = "brcm,bcm2835-dma"; reg = <0x7e007000 0xf00>; interrupts = <1 16>, From patchwork Mon Dec 27 12:05:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 528344 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1EB40C4321E for ; Mon, 27 Dec 2021 12:06:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236577AbhL0MGc (ORCPT ); Mon, 27 Dec 2021 07:06:32 -0500 Received: from mout.kundenserver.de ([212.227.126.133]:52495 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236569AbhL0MG3 (ORCPT ); Mon, 27 Dec 2021 07:06:29 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MGz5f-1nFHHi2rQZ-00E4bT; Mon, 27 Dec 2021 13:06:13 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 02/11] dt-bindings: dma: Convert brcm,bcm2835-dma to json-schema Date: Mon, 27 Dec 2021 13:05:36 +0100 Message-Id: <1640606743-10993-3-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:5EBx1vqHQjUwIibXOA/ejfDPHeveGUnOdiS0WCl/uWvy16rhMmD 3igTFnIZuP1gVfVP8rIgTDPrIn7PY7q8udtRc5qE1va9C7Wne6qmHnryakgbi5ZxgzrR77d PIOwPtW+LDq7j0Zyo5jaJccoIWRXLDwWUhUjMSRspJhOoD5gTJG7BKExlSHanoimXDh0F4l yLHfln/CqZgmxefhsH4UQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:XLJknB9NW4s=:NehJJ6QaDj365aBk3SsIQV Q9NOFQla64wFtlsiQdAUwJAmbCuOSMS5XtCmwxboBFue28AZWcFVKW2lzTjulakx6sJXKA6iC W1kzm9EBi3W1tB/m1FtXVH4eL9pdLKsDNa20FOueJOK340cL//KmqyFtdhrsHbh+5Hc1IQ2s6 BWnjpi4cUS+M5HKxqMJolHYBytNLrp18mJNLDuM6tC3IkopsLbHcjyjiIY2s/yBwgNaM53OhV fO4Kk7fgwNvB8BeEL/QjN3J0Q2g2Q8fiFeb3vbL6N8VQE+rnP9I6y+oPUUv80IIc34+QGTADD CnYKPcpfarWAmmS368opF7kRsOh5Ww+RIN8uL4Qe/QDq099v+yT3K0ixcq0aGSGJbCj3eBJkz Mwj8/XaGgwNiVYgTpgc6K2LNgAHjwoyh5EmiUKCy1FOXIST7nzxQUwiPRnvk0khlgmnUe7aV4 nOtixfZ7dSm/rEji8B+fqUjnIM85ue6amFjfy5jRMulMeBTSoeuSAOTMD3E5jc5+LoJbpxTJ+ XBy3+sgLuczJjttvgAqaIIubykrtNmm+bZW+AKR8PNbPHpqC1r59RW86cod8hOr0z+Yzh86AR /q/Tzr0hopCfLicUYWrx8HHvEw70ewq0I5UF752fmVSbqszcWC0gCwsdeMlQWbWTZEd8JJooJ k79sKaW+vHssDsx6fMaslV+lyvKuX352/lyaY/F/M60DtTMPCRipzk8qASeFl1zKAhGTE11qs 1n88j/QjNUDulgL2 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This convert the BCM2835 DMA bindings to YAML format. Signed-off-by: Stefan Wahren --- .../devicetree/bindings/dma/brcm,bcm2835-dma.txt | 83 ---------------- .../devicetree/bindings/dma/brcm,bcm2835-dma.yaml | 107 +++++++++++++++++++++ 2 files changed, 107 insertions(+), 83 deletions(-) delete mode 100644 Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt create mode 100644 Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.yaml diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt deleted file mode 100644 index b6a8cc0..0000000 --- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +++ /dev/null @@ -1,83 +0,0 @@ -* BCM2835 DMA controller - -The BCM2835 DMA controller has 16 channels in total. -Only the lower 13 channels have an associated IRQ. -Some arbitrary channels are used by the firmware -(1,3,6,7 in the current firmware version). -The channels 0,2 and 3 have special functionality -and should not be used by the driver. - -Required properties: -- compatible: Should be "brcm,bcm2835-dma". -- reg: Should contain DMA registers location and length. -- interrupts: Should contain the DMA interrupts associated - to the DMA channels in ascending order. -- interrupt-names: Should contain the names of the interrupt - in the form "dmaXX". - Use "dma-shared-all" for the common interrupt line - that is shared by all dma channels. -- #dma-cells: Must be <1>, the cell in the dmas property of the - client device represents the DREQ number. -- brcm,dma-channel-mask: Bit mask representing the channels - not used by the firmware in ascending order, - i.e. first channel corresponds to LSB. - -Example: - -dma: dma@7e007000 { - compatible = "brcm,bcm2835-dma"; - reg = <0x7e007000 0xf00>; - interrupts = <1 16>, - <1 17>, - <1 18>, - <1 19>, - <1 20>, - <1 21>, - <1 22>, - <1 23>, - <1 24>, - <1 25>, - <1 26>, - /* dma channel 11-14 share one irq */ - <1 27>, - <1 27>, - <1 27>, - <1 27>, - /* unused shared irq for all channels */ - <1 28>; - interrupt-names = "dma0", - "dma1", - "dma2", - "dma3", - "dma4", - "dma5", - "dma6", - "dma7", - "dma8", - "dma9", - "dma10", - "dma11", - "dma12", - "dma13", - "dma14", - "dma-shared-all"; - - #dma-cells = <1>; - brcm,dma-channel-mask = <0x7f35>; -}; - - -DMA clients connected to the BCM2835 DMA controller must use the format -described in the dma.txt file, using a two-cell specifier for each channel. - -Example: - -bcm2835_i2s: i2s@7e203000 { - compatible = "brcm,bcm2835-i2s"; - reg = < 0x7e203000 0x24>; - clocks = <&clocks BCM2835_CLOCK_PCM>; - - dmas = <&dma 2>, - <&dma 3>; - dma-names = "tx", "rx"; -}; diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.yaml b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.yaml new file mode 100644 index 0000000..44cb83f --- /dev/null +++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.yaml @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/brcm,bcm2835-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: BCM2835 DMA controller + +maintainers: + - Nicolas Saenz Julienne + +description: | + The BCM2835 DMA controller has 16 channels in total. + Only the lower 13 channels have an associated IRQ. + Some arbitrary channels are used by the firmware + (1,3,6,7 in the current firmware version). + The channels 0,2 and 3 have special functionality + and should not be used by the driver. + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + compatible: + const: brcm,bcm2835-dma + + reg: + maxItems: 1 + + interrupts: + description: + Should contain the DMA interrupts associated to the DMA channels in + ascending order. + minItems: 1 + maxItems: 16 + + interrupt-names: + minItems: 1 + maxItems: 16 + + "#dma-cells": + const: 1 + description: > + DMA clients must use the format described in dma.txt, giving a phandle + to the DMA controller while the second cell in the dmas property of the + client device represents the DREQ number. + + brcm,dma-channel-mask: + description: + Bit mask representing the channels not used by the firmware in + ascending order, i.e. first channel corresponds to LSB. + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - "#dma-cells" + - brcm,dma-channel-mask + +additionalProperties: false + +examples: + - | + dma: dma-controller@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <1 16>, + <1 17>, + <1 18>, + <1 19>, + <1 20>, + <1 21>, + <1 22>, + <1 23>, + <1 24>, + <1 25>, + <1 26>, + /* dma channel 11-14 share one irq */ + <1 27>, + <1 27>, + <1 27>, + <1 27>, + /* unused shared irq for all channels */ + <1 28>; + interrupt-names = "dma0", + "dma1", + "dma2", + "dma3", + "dma4", + "dma5", + "dma6", + "dma7", + "dma8", + "dma9", + "dma10", + "dma11", + "dma12", + "dma13", + "dma14", + "dma-shared-all"; + #dma-cells = <1>; + brcm,dma-channel-mask = <0x7f35>; + }; + +... From patchwork Mon Dec 27 12:05:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 529411 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B5B6C4332F for ; Mon, 27 Dec 2021 12:06:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236587AbhL0MGf (ORCPT ); Mon, 27 Dec 2021 07:06:35 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:47399 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236586AbhL0MGf (ORCPT ); Mon, 27 Dec 2021 07:06:35 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MryKr-1mgUEN17Ez-00nx3N; Mon, 27 Dec 2021 13:06:14 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 03/11] dmaengine: bcm2835: Support common dma-channel-mask Date: Mon, 27 Dec 2021 13:05:37 +0100 Message-Id: <1640606743-10993-4-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:pLYG2yJd/86QSRmuXUNXZ0jIhtsFv1rfHEN2cSa9TfrRHXAWO4l aNYr2qJeom3SA27zUgKi6qnIgcL0rjTmq/0FDmy2SMlwHx+4AP4XCT2c+qwQexjMvOGKiS1 JTOEQAVEPBUUr7BwZuH4qT2h5SQSpVcrYOJGgtzQeMj6za1WG8IyO+YLj0eiNSrC6IMJn1p /9/wtHXceaKFfdeRcVerA== X-UI-Out-Filterresults: notjunk:1;V03:K0:J6uy7lC+pS8=:/R/8iW/sI1gAwBu30ljRSk jXqZfVAjxRgtDwM6cRkToPx1ynXW1wFJyh2Q8H6djqi5HwsK6+pWX7jNZxor3t/2fo9MCuUfM rdZB1ykQt+N0FEXMK3mdHYizMURtO+BSmLYspKcZ0vIpcFhvBMHX0ycUL26VeA7jkPiJFncic f+Ka9dvWLA0mVfXzCj9EZrxMFs+n3yv0uignNRzEaCGdELeYtl/YCc+KvkVhFw+/XiRyoUyQj Cd2uCaEfJwk1wQ5ZL65s3VkfiaqRHeDrp4Jv1ofgP6IgQkTikTcvgBTZ2GXWjx5zyOz0Ole3y y8sfH/vTdHcI7K4VmibkdOoZF+N3wDb7Gbb4Z7sRvahfDEWLgNYIg4ptytQ3ETlm2HoDiZvEE VAJ/4KDo5CGzT4syfC+Dap4JifeJyisc2+jKh7nQr4xgXRH43v0F7lWEo5mF2NWWejLa1WzcD Iynxj2lVGYcgIHrXdabARmmex3qUKUO8lLMMw0onmbYnZ0rBWgkKudnKHU/TERUf0hfHypZdm ThOjjCfvl+FzUGDahA5QUjFNZsVKhwC8/XFMoJkqX1txAaifmUyhXIBM6EsDzlQT2TkF14DvY gPl6ZGy55KN1sqQRjrsFFFcTxmwG/RkYtZtEvOT1xejCmgIVYKTLeGXot58eR+8jcAhHfJT+m 0dEUMkp5yNzRpRCM7qpVRlb+RZ4gyovXbshezgG0SIQY4pJ/+pMTmN9hIy2J1kqsuQejM3JX8 5l6ykr9GibWR8/6H Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Nowadays there is a generic property for dma-channel-mask in the DMA controller binding. So prefer this one instead of the old vendor specific one. Print a warning in case the old one is used. Btw use the result of of_property_read_u32() as return code in error case. Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 630dfbb..adfe6bc 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -943,12 +943,19 @@ static int bcm2835_dma_probe(struct platform_device *pdev) } /* Request DMA channel mask from device tree */ - if (of_property_read_u32(pdev->dev.of_node, - "brcm,dma-channel-mask", - &chans_available)) { - dev_err(&pdev->dev, "Failed to get channel mask\n"); - rc = -EINVAL; - goto err_no_dma; + rc = of_property_read_u32(pdev->dev.of_node, "dma-channel-mask", + &chans_available); + + if (rc) { + /* Try deprecated property */ + if (of_property_read_u32(pdev->dev.of_node, + "brcm,dma-channel-mask", + &chans_available)) { + dev_err(&pdev->dev, "Failed to get channel mask\n"); + goto err_no_dma; + } + + dev_warn(&pdev->dev, "Please update DT blob\n"); } /* get irqs for each channel that we support */ From patchwork Mon Dec 27 12:05:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 529413 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E216C4167D for ; Mon, 27 Dec 2021 12:06:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236578AbhL0MGc (ORCPT ); Mon, 27 Dec 2021 07:06:32 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:35123 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230075AbhL0MGa (ORCPT ); Mon, 27 Dec 2021 07:06:30 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1M1Yl9-1mzt5p3y0p-00332R; Mon, 27 Dec 2021 13:06:15 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 04/11] dmaengine: bcm2835: move CB info generation into separate function Date: Mon, 27 Dec 2021 13:05:38 +0100 Message-Id: <1640606743-10993-5-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:CPNybPgRYx20mRrC3A4iHHfAsiqMRd/Kohw8QKQNFQ7exA6MA50 PZwl/W//j7iPMWCobsSSe4ImlyfCf5cE1v9nUpc/atYVpV0n0J9qYJnsOfsAgPkdFS5mqfA Vb7my7BxeTVQR2CU4JBZH0itf1t4zZSJGqqcoyDz5DXzeT7r6IwcRi7fpUFyySasHiY+1pe ItIc16jro99YaA1MVYgFg== X-UI-Out-Filterresults: notjunk:1;V03:K0:i6dd0S8v7SI=:KRnssHz/fO2BLDgQFq7bkL 3ggxaBXrA4SzrrxzEpzmHwQlSszb+tXB8UZ5oKaocWdcurVFMnysD69X2QcOWnoMBXU8hRXhv NBH6F/2He7oGthIzyrbSuoRpmBRhiI61Iivd8lOJHOy0N28k7ZYg5fKLXqEUTN6493ThLBHiL 4LYg/ENQTyuhspeAuoClnETUN90aZyRc+IbKmcOqTHz+K4Vdcn5pxtZqFVDM7H94xcfFKPna/ IJVU0vdHex4WnLOzv53lxBTPATT+7awJFX+IYNPL0Im6sS9SvSBIz7WF6hF2rmWdHOiJrL5Z4 PnlmpUmdDWNt1h9HkVmnYKFqqvSc6v0Dq+mhTUDsrHwNbFAo5n0bO25mkgSqynWqqsn4qdwgV TNZoqheTQXDLLHceop/uiJaHt2WMj4Ozuw5WbQcsFiofFfXCLqqlAuJFoVyWoCoCgfaGCTfZ3 uzhG5yZQEPtL6WMrAvutxt6jiQUIWab+ECX9NMVvpHD1lDYQhoxC55+1O5iMeycOlosV1d90Z uW3cxBb3gNmnAN0/sbB+Y7/WTDTsfHQQcW6CDXOsTT5hyzvzgaYDVeVt960O5yK3z7nllW2ke Zy7tdKdmCIncvgWMFDkj/xS4GLSe+V1KzbsYgNuQxbBrIJzIZSJyESfjlWKIS4omkxae94Sff noJEgNeCEWOSwZGhMrIgaX9MI8aje+ruKOL+5u761jI824UZ/1w5Rm8q8EF1mSbh3oEcQ9QZC 3uX8lFn0Wz1Zwmid Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Actually the generation of the Control Block info follows some simple rules. So handle this with a separate function to avoid open coding for every DMA operation. Another advantage is that we can easier introduce other platforms with different info bits. Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 51 ++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index adfe6bc..10c9ba2 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -201,6 +201,35 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc( return container_of(t, struct bcm2835_desc, vd.tx); } +static u32 bcm2835_dma_prepare_cb_info(struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool zero_page) +{ + u32 result; + + if (direction == DMA_MEM_TO_MEM) + return BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; + + result = BCM2835_DMA_WAIT_RESP; + + /* Setup DREQ channel */ + if (c->dreq != 0) + result |= BCM2835_DMA_PER_MAP(c->dreq); + + if (direction == DMA_DEV_TO_MEM) { + result |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; + } else { + result |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; + + /* non-lite channels can write zeroes w/o accessing memory */ + if (zero_page && !c->is_lite_channel) { + result |= BCM2835_DMA_S_IGNORE; + } + } + + return result; +} + static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { size_t i; @@ -615,7 +644,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( { struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; - u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; + u32 info = bcm2835_dma_prepare_cb_info(c, DMA_MEM_TO_MEM, false); u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -646,7 +675,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src = 0, dst = 0; - u32 info = BCM2835_DMA_WAIT_RESP; + u32 info = bcm2835_dma_prepare_cb_info(c, direction, false); u32 extra = BCM2835_DMA_INT_EN; size_t frames; @@ -656,19 +685,14 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( return NULL; } - if (c->dreq != 0) - info |= BCM2835_DMA_PER_MAP(c->dreq); - if (direction == DMA_DEV_TO_MEM) { if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; src = c->cfg.src_addr; - info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; } else { if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; dst = c->cfg.dst_addr; - info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; } /* count frames in sg list */ @@ -698,7 +722,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src, dst; - u32 info = BCM2835_DMA_WAIT_RESP; + u32 info = bcm2835_dma_prepare_cb_info(c, direction, + buf_addr == od->zero_page); u32 extra = 0; size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -729,26 +754,16 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n", __func__, buf_len, period_len); - /* Setup DREQ channel */ - if (c->dreq != 0) - info |= BCM2835_DMA_PER_MAP(c->dreq); - if (direction == DMA_DEV_TO_MEM) { if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; src = c->cfg.src_addr; dst = buf_addr; - info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; } else { if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; dst = c->cfg.dst_addr; src = buf_addr; - info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; - - /* non-lite channels can write zeroes w/o accessing memory */ - if (buf_addr == od->zero_page && !c->is_lite_channel) - info |= BCM2835_DMA_S_IGNORE; } /* calculate number of frames */ From patchwork Mon Dec 27 12:05:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 528343 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00BD3C4167E for ; Mon, 27 Dec 2021 12:06:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230075AbhL0MGd (ORCPT ); Mon, 27 Dec 2021 07:06:33 -0500 Received: from mout.kundenserver.de ([212.227.126.135]:44001 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236568AbhL0MGc (ORCPT ); Mon, 27 Dec 2021 07:06:32 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MCsLo-1nAaBz1wDQ-008rfU; Mon, 27 Dec 2021 13:06:15 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 05/11] dmaengine: bcm2835: move CB final extra info generation into function Date: Mon, 27 Dec 2021 13:05:39 +0100 Message-Id: <1640606743-10993-6-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:UT61IjKwl0DbobMULXOCOAAWeiIa6jN616fv3vRUKt5uXE7XPa+ V+HQ17CrbavcwDYN9f80AS++6dV1zaASSyohTOfndC19yrqlaWku863uHLG8GyFxtV00Dog Cxce5hLXBQFBq/yeb0TxcGozg/ovjCgeJLqqRX022/ynWDb1ZIvWK1AqLDWllwrfRvmicpO PcmSkMF4VLhx1zNyjFIwA== X-UI-Out-Filterresults: notjunk:1;V03:K0:sBWknKLJQQQ=:7cVpLUapyEQLtqfYq11Ktb oCvuuMFwaZuKMYd8QO0NaSTYiYnwfO45VMEwjVCOke+hu/k4ZXe6zu13ClL64U/zPh3bkiQsP uhy2/U9yR9uesiHUzjpPdeW1MveoXvp330v3GTd2f48ugdY5inKNkac00vr0OMfUpLkjh/9xq b93R4BKNLciGJBgnS8Bqwdweg/O+EOQR+KAA9wT+YhbnYCgx7ml+u5CkiKvZcw9AKPWN3p8Vu qzj/GOKANFMolTy26inh59khhUvxw2DQpz55VgfHLxhwXJ8k+PBSqoCNZ+rUOjRT2aI06MJ7w 7joqeivFXAKefp6KCSVCwF//ocmr3GsUJxDu3Zn19Woa9v0Cn98yJRmOvxEs7ppl1H2e1x3CS skrm6V3z8okFK4NIl6ouENGovvj6XQ9yKDN4jGeqKaINIjL8waY3tYiIXZlL68SwL9FzvfHlf Wd0khgFSmVZlLE8ssJextQVWNwvJLfcNoHWbiK4fK6Zw4lntmkXUKlt0OA61C26tsPsx+gWOg txaO2gDkSwNOEOCv7Zq3Daude5Go+YjKbCPoRK6ti8NFdDThlj3PKXzhOVD2ZnvyOEk2LDv2z QCRaDUMZB/aDUGXRwABlViJ/YPPs2F1h0SJgQ+i7AmZkLNmSrBsYISALKsuv0T2hWjLfm/uDG FzEmPDCSZhLO42RnXSPg6WJ9Zkkff8Nr0LvmYxoCXtLrtKkEc2rCltdtgrNgJ9uOCSkD8E6DN o3Xtd7uRCgGnahXT Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Similar to the info generation, generate the final extra info with a separate function. This is necessary to introduce other platforms with different info bits. Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 10c9ba2..863792e 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -230,6 +230,29 @@ static u32 bcm2835_dma_prepare_cb_info(struct bcm2835_chan *c, return result; } +static u32 bcm2835_dma_prepare_cb_extra(struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool cyclic, bool final, + unsigned long flags) +{ + u32 result = 0; + + if (cyclic) { + if (flags & DMA_PREP_INTERRUPT) + result |= BCM2835_DMA_INT_EN; + } else { + if (!final) + return 0; + + result |= BCM2835_DMA_INT_EN; + + if (direction == DMA_MEM_TO_MEM) + result |= BCM2835_DMA_WAIT_RESP; + } + + return result; +} + static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { size_t i; @@ -645,7 +668,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; u32 info = bcm2835_dma_prepare_cb_info(c, DMA_MEM_TO_MEM, false); - u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; + u32 extra = bcm2835_dma_prepare_cb_extra(c, DMA_MEM_TO_MEM, false, + true, 0); size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -676,7 +700,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( struct bcm2835_desc *d; dma_addr_t src = 0, dst = 0; u32 info = bcm2835_dma_prepare_cb_info(c, direction, false); - u32 extra = BCM2835_DMA_INT_EN; + u32 extra = bcm2835_dma_prepare_cb_extra(c, direction, false, true, 0); size_t frames; if (!is_slave_direction(direction)) { @@ -724,7 +748,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( dma_addr_t src, dst; u32 info = bcm2835_dma_prepare_cb_info(c, direction, buf_addr == od->zero_page); - u32 extra = 0; + u32 extra = bcm2835_dma_prepare_cb_extra(c, direction, true, true, 0); size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -740,9 +764,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( return NULL; } - if (flags & DMA_PREP_INTERRUPT) - extra |= BCM2835_DMA_INT_EN; - else + if (!(flags & DMA_PREP_INTERRUPT)) period_len = buf_len; /* From patchwork Mon Dec 27 12:05:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 528341 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2582C35263 for ; Mon, 27 Dec 2021 12:06:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236543AbhL0MGf (ORCPT ); Mon, 27 Dec 2021 07:06:35 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:54491 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236580AbhL0MGe (ORCPT ); Mon, 27 Dec 2021 07:06:34 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MkYkI-1magg545FO-00m2RS; Mon, 27 Dec 2021 13:06:16 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 06/11] dmaengine: bcm2835: make address increment platform independent Date: Mon, 27 Dec 2021 13:05:40 +0100 Message-Id: <1640606743-10993-7-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:HrffKyC4m6ikFaJSkU6yeCuvlOClCWXEx4SVySiaZWR2sYV95iQ BgBYtZxP6knwrhszIG5N6afpgRnMTzau0G6fS+Rs2DMd+Nvrh2Ca4bN4EAr1jKTIbnGtbjo 7hjfBm4WQrOfcoyiaPR1jV0MXBqj8/GplXipQ21YhDGLi9hjg+mV1WWEFzdO6dL4Cadlgb9 /rP2OAS/q/m0PBs5YvyUA== X-UI-Out-Filterresults: notjunk:1;V03:K0:DXG1JcMei24=:cHwkAopfBiYzTK5pSHm0yY X+TUWkiYWFgzoqiAzMyAPovCn5PbMF25gZ7ZHvRRqtnE2zGAwSdKfWzWqdAnERAYG6oLjCHsU 2S4DIfiY2ja3/ge87akcdohMjqEwr1H7dZOpooqquDc2mh595daLKhSXt8yAzKTU4AZpQfg7W M8gfpr8J12DSvW1I9EkUGU9f0dIyz4X3qJMcDEVoObxb8PuEUaegm02X25OOz2vBnoE+fUtcA vjYBgStX9c/Nn1RV2DPJzVXiHV77IJndmOoluNbQLWlIdc7qFqk5yvvXsZllcaduGHt/bW4Nb 1cQRlmHxz0AuL4tlDPRxseqnvHQ2jM6MaO3T93oVXpiO4INTn0YWh+m7L3RKjBFnjv3qMptPF H+xoMKe41G5U5pHYiTK1eOULP1OCfOf3Tj+BHxATBjWMGOH1P+WGCV1blJnB4f3gw0HmpT9oK 8xCf0xAYp+tMW7BULKTp4PBrLPTpXUQWibyL+oxOd3UgoqWWZZ6Zp4jhulMJ4ZEP1vKi3/stG TbYsqEwEvJbmM1dMR1aU44HvUaKYCMnudI5tv2YbUPvFBPTP51NRtoCKtkGcL6hddzcOvhEvP RIi+8Lb+fLpetYfbTJpNGN2twEqhCftDfh9ZP5i/CuOYsfl8IBWGxoK9cNp/n/E7PJ45//HSZ dvtYgSegso+lH9H9+Jjk6h1SH5KJiTZHYmyoADlj2ugLawP59TZiHQbCtodgtT7fzrtdhuuUY WpzY5n2GEqgzrlXS Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Actually the criteria to increment source & destination address doesn't based on platform specific bits. It's just the DMA transfer direction which is translated into the info bits. So introduce two new helper functions and get the rid of these platform specifics. Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 863792e..a7b9f88 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -253,6 +253,24 @@ static u32 bcm2835_dma_prepare_cb_extra(struct bcm2835_chan *c, return result; } +static inline bool need_src_incr(enum dma_transfer_direction direction) +{ + return direction != DMA_DEV_TO_MEM; +} + +static inline bool need_dst_incr(enum dma_transfer_direction direction) +{ + switch (direction) { + case DMA_MEM_TO_MEM: + case DMA_DEV_TO_MEM: + return true; + default: + break; + } + + return false; +} + static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { size_t i; @@ -337,10 +355,8 @@ static inline size_t bcm2835_dma_count_frames_for_sg( * @cyclic: it is a cyclic transfer * @info: the default info bits to apply per controlblock * @frames: number of controlblocks to allocate - * @src: the src address to assign (if the S_INC bit is set - * in @info, then it gets incremented) - * @dst: the dst address to assign (if the D_INC bit is set - * in @info, then it gets incremented) + * @src: the src address to assign + * @dst: the dst address to assign * @buf_len: the full buffer length (may also be 0) * @period_len: the period length when to apply @finalextrainfo * in addition to the last transfer @@ -409,9 +425,9 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( d->cb_list[frame - 1].cb->next = cb_entry->paddr; /* update src and dst and length */ - if (src && (info & BCM2835_DMA_S_INC)) + if (src && need_src_incr(direction)) src += control_block->length; - if (dst && (info & BCM2835_DMA_D_INC)) + if (dst && need_dst_incr(direction)) dst += control_block->length; /* Length of total transfer */ From patchwork Mon Dec 27 12:05:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 529412 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05C0FC3525C for ; Mon, 27 Dec 2021 12:06:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236581AbhL0MGe (ORCPT ); Mon, 27 Dec 2021 07:06:34 -0500 Received: from mout.kundenserver.de ([212.227.126.133]:35911 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236543AbhL0MGd (ORCPT ); Mon, 27 Dec 2021 07:06:33 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1Ml6i4-1ma8Rg1zeG-00lUD6; Mon, 27 Dec 2021 13:06:16 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 07/11] dmaengine: bcm2385: drop info parameters Date: Mon, 27 Dec 2021 13:05:41 +0100 Message-Id: <1640606743-10993-8-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:veQprJd5ydJ2eSPjMP4NQjyRPxhb9yVxCJ9uCTSwnJ7PEmBIYDV FnvEWSKgnsbLrrYaHkBzF6YUSQS7D2j5YnYLkLLQ+WJWQwrhYFFCDjYqCa3GVi/wQc6+puL RL26IYqGiQ9BXq3cv1Ki5FJgfLwjQoXFcBqb78B2lGd5NK5GLjOs261pTc2Z/KaEdy0EDKX tpGW4VeHP5pLa7fPmC00w== X-UI-Out-Filterresults: notjunk:1;V03:K0:/PmHXNHlx3M=:EarIMjBb0WU74G31gJ373C 98/eMtcNYB6jIYH4uiLPtJEynkaeUbBLdldZfrYsQ/hcLGmxM31Sk2HhohlKdKXl4oZH9f2YF AG3j0SvJKH5fE3+5ZuT+0GrnpmVBJ1DfIT1Of+1mD9iHIzMPVgEMjkrUpsjr3L6g+YNUJ55TL D/yPQ0eInsxWlClo5woXLqhprFmIfTbz0DmLt1pn8ZXvr+4UE51+E4lGA6DSQI//9KtG5iGD2 DZtE4Ff6BbKk4wM4FzglW2jTxusJTyJkP9Ykv942sBaB/iwtb6ggI+wxyRh83M5MGUy3FC6s5 IzE3vKeectS9/5iiSpWuDE9uZwHOjPW99fT/7ddvSUSMKBWItxT701uyLBxuRp1JJfVR/kZmB 0NvESVSFxWK1OfRtlgvjfXgpwQXtEPjPIYQUwK0IQ++sg/TZLLAq4hMtgyxjiXInK+aY6fj1V ciV/JolciAqXaC8Pmq2HNDP0ZlXWxQfmtvIX4tc5IToSzCn1rHFp4B+NXRRWWBTXnpv5RdIRJ OnvqSGFZ7L5YXi+HmmhmCyl5s7IwL2Cwx9IJCf84m32XIdZZNkeILvn+ERxREN6xEuGDDjDEd cK1ps8VpbUsnEJotEpCBteZSVme3lCFshGBSfQryqw0hKHwOFEW8Q4tAmAeGOyIM0zWLjRsHI x55FFtgyphbK0aRqVS7pocoDDuG/7UiwfCGlDe6GDWnfCjWSe5Rb7j4suorCEznIr4ZWz3gLH UpYF1P2wc3KA+Aud Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The parameters info and finalextrainfo are platform specific. So drop them by generating them within bcm2835_dma_create_cb_chain(). Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 75 +++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index a7b9f88..997fe6e 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -288,13 +288,12 @@ static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) container_of(vd, struct bcm2835_desc, vd)); } -static void bcm2835_dma_create_cb_set_length( +static bool bcm2835_dma_create_cb_set_length( struct bcm2835_chan *chan, struct bcm2835_dma_cb *control_block, size_t len, size_t period_len, - size_t *total_len, - u32 finalextrainfo) + size_t *total_len) { size_t max_len = bcm2835_dma_max_frame_length(chan); @@ -303,7 +302,7 @@ static void bcm2835_dma_create_cb_set_length( /* finished if we have no period_length */ if (!period_len) - return; + return false; /* * period_len means: that we need to generate @@ -317,7 +316,7 @@ static void bcm2835_dma_create_cb_set_length( if (*total_len + control_block->length < period_len) { /* update number of bytes in this period so far */ *total_len += control_block->length; - return; + return false; } /* calculate the length that remains to reach period_length */ @@ -326,8 +325,7 @@ static void bcm2835_dma_create_cb_set_length( /* reset total_length for next period */ *total_len = 0; - /* add extrainfo bits in info */ - control_block->info |= finalextrainfo; + return true; } static inline size_t bcm2835_dma_count_frames_for_sg( @@ -353,7 +351,6 @@ static inline size_t bcm2835_dma_count_frames_for_sg( * @chan: the @dma_chan for which we run this * @direction: the direction in which we transfer * @cyclic: it is a cyclic transfer - * @info: the default info bits to apply per controlblock * @frames: number of controlblocks to allocate * @src: the src address to assign * @dst: the dst address to assign @@ -361,22 +358,24 @@ static inline size_t bcm2835_dma_count_frames_for_sg( * @period_len: the period length when to apply @finalextrainfo * in addition to the last transfer * this will also break some control-blocks early - * @finalextrainfo: additional bits in last controlblock - * (or when period_len is reached in case of cyclic) * @gfp: the GFP flag to use for allocation + * @flags */ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( struct dma_chan *chan, enum dma_transfer_direction direction, - bool cyclic, u32 info, u32 finalextrainfo, size_t frames, - dma_addr_t src, dma_addr_t dst, size_t buf_len, - size_t period_len, gfp_t gfp) + bool cyclic, size_t frames, dma_addr_t src, dma_addr_t dst, + size_t buf_len, size_t period_len, gfp_t gfp, unsigned long flags) { + struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); size_t len = buf_len, total_len; size_t frame; struct bcm2835_desc *d; struct bcm2835_cb_entry *cb_entry; struct bcm2835_dma_cb *control_block; + u32 extrainfo = bcm2835_dma_prepare_cb_extra(c, direction, cyclic, + false, flags); + bool zero_page = false; if (!frames) return NULL; @@ -390,6 +389,15 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( d->dir = direction; d->cyclic = cyclic; + switch (direction) { + case DMA_MEM_TO_MEM: + case DMA_DEV_TO_MEM: + break; + default: + zero_page = src == od->zero_page; + } + + /* * Iterate over all frames, create a control block * for each frame and link them together. @@ -403,7 +411,8 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( /* fill in the control block */ control_block = cb_entry->cb; - control_block->info = info; + control_block->info = bcm2835_dma_prepare_cb_info(c, direction, + zero_page); control_block->src = src; control_block->dst = dst; control_block->stride = 0; @@ -411,10 +420,12 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( /* set up length in control_block if requested */ if (buf_len) { /* calculate length honoring period_length */ - bcm2835_dma_create_cb_set_length( + if (bcm2835_dma_create_cb_set_length( c, control_block, - len, period_len, &total_len, - cyclic ? finalextrainfo : 0); + len, period_len, &total_len)) { + /* add extrainfo bits in info */ + control_block->info |= extrainfo; + } /* calculate new remaining length */ len -= control_block->length; @@ -435,7 +446,9 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( } /* the last frame requires extra flags */ - d->cb_list[d->frames - 1].cb->info |= finalextrainfo; + extrainfo = bcm2835_dma_prepare_cb_extra(c, direction, cyclic, true, + flags); + d->cb_list[d->frames - 1].cb->info |= extrainfo; /* detect a size missmatch */ if (buf_len && (d->size != buf_len)) @@ -683,9 +696,6 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( { struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; - u32 info = bcm2835_dma_prepare_cb_info(c, DMA_MEM_TO_MEM, false); - u32 extra = bcm2835_dma_prepare_cb_extra(c, DMA_MEM_TO_MEM, false, - true, 0); size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -697,9 +707,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( frames = bcm2835_dma_frames_for_length(len, max_len); /* allocate the CB chain - this also fills in the pointers */ - d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false, - info, extra, frames, - src, dst, len, 0, GFP_KERNEL); + d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false, frames, + src, dst, len, 0, GFP_KERNEL, 0); if (!d) return NULL; @@ -715,8 +724,6 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src = 0, dst = 0; - u32 info = bcm2835_dma_prepare_cb_info(c, direction, false); - u32 extra = bcm2835_dma_prepare_cb_extra(c, direction, false, true, 0); size_t frames; if (!is_slave_direction(direction)) { @@ -739,10 +746,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len); /* allocate the CB chain */ - d = bcm2835_dma_create_cb_chain(chan, direction, false, - info, extra, - frames, src, dst, 0, 0, - GFP_NOWAIT); + d = bcm2835_dma_create_cb_chain(chan, direction, false, frames, src, + dst, 0, 0, GFP_NOWAIT, 0); if (!d) return NULL; @@ -758,13 +763,9 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction direction, unsigned long flags) { - struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src, dst; - u32 info = bcm2835_dma_prepare_cb_info(c, direction, - buf_addr == od->zero_page); - u32 extra = bcm2835_dma_prepare_cb_extra(c, direction, true, true, 0); size_t max_len = bcm2835_dma_max_frame_length(c); size_t frames; @@ -815,10 +816,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine * implementation calls prep_dma_cyclic with interrupts disabled. */ - d = bcm2835_dma_create_cb_chain(chan, direction, true, - info, extra, - frames, src, dst, buf_len, - period_len, GFP_NOWAIT); + d = bcm2835_dma_create_cb_chain(chan, direction, true, frames, src, dst, + buf_len, period_len, GFP_NOWAIT, flags); if (!d) return NULL; From patchwork Mon Dec 27 12:05:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 528342 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 959FCC433FE for ; Mon, 27 Dec 2021 12:06:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236583AbhL0MGd (ORCPT ); Mon, 27 Dec 2021 07:06:33 -0500 Received: from mout.kundenserver.de ([212.227.126.135]:38865 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236574AbhL0MGc (ORCPT ); Mon, 27 Dec 2021 07:06:32 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1N9MlI-1mPEMf2TIq-015LTo; Mon, 27 Dec 2021 13:06:17 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 09/11] dmaengine: bcm2835: introduce multi platform support Date: Mon, 27 Dec 2021 13:05:43 +0100 Message-Id: <1640606743-10993-10-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> References: <1640606743-10993-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:hRYLB1N608LvE2RK10d2h3RkkDf6BDGvwFZi9WSLHZ66qnfEWBy m+8bFBsJermtvSfk4jjzM8SYeFIXCqSHv5laiqZ3ahBTzpj5HFw7N4JQZAoQwwCwJ+p+ATN UFKNy6dDCtMMsXp+B0PbtYBVm240y7VK0UK4l1gban2VKO56Up0jpSjGHlSJsPdkpvhHG1/ 2BNW6L8UNMx4o3JM7SXzA== X-UI-Out-Filterresults: notjunk:1;V03:K0:UQEuk0NfnIA=:vK7MiNwq2h/Dg9jI6vth9U sCXYQDJCYUq69bRXK+zZC96f3Y4l+cg0SRgNWFcvDeo5Bdb45r+qNAhP/tp/Q51laNyaumcFR 3Gbq6dreI/1F7rUx9n27Z0EMMXSFFA/IkTMV/nRkgsr0Ay9SXTQJVcvAwFBVNryHTUZeDaZ4Q P3zS6pjfT/Jmc6lnOAm4gZmZDv37YAWyl8AtqEdDBRQhQQhZ2ur1mCAndp6719HCarfGkaS28 NT29ts95QROSv18hyPD7a/UJv96901M7Ey0ZpzOWcXPi2aJ/ntH8E9wC+lWni4cRv8a4rHHZb THWjNdyDP7/JPMjeoNNCc7DgzwTmbAtTYVumae7os/q8XZww2I0WYVDxVZjvwO8I/MJwn/B/Z O4XCcDY/qgA1d8T+IYgTfkl+KVj1rNXEX5YmRaveXztAlWkaaukC9+uvSp228PXavRTCZRrbE 5Q2JN/DYQ+2FTmCAHW21awPlqD/d89aqyrCjf2UmKLcIG+8lH8SNHV7aB90cYieeJacVia4BM I5sdE7q9hsJR6FOQaJGa1EIs6T+Rl7ix8HaxAcyGnn3LAjK6E71ejhum8hgsxEO4UO2vNe6WB X5OOTW2cFBlsogIVG9667IjTq3MORdaiV1P3jeAH+5iCa2fYeEZiHEMd9bUBqmEe8IyzJqfLq tpJX2cdWGL7pJBH0NClohVC4SDprO/dBam9Ti+N1DuZWc9TDEzHciN+VQR3nzGu8ESFNgyso8 oF2K+sDQNB0jAj94 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This finally moves all platform specific stuff into a separate structure, which is initialized on the OF compatible during probing. Since the DMA control block is different on the BCM2711 platform, we introduce a common control block to reserve the necessary space and adequate methods for access. Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 303 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 235 insertions(+), 68 deletions(-) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 0933404..7159fa2 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -48,6 +48,11 @@ struct bcm2835_dmadev { struct dma_device ddev; void __iomem *base; dma_addr_t zero_page; + const struct bcm2835_dma_cfg *cfg; +}; + +struct bcm_dma_cb { + uint32_t rsvd[8]; }; struct bcm2835_dma_cb { @@ -61,7 +66,7 @@ struct bcm2835_dma_cb { }; struct bcm2835_cb_entry { - struct bcm2835_dma_cb *cb; + struct bcm_dma_cb *cb; dma_addr_t paddr; }; @@ -82,6 +87,38 @@ struct bcm2835_chan { bool is_lite_channel; }; +struct bcm2835_dma_cfg { + dma_addr_t addr_offset; + u32 cs_reg; + u32 cb_reg; + + u32 wait_mask; + u32 reset_mask; + u32 int_mask; + u32 active_mask; + + u32 (*cb_get_length)(void *data); + dma_addr_t (*cb_get_addr)(void *data, enum dma_transfer_direction); + + void (*cb_init)(void *data, struct bcm2835_chan *c, + enum dma_transfer_direction, u32 src, u32 dst, + bool zero_page); + void (*cb_set_src)(void *data, enum dma_transfer_direction, u32 src); + void (*cb_set_dst)(void *data, enum dma_transfer_direction, u32 dst); + void (*cb_set_next)(void *data, u32 next); + void (*cb_set_length)(void *data, u32 length); + void (*cb_append_extra)(void *data, + struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool cyclic, bool final, unsigned long flags); + + u32 (*to_cb_addr)(dma_addr_t addr); + + void (*chan_plat_init)(struct bcm2835_chan *c); + dma_addr_t (*read_addr)(struct bcm2835_chan *c, + enum dma_transfer_direction); +}; + struct bcm2835_desc { struct bcm2835_chan *c; struct virt_dma_desc vd; @@ -190,6 +227,13 @@ static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) return container_of(d, struct bcm2835_dmadev, ddev); } +static inline const struct bcm2835_dma_cfg *to_bcm2835_cfg(struct dma_device *d) +{ + struct bcm2835_dmadev *od = container_of(d, struct bcm2835_dmadev, ddev); + + return od->cfg; +} + static inline struct bcm2835_chan *to_bcm2835_dma_chan(struct dma_chan *c) { return container_of(c, struct bcm2835_chan, vc.chan); @@ -271,6 +315,104 @@ static inline bool need_dst_incr(enum dma_transfer_direction direction) return false; } +static inline u32 bcm2835_dma_cb_get_length(void *data) +{ + struct bcm2835_dma_cb *cb = data; + + return cb->length; +} + +static inline dma_addr_t +bcm2835_dma_cb_get_addr(void *data, enum dma_transfer_direction direction) +{ + struct bcm2835_dma_cb *cb = data; + + if (direction == DMA_DEV_TO_MEM) + return cb->dst; + + return cb->src; +} + +static inline void +bcm2835_dma_cb_init(void *data, struct bcm2835_chan *c, + enum dma_transfer_direction direction, u32 src, u32 dst, + bool zero_page) +{ + struct bcm2835_dma_cb *cb = data; + + cb->info = bcm2835_dma_prepare_cb_info(c, direction, zero_page); + cb->src = src; + cb->dst = dst; + cb->stride = 0; + cb->next = 0; +} + +static inline void +bcm2835_dma_cb_set_src(void *data, enum dma_transfer_direction direction, + u32 src) +{ + struct bcm2835_dma_cb *cb = data; + + cb->src = src; +} + +static inline void +bcm2835_dma_cb_set_dst(void *data, enum dma_transfer_direction direction, + u32 dst) +{ + struct bcm2835_dma_cb *cb = data; + + cb->dst = dst; +} + +static inline void bcm2835_dma_cb_set_next(void *data, u32 next) +{ + struct bcm2835_dma_cb *cb = data; + + cb->next = next; +} + +static inline void bcm2835_dma_cb_set_length(void *data, u32 length) +{ + struct bcm2835_dma_cb *cb = data; + + cb->length = length; +} + +static inline void +bcm2835_dma_cb_append_extra(void *data, struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool cyclic, bool final, unsigned long flags) +{ + struct bcm2835_dma_cb *cb = data; + + cb->info |= bcm2835_dma_prepare_cb_extra(c, direction, cyclic, final, + flags); +} + +static inline dma_addr_t bcm2835_dma_to_cb_addr(dma_addr_t addr) +{ + return addr; +} + +static void bcm2835_dma_chan_plat_init(struct bcm2835_chan *c) +{ + /* check in DEBUG register if this is a LITE channel */ + if (readl(c->chan_base + BCM2835_DMA_DEBUG) & BCM2835_DMA_DEBUG_LITE) + c->is_lite_channel = true; +} + +static dma_addr_t bcm2835_dma_read_addr(struct bcm2835_chan *c, + enum dma_transfer_direction direction) +{ + if (direction == DMA_MEM_TO_DEV) + return readl(c->chan_base + BCM2835_DMA_SOURCE_AD); + else if (direction == DMA_DEV_TO_MEM) + return readl(c->chan_base + BCM2835_DMA_DEST_AD); + + return 0; +} + static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { size_t i; @@ -290,16 +432,19 @@ static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) static bool bcm2835_dma_create_cb_set_length( struct dma_chan *chan, - struct bcm2835_dma_cb *control_block, + void *data, size_t len, size_t period_len, size_t *total_len) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); size_t max_len = bcm2835_dma_max_frame_length(c); /* set the length taking lite-channel limitations into account */ - control_block->length = min_t(u32, len, max_len); + u32 length = min_t(u32, len, max_len); + + cfg->cb_set_length(data, length); /* finished if we have no period_length */ if (!period_len) @@ -314,14 +459,14 @@ static bool bcm2835_dma_create_cb_set_length( */ /* have we filled in period_length yet? */ - if (*total_len + control_block->length < period_len) { + if (*total_len + length < period_len) { /* update number of bytes in this period so far */ - *total_len += control_block->length; + *total_len += length; return false; } /* calculate the length that remains to reach period_length */ - control_block->length = period_len - *total_len; + cfg->cb_set_length(data, period_len - *total_len); /* reset total_length for next period */ *total_len = 0; @@ -367,15 +512,14 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( bool cyclic, size_t frames, dma_addr_t src, dma_addr_t dst, size_t buf_len, size_t period_len, gfp_t gfp, unsigned long flags) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); size_t len = buf_len, total_len; size_t frame; struct bcm2835_desc *d; struct bcm2835_cb_entry *cb_entry; - struct bcm2835_dma_cb *control_block; - u32 extrainfo = bcm2835_dma_prepare_cb_extra(c, direction, cyclic, - false, flags); + struct bcm_dma_cb *control_block; bool zero_page = false; if (!frames) @@ -412,12 +556,7 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( /* fill in the control block */ control_block = cb_entry->cb; - control_block->info = bcm2835_dma_prepare_cb_info(c, direction, - zero_page); - control_block->src = src; - control_block->dst = dst; - control_block->stride = 0; - control_block->next = 0; + cfg->cb_init(control_block, c, src, dst, direction, zero_page); /* set up length in control_block if requested */ if (buf_len) { /* calculate length honoring period_length */ @@ -425,31 +564,33 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( chan, control_block, len, period_len, &total_len)) { /* add extrainfo bits in info */ - control_block->info |= extrainfo; + bcm2835_dma_cb_append_extra(control_block, c, + direction, cyclic, + false, flags); } /* calculate new remaining length */ - len -= control_block->length; + len -= cfg->cb_get_length(control_block); } /* link this the last controlblock */ if (frame) - d->cb_list[frame - 1].cb->next = cb_entry->paddr; + cfg->cb_set_next(d->cb_list[frame - 1].cb, + cb_entry->paddr); /* update src and dst and length */ if (src && need_src_incr(direction)) - src += control_block->length; + src += cfg->cb_get_length(control_block); if (dst && need_dst_incr(direction)) - dst += control_block->length; + dst += cfg->cb_get_length(control_block); /* Length of total transfer */ - d->size += control_block->length; + d->size += cfg->cb_get_length(control_block); } /* the last frame requires extra flags */ - extrainfo = bcm2835_dma_prepare_cb_extra(c, direction, cyclic, true, - flags); - d->cb_list[d->frames - 1].cb->info |= extrainfo; + cfg->cb_append_extra(d->cb_list[d->frames - 1].cb, c, direction, cyclic, + true, flags); /* detect a size missmatch */ if (buf_len && (d->size != buf_len)) @@ -469,6 +610,7 @@ static void bcm2835_dma_fill_cb_chain_with_sg( struct scatterlist *sgl, unsigned int sg_len) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); size_t len, max_len; unsigned int i; @@ -479,18 +621,19 @@ static void bcm2835_dma_fill_cb_chain_with_sg( for_each_sg(sgl, sgent, sg_len, i) { for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent); len > 0; - addr += cb->cb->length, len -= cb->cb->length, cb++) { + addr += cfg->cb_get_length(cb->cb), len -= cfg->cb_get_length(cb->cb), cb++) { if (direction == DMA_DEV_TO_MEM) - cb->cb->dst = addr; + cfg->cb_set_dst(cb->cb, direction, addr); else - cb->cb->src = addr; - cb->cb->length = min(len, max_len); + cfg->cb_set_src(cb->cb, direction, addr); + cfg->cb_set_length(cb->cb, min(len, max_len)); } } } static void bcm2835_dma_abort(struct dma_chan *chan) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); void __iomem *chan_base = c->chan_base; long int timeout = 10000; @@ -499,15 +642,15 @@ static void bcm2835_dma_abort(struct dma_chan *chan) * A zero control block address means the channel is idle. * (The ACTIVE flag in the CS register is not a reliable indicator.) */ - if (!readl(chan_base + BCM2835_DMA_ADDR)) + if (!readl(chan_base + cfg->cb_reg)) return; /* Write 0 to the active bit - Pause the DMA */ - writel(0, chan_base + BCM2835_DMA_CS); + writel(0, chan_base + cfg->cs_reg); /* Wait for any current AXI transfer to complete */ - while ((readl(chan_base + BCM2835_DMA_CS) & - BCM2835_DMA_WAITING_FOR_WRITES) && --timeout) + while ((readl(chan_base + cfg->cs_reg) & cfg->wait_mask) && + --timeout) cpu_relax(); /* Peripheral might be stuck and fail to signal AXI write responses */ @@ -515,11 +658,12 @@ static void bcm2835_dma_abort(struct dma_chan *chan) dev_err(c->vc.chan.device->dev, "failed to complete outstanding writes\n"); - writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS); + writel(cfg->reset_mask, chan_base + cfg->cs_reg); } static void bcm2835_dma_start_desc(struct dma_chan *chan) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct bcm2835_desc *d; @@ -533,13 +677,14 @@ static void bcm2835_dma_start_desc(struct dma_chan *chan) c->desc = d = to_bcm2835_dma_desc(&vd->tx); - writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR); - writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); + writel(cfg->to_cb_addr(d->cb_list[0].paddr), c->chan_base + cfg->cb_reg); + writel(cfg->active_mask, c->chan_base + cfg->cs_reg); } static irqreturn_t bcm2835_dma_callback(int irq, void *data) { struct dma_chan *chan = data; + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; unsigned long flags; @@ -547,9 +692,9 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) /* check the shared interrupt */ if (c->irq_flags & IRQF_SHARED) { /* check if the interrupt is enabled */ - flags = readl(c->chan_base + BCM2835_DMA_CS); + flags = readl(c->chan_base + cfg->cs_reg); /* if not set then we are not the reason for the irq */ - if (!(flags & BCM2835_DMA_INT)) + if (!(flags & cfg->int_mask)) return IRQ_NONE; } @@ -562,8 +707,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) * if this IRQ handler is threaded.) If the channel is finished, it * will remain idle despite the ACTIVE flag being set. */ - writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE, - c->chan_base + BCM2835_DMA_CS); + writel(cfg->int_mask | cfg->active_mask, c->chan_base + cfg->cs_reg); d = c->desc; @@ -571,7 +715,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) if (d->cyclic) { /* call the cyclic callback */ vchan_cyclic_callback(&d->vd); - } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) { + } else if (!readl(c->chan_base + cfg->cb_reg)) { vchan_cookie_complete(&c->desc->vd); bcm2835_dma_start_desc(chan); } @@ -594,7 +738,7 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) * (32 byte) aligned address (BCM2835 ARM Peripherals, sec. 4.2.1.1). */ c->cb_pool = dma_pool_create(dev_name(dev), dev, - sizeof(struct bcm2835_dma_cb), 32, 0); + sizeof(struct bcm_dma_cb), 32, 0); if (!c->cb_pool) { dev_err(dev, "unable to allocate descriptor pool\n"); return -ENOMEM; @@ -620,20 +764,16 @@ static size_t bcm2835_dma_desc_size(struct bcm2835_desc *d) return d->size; } -static size_t bcm2835_dma_desc_size_pos(struct bcm2835_desc *d, dma_addr_t addr) +static size_t bcm2835_dma_desc_size_pos(const struct bcm2835_dma_cfg *cfg, + struct bcm2835_desc *d, dma_addr_t addr) { unsigned int i; size_t size; for (size = i = 0; i < d->frames; i++) { - struct bcm2835_dma_cb *control_block = d->cb_list[i].cb; - size_t this_size = control_block->length; - dma_addr_t dma; - - if (d->dir == DMA_DEV_TO_MEM) - dma = control_block->dst; - else - dma = control_block->src; + struct bcm_dma_cb *control_block = d->cb_list[i].cb; + size_t this_size = cfg->cb_get_length(control_block); + dma_addr_t dma = cfg->cb_get_addr(control_block, d->dir); if (size) size += this_size; @@ -647,6 +787,7 @@ static size_t bcm2835_dma_desc_size_pos(struct bcm2835_desc *d, dma_addr_t addr) static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct virt_dma_desc *vd; enum dma_status ret; @@ -665,14 +806,8 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, struct bcm2835_desc *d = c->desc; dma_addr_t pos; - if (d->dir == DMA_MEM_TO_DEV) - pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD); - else if (d->dir == DMA_DEV_TO_MEM) - pos = readl(c->chan_base + BCM2835_DMA_DEST_AD); - else - pos = 0; - - txstate->residue = bcm2835_dma_desc_size_pos(d, pos); + pos = cfg->read_addr(c, d->dir); + txstate->residue = bcm2835_dma_desc_size_pos(cfg, d, pos); } else { txstate->residue = 0; } @@ -725,6 +860,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( enum dma_transfer_direction direction, unsigned long flags, void *context) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src = 0, dst = 0; @@ -739,11 +875,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( if (direction == DMA_DEV_TO_MEM) { if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; - src = c->cfg.src_addr; + src = cfg->addr_offset + c->cfg.src_addr; } else { if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; - dst = c->cfg.dst_addr; + dst = cfg->addr_offset + c->cfg.dst_addr; } /* count frames in sg list */ @@ -767,6 +903,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction direction, unsigned long flags) { + const struct bcm2835_dma_cfg *cfg = to_bcm2835_cfg(chan->device); struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_desc *d; dma_addr_t src, dst; @@ -800,12 +937,12 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( if (direction == DMA_DEV_TO_MEM) { if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; - src = c->cfg.src_addr; + src = cfg->addr_offset + c->cfg.src_addr; dst = buf_addr; } else { if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) return NULL; - dst = c->cfg.dst_addr; + dst = cfg->addr_offset + c->cfg.dst_addr; src = buf_addr; } @@ -826,7 +963,8 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( return NULL; /* wrap around into a loop */ - d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr; + cfg->cb_set_next(d->cb_list[d->frames - 1].cb, + cfg->to_cb_addr(d->cb_list[0].paddr)); return vchan_tx_prep(&c->vc, &d->vd, flags); } @@ -887,10 +1025,7 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, c->irq_number = irq; c->irq_flags = irq_flags; - /* check in DEBUG register if this is a LITE channel */ - if (readl(c->chan_base + BCM2835_DMA_DEBUG) & - BCM2835_DMA_DEBUG_LITE) - c->is_lite_channel = true; + d->cfg->chan_plat_init(c); return 0; } @@ -909,8 +1044,34 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od) DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); } +static const struct bcm2835_dma_cfg bcm2835_data = { + .addr_offset = 0, + + .cs_reg = BCM2835_DMA_CS, + .cb_reg = BCM2835_DMA_ADDR, + + .wait_mask = BCM2835_DMA_WAITING_FOR_WRITES, + .reset_mask = BCM2835_DMA_RESET, + .int_mask = BCM2835_DMA_INT, + .active_mask = BCM2835_DMA_ACTIVE, + + .cb_get_length = bcm2835_dma_cb_get_length, + .cb_get_addr = bcm2835_dma_cb_get_addr, + .cb_init = bcm2835_dma_cb_init, + .cb_set_src = bcm2835_dma_cb_set_src, + .cb_set_dst = bcm2835_dma_cb_set_dst, + .cb_set_next = bcm2835_dma_cb_set_next, + .cb_set_length = bcm2835_dma_cb_set_length, + .cb_append_extra = bcm2835_dma_cb_append_extra, + + .to_cb_addr = bcm2835_dma_to_cb_addr, + + .chan_plat_init = bcm2835_dma_chan_plat_init, + .read_addr = bcm2835_dma_read_addr, +}; + static const struct of_device_id bcm2835_dma_of_match[] = { - { .compatible = "brcm,bcm2835-dma", }, + { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_data }, {}, }; MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match); @@ -933,6 +1094,7 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec, static int bcm2835_dma_probe(struct platform_device *pdev) { + const struct of_device_id *of_id; struct bcm2835_dmadev *od; struct resource *res; void __iomem *base; @@ -943,6 +1105,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev) uint32_t chans_available; char chan_name[BCM2835_DMA_CHAN_NAME_SIZE]; + of_id = of_match_node(bcm2835_dma_of_match, pdev->dev.of_node); + if (!of_id) + return -EINVAL; + if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; @@ -964,6 +1130,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) return PTR_ERR(base); od->base = base; + od->cfg = of_id->data; dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); From patchwork Mon Dec 27 12:06:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 528340 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8BBBAC433F5 for ; Mon, 27 Dec 2021 12:07:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236592AbhL0MHV (ORCPT ); Mon, 27 Dec 2021 07:07:21 -0500 Received: from mout.kundenserver.de ([217.72.192.74]:52615 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236580AbhL0MHU (ORCPT ); Mon, 27 Dec 2021 07:07:20 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MjSDU-1mZal80xJa-00kvYa; Mon, 27 Dec 2021 13:07:04 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Date: Mon, 27 Dec 2021 13:06:51 +0100 Message-Id: <1640606812-11110-1-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 X-Provags-ID: V03:K1:FKTE3QBORw5hEsQfHD79ClFMhoD8B8l3aouZxLdKft11kB1YBEv vgwEFd8DsQrunbX5vszimlDjGKJmvKu8892KuSqeqsFreX+hFlkbyh8hX7cj6SX4owQ4AjO YnuHcg8AY8TX26AuENxXyOfLWFK7aFpjbRPPisBtFAXqcEf3GJBCroOB8cVgLmmQnd4i3or GbX1UcT8P10qVn+YMTbKw== X-UI-Out-Filterresults: notjunk:1;V03:K0:JijceJqOFOc=:jyzT1peeJ9B6syi5XO6DCh nYUUrWzf6XrlRtheM7kL8XvbaJZTpwgLoMBsT+UoBV+5kg4d/wVnxhJiQCqcXie/OKP2Hd0GZ Q8oFnk5MYaB7KflnhHpVGgd6zBJ16BVn6UrVvmYPiI3Px/s5epkjoVwlxlpfnidJyMrn2F4Np UWxrbS0Yoh+16IZ+200DH/nd9EoYghS5yYf2SSvGRdz0YTE/xmlTfLSh/3GijvuOQheRqUHnv 3HAKN3WBCGD9OyvTrZTs207Jpr+txmv30KhB7mnvYWgbjQ3Q0yQfIqH/jKxG1BRHXI7o7tgPU dymzP2PQeZFXqwqofE651z0PSWQoDFRsXeLo60jeMXpwPuHBBzYeH0F5ia2O1YIfjMJlS8c93 LERU1abstOZR+3TOiplAqUnmcPUCUNXoBX0gy3jIu/i7eLmTpuw3pniZ8nibxsS/MEnhIP5ui WL9gToQDc3pBJKU9mFiiaU9glSj56X8k8NSrjZgNK8w1gbGPJCOwTL7kpK96s5gO5bJYtZ54L jGAG4lpwpLwKJFu9R8RYRwbfyoEvkH1CKrKTcCgpuOihZbAb0kVAw4avztVUKF30M3ZTfQaBm 1wVN0Tv3+by6yApDqANm2Fs7d9ptn3t22e+N9kOLBYSbiFaDmsImOqku+tuEz0EKx/SizEbYi DzlgMXUkwdv+sw/jKZCnBOL7ZK5PUY1MJkTcUkSYTGpPhnvDE6i299nJkBhRdyCzkU7RUfw+m Y3qxzJtAv6dRmLsQ Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org BCM2711 has 4 DMA channels with a 40-bit address range, allowing them to access the full 4GB of memory on a Pi 4. Assume every channel is capable of 40-bit address range. Signed-off-by: Stefan Wahren --- drivers/dma/bcm2835-dma.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 7159fa2..83343f9 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -36,6 +36,7 @@ #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 #define BCM2835_DMA_CHAN_NAME_SIZE 8 +#define BCM2711_DMA40_PHYS_ADDR 0x400000000ULL /** * struct bcm2835_dmadev - BCM2835 DMA controller @@ -65,6 +66,17 @@ struct bcm2835_dma_cb { uint32_t pad[2]; }; +struct bcm2711_dma40_scb { + uint32_t ti; + uint32_t src; + uint32_t srci; + uint32_t dst; + uint32_t dsti; + uint32_t len; + uint32_t next_cb; + uint32_t rsvd; +}; + struct bcm2835_cb_entry { struct bcm_dma_cb *cb; dma_addr_t paddr; @@ -205,6 +217,49 @@ struct bcm2835_desc { #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) +/* 40-bit DMA support */ +#define BCM2711_DMA40_CS 0x00 +#define BCM2711_DMA40_CB 0x04 +#define BCM2711_DMA40_DEBUG 0x0c +#define BCM2711_DMA40_TI 0x10 +#define BCM2711_DMA40_SRC 0x14 +#define BCM2711_DMA40_SRCI 0x18 +#define BCM2711_DMA40_DEST 0x1c +#define BCM2711_DMA40_DESTI 0x20 +#define BCM2711_DMA40_LEN 0x24 +#define BCM2711_DMA40_NEXT_CB 0x28 +#define BCM2711_DMA40_DEBUG2 0x2c + +#define BCM2711_DMA40_ACTIVE BIT(0) +#define BCM2711_DMA40_END BIT(1) +#define BCM2711_DMA40_INT BIT(2) +#define BCM2711_DMA40_DREQ BIT(3) /* DREQ state */ +#define BCM2711_DMA40_RD_PAUSED BIT(4) /* Reading is paused */ +#define BCM2711_DMA40_WR_PAUSED BIT(5) /* Writing is paused */ +#define BCM2711_DMA40_DREQ_PAUSED BIT(6) /* Is paused by DREQ flow control */ +#define BCM2711_DMA40_WAITING_FOR_WRITES BIT(7) /* Waiting for last write */ +#define BCM2711_DMA40_ERR BIT(10) +#define BCM2711_DMA40_QOS(x) (((x) & 0x1f) << 16) +#define BCM2711_DMA40_PANIC_QOS(x) (((x) & 0x1f) << 20) +#define BCM2711_DMA40_WAIT_FOR_WRITES BIT(28) +#define BCM2711_DMA40_DISDEBUG BIT(29) +#define BCM2711_DMA40_ABORT BIT(30) +#define BCM2711_DMA40_HALT BIT(31) + +/* Transfer information bits */ +#define BCM2711_DMA40_INTEN BIT(0) +#define BCM2711_DMA40_TDMODE BIT(1) /* 2D-Mode */ +#define BCM2711_DMA40_WAIT_RESP BIT(2) /* wait for AXI write to be acked */ +#define BCM2711_DMA40_WAIT_RD_RESP BIT(3) /* wait for AXI read to complete */ +#define BCM2711_DMA40_PER_MAP(x) ((x & 31) << 9) /* REQ source */ +#define BCM2711_DMA40_S_DREQ BIT(14) /* enable SREQ for source */ +#define BCM2711_DMA40_D_DREQ BIT(15) /* enable DREQ for destination */ +#define BCM2711_DMA40_S_WAIT(x) ((x & 0xff) << 16) /* add DMA read-wait cycles */ +#define BCM2711_DMA40_D_WAIT(x) ((x & 0xff) << 24) /* add DMA write-wait cycles */ + +#define BCM2711_DMA40_INC BIT(12) +#define BCM2711_DMA40_IGNORE BIT(15) + /* the max dma length for different channels */ #define MAX_DMA_LEN SZ_1G #define MAX_LITE_DMA_LEN (SZ_64K - 4) @@ -297,6 +352,53 @@ static u32 bcm2835_dma_prepare_cb_extra(struct bcm2835_chan *c, return result; } +static u32 bcm2711_dma_prepare_cb_info(struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool zero_page) +{ + u32 result; + + if (direction == DMA_MEM_TO_MEM) + return 0; + + result = BCM2711_DMA40_WAIT_RESP; + + /* Setup DREQ channel */ + if (c->dreq != 0) + result |= BCM2711_DMA40_PER_MAP(c->dreq); + + if (direction == DMA_DEV_TO_MEM) { + result |= BCM2711_DMA40_S_DREQ | BCM2711_DMA40_WAIT_RD_RESP; + } else { + result |= BCM2711_DMA40_D_DREQ; + } + + return result; +} + +static u32 bcm2711_dma_prepare_cb_extra(struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool cyclic, bool final, + unsigned long flags) +{ + u32 result = 0; + + if (cyclic) { + if (flags & DMA_PREP_INTERRUPT) + result |= BCM2711_DMA40_INTEN; + } else { + if (!final) + return 0; + + result |= BCM2711_DMA40_INTEN; + + if (direction == DMA_MEM_TO_MEM) + result |= BCM2711_DMA40_WAIT_RESP; + } + + return result; +} + static inline bool need_src_incr(enum dma_transfer_direction direction) { return direction != DMA_DEV_TO_MEM; @@ -413,6 +515,120 @@ static dma_addr_t bcm2835_dma_read_addr(struct bcm2835_chan *c, return 0; } +static inline u32 bcm2711_dma_cb_get_length(void *data) +{ + struct bcm2711_dma40_scb *scb = data; + + return scb->len; +} + +static inline dma_addr_t +bcm2711_dma_cb_get_addr(void *data, enum dma_transfer_direction direction) +{ + struct bcm2711_dma40_scb *scb = data; + + if (direction == DMA_DEV_TO_MEM) + return scb->dst + ((scb->dsti & 0xff) << 8); + + return scb->src + ((scb->srci & 0xff) << 8); +} + +static inline void +bcm2711_dma_cb_init(void *data, struct bcm2835_chan *c, + enum dma_transfer_direction direction, u32 src, u32 dst, + bool zero_page) +{ + struct bcm2711_dma40_scb *scb = data; + + scb->ti = bcm2711_dma_prepare_cb_info(c, direction, zero_page); + scb->src = lower_32_bits(src); + scb->srci = upper_32_bits(src); + + if (need_src_incr(direction)) + scb->srci |= BCM2711_DMA40_INC; + + scb->dst = lower_32_bits(dst); + scb->dsti = upper_32_bits(dst); + + if (need_dst_incr(direction)) + scb->dsti |= BCM2711_DMA40_INC; + + scb->next_cb = 0; +} + +static inline void +bcm2711_dma_cb_set_src(void *data, enum dma_transfer_direction direction, + u32 src) +{ + struct bcm2711_dma40_scb *scb = data; + + scb->src = lower_32_bits(src); + scb->srci = upper_32_bits(src); + + if (need_src_incr(direction)) + scb->srci |= BCM2711_DMA40_INC; +} + +static inline void +bcm2711_dma_cb_set_dst(void *data, enum dma_transfer_direction direction, + u32 dst) +{ + struct bcm2711_dma40_scb *scb = data; + + scb->dst = lower_32_bits(dst); + scb->dsti = upper_32_bits(dst); + + if (need_dst_incr(direction)) + scb->dsti |= BCM2711_DMA40_INC; +} + +static inline void bcm2711_dma_cb_set_next(void *data, u32 next) +{ + struct bcm2711_dma40_scb *scb = data; + + scb->next_cb = next; +} + +static inline void bcm2711_dma_cb_set_length(void *data, u32 length) +{ + struct bcm2711_dma40_scb *scb = data; + + scb->len = length; +} + +static inline void +bcm2711_dma_cb_append_extra(void *data, struct bcm2835_chan *c, + enum dma_transfer_direction direction, + bool cyclic, bool final, unsigned long flags) +{ + struct bcm2711_dma40_scb *scb = data; + + scb->ti |= bcm2711_dma_prepare_cb_extra(c, direction, cyclic, final, + flags); +} + +static inline dma_addr_t bcm2711_dma_to_cb_addr(dma_addr_t addr) +{ + return (addr >> 5); +} + +static void bcm2711_dma_chan_plat_init(struct bcm2835_chan *c) +{ +} + +static dma_addr_t bcm2711_dma_read_addr(struct bcm2835_chan *c, + enum dma_transfer_direction direction) +{ + if (direction == DMA_MEM_TO_DEV) + return readl(c->chan_base + BCM2711_DMA40_SRC) + + ((readl(c->chan_base + BCM2711_DMA40_SRCI) & 0xff) << 8); + else if (direction == DMA_DEV_TO_MEM) + return readl(c->chan_base + BCM2711_DMA40_DEST) + + ((readl(c->chan_base + BCM2711_DMA40_DESTI) & 0xff) << 8); + + return 0; +} + static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) { size_t i; @@ -1070,8 +1286,35 @@ static const struct bcm2835_dma_cfg bcm2835_data = { .read_addr = bcm2835_dma_read_addr, }; +static const struct bcm2835_dma_cfg bcm2711_data = { + .addr_offset = BCM2711_DMA40_PHYS_ADDR, + + .cs_reg = BCM2711_DMA40_CS, + .cb_reg = BCM2711_DMA40_CB, + + .wait_mask = BCM2711_DMA40_WAITING_FOR_WRITES, + .reset_mask = BCM2711_DMA40_HALT, + .int_mask = BCM2711_DMA40_INTEN, + .active_mask = BCM2711_DMA40_ACTIVE, + + .cb_get_length = bcm2711_dma_cb_get_length, + .cb_get_addr = bcm2711_dma_cb_get_addr, + .cb_init = bcm2711_dma_cb_init, + .cb_set_src = bcm2711_dma_cb_set_src, + .cb_set_dst = bcm2711_dma_cb_set_dst, + .cb_set_next = bcm2711_dma_cb_set_next, + .cb_set_length = bcm2711_dma_cb_set_length, + .cb_append_extra = bcm2711_dma_cb_append_extra, + + .to_cb_addr = bcm2711_dma_to_cb_addr, + + .chan_plat_init = bcm2711_dma_chan_plat_init, + .read_addr = bcm2711_dma_read_addr, +}; + static const struct of_device_id bcm2835_dma_of_match[] = { { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_data }, + { .compatible = "brcm,bcm2711-dma", .data = &bcm2711_data }, {}, }; MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match); From patchwork Mon Dec 27 12:06:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 529410 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1810C433FE for ; Mon, 27 Dec 2021 12:07:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236586AbhL0MHT (ORCPT ); Mon, 27 Dec 2021 07:07:19 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:46457 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236580AbhL0MHS (ORCPT ); Mon, 27 Dec 2021 07:07:18 -0500 Received: from localhost.localdomain ([37.4.249.169]) by mrelayeu.kundenserver.de (mreue108 [212.227.15.183]) with ESMTPSA (Nemesis) id 1Mirb8-1mXzoK2zJM-00erHu; Mon, 27 Dec 2021 13:07:04 +0100 From: Stefan Wahren To: Vinod Koul , Rob Herring , Florian Fainelli , Nicolas Saenz Julienne Cc: Ray Jui , Scott Branden , bcm-kernel-feedback-list@broadcom.com, dmaengine@vger.kernel.org, Phil Elwell , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Lukas Wunner , linux-rpi-kernel@lists.infradead.org, Stefan Wahren Subject: [PATCH RFC 11/11] ARM: dts: bcm2711: add bcm2711-dma node Date: Mon, 27 Dec 2021 13:06:52 +0100 Message-Id: <1640606812-11110-2-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640606812-11110-1-git-send-email-stefan.wahren@i2se.com> References: <1640606812-11110-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K1:U3nO36HzZGXq40n9R882naHiNjUl4oAFLiWYXZZHkaUh42dvvLS burphzCrKM4DScfSiS/mZaIkh+uybGI1l2APtf1yp9EoWu0+1FY/9Ry/OPB2kmcRbGK4WEa ndQURDst4PiujCCqJSeJGfu5+BNnHwBVdfuFSMIwLx/YjacYrvvpctnSy4Xpcma2qJ9qrAX C6uiZeOtSxYEys3O9MIdA== X-UI-Out-Filterresults: notjunk:1;V03:K0:PcMir07Pc54=:bxIJKo2MiIwel1ZhW6jVx5 e8W38T1FRN+TR0DUfVTqJNCcq4sZ18dUnvBpn0tQz41g4qmNg52LH3/xa4JhgnlF582q6dbYw KYX1R8UcQxW85FjugCnqn3AEX9uEk/QDGQx07FDg1UHXITPDlC6AYbVK96A2VNYCw1wqSRoqs p3z+1pEi6fYIv0wGedFrsmQXCweu5BoiupAV0UTd3cnCt6yAfQCIGXvXq4SrTywFiosFVi4Hx f0LWr2aA4dYS2VZ7xYgkRiZQDlDKQOKLzsS2J9cVWj6ba7rYwnxnsXkyfsz0t+e6AmdXTS96D TZlesK47HWeSJ8EWounZTgHaYyd2U6dMWQz6S5kaPVtUTxFRE+6ObJuTLoQ7R+y2xuj+yBYNv Ld9Wvo8xegHoa+ws12LL2lKucFn7f0QpQfzO7a+Alr10N/4yYcQtlAiVRk5Tz0CmEu71RMUfb j6QQm+Yrtzy57pRI/RPdXb8bZhWuXk/ruZBuocVcnMj4n/hFTQAXXDfmPsBjV4/YgdCXuAHIP jsJyXtm0xZHchTSUVxnDujGVRKwUwsCc74ptcEnw07ZRPRezn3vips9TtGupRnkXY4m0Oe3hV ImhGcrhEScceH1pa0Q+2ANQ5I4ER+dIQ/SrX2a9SkdCj/aC+if6O5XUG77ClLZoRMvXNlduWi WF48MEk8YTZZrqFO/iw3/899Es5JBVzNT340L0fkmr3t/BYAjE/muLJFXdkujchIFqDEpzdaz Zlx4qJWgfcsUgkqE Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org BCM2711 has 4 DMA channels with a 40-bit address range, allowing them to access the full 4GB of memory on a Pi 4. Not sure which adjustments to the parent node (scb) are required. Signed-off-by: Stefan Wahren --- arch/arm/boot/dts/bcm2711.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi index 590068b..12f373b 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -536,6 +536,22 @@ #size-cells = <0x1>; }; }; + + dma40: dma-controller@7e007b00 { + compatible = "brcm,bcm2711-dma"; + reg = <0x0 0x7e007b00 0x400>; + interrupts = , /* dma4 11 */ + , /* dma4 12 */ + , /* dma4 13 */ + ; /* dma4 14 */ + interrupt-names = "dma11", + "dma12", + "dma13", + "dma14"; + #dma-cells = <1>; + /* The VPU firmware uses DMA channel 11 for VCHIQ */ + brcm,dma-channel-mask = <0x7000>; + }; }; };