* Re: [PATCH 6.6 000/175] 6.6.131-rc1 review
From: Jon Hunter @ 2026-04-01 9:19 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr,
linux-tegra, stable
In-Reply-To: <20260331161729.779738837@linuxfoundation.org>
On Tue, 31 Mar 2026 18:19:44 +0200, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 6.6.131 release.
> There are 175 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 02 Apr 2026 16:16:56 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.6.131-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.6.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
All tests passing for Tegra ...
Test results for stable-v6.6:
11 builds: 11 pass, 0 fail
28 boots: 28 pass, 0 fail
133 tests: 133 pass, 0 fail
Linux version: 6.6.131-rc1-g616fc3cb7c95
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra186-p3509-0000+p3636-0001, tegra194-p2972-0000,
tegra194-p3509-0000+p3668-0000, tegra20-ventana,
tegra210-p2371-2180, tegra210-p3450-0000,
tegra234-p3737-0000+p3701-0000, tegra30-cardhu-a04
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Jon
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: timestamp: Add Tegra264 support
From: Krzysztof Kozlowski @ 2026-04-01 7:52 UTC (permalink / raw)
To: Suneel Garapati, linux-tegra
In-Reply-To: <20260331200454.186649-1-suneelg@nvidia.com>
On 31/03/2026 22:04, Suneel Garapati wrote:
> Add timestamp provider support for the Tegra264 in devicetree
> bindings. Tegra264 has two generic timestamping engines (GTE)
> which are the always-on GTE (AON) and legacy interrupt
> controller (LIC) GTE.
Please use scripts/get_maintainers.pl to get a list of necessary people
and lists to CC. It might happen, that command when run on an older
kernel, gives you outdated entries. Therefore please be sure you base
your patches on recent Linux kernel.
Tools like b4 or scripts/get_maintainer.pl provide you proper list of
people, so fix your workflow. Tools might also fail if you work on some
ancient tree (don't, instead use mainline) or work on fork of kernel
(don't, instead use mainline). Just use b4 and everything should be
fine, although remember about `b4 prep --auto-to-cc` if you added new
patches to the patchset.
You missed at least devicetree list (maybe more), so this won't be
tested by automated tooling. Performing review on untested code might be
a waste of time.
Please kindly resend and include all necessary To/Cc entries.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH 1/3] dt-bindings: timestamp: Add Tegra264 support
From: Suneel Garapati @ 2026-03-31 20:04 UTC (permalink / raw)
To: linux-tegra; +Cc: Suneel Garapati
Add timestamp provider support for the Tegra264 in devicetree
bindings. Tegra264 has two generic timestamping engines (GTE)
which are the always-on GTE (AON) and legacy interrupt
controller (LIC) GTE.
Signed-off-by: Suneel Garapati <suneelg@nvidia.com>
---
.../devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml b/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
index 456797967adc..210200421a38 100644
--- a/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
+++ b/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
@@ -25,6 +25,8 @@ properties:
- nvidia,tegra194-gte-lic
- nvidia,tegra234-gte-aon
- nvidia,tegra234-gte-lic
+ - nvidia,tegra264-gte-aon
+ - nvidia,tegra264-gte-lic
reg:
maxItems: 1
@@ -112,6 +114,7 @@ allOf:
contains:
enum:
- nvidia,tegra234-gte-aon
+ - nvidia,tegra264-gte-aon
then:
required:
- nvidia,gpio-controller
--
2.34.1
^ permalink raw reply related
* Re: [PATCH rc 1/2] iommu: Do not call drivers for empty gathers
From: Jason Gunthorpe @ 2026-03-31 19:58 UTC (permalink / raw)
To: Jon Hunter
Cc: iommu, Joerg Roedel, Robin Murphy, Will Deacon, Alejandro Jimenez,
Janusz Krzysztofik, Joerg Roedel, Kevin Tian, Pasha Tatashin,
patches, Samiullah Khawaja, stable, linux-tegra@vger.kernel.org
In-Reply-To: <8800a38b-8515-4bbe-af15-0dae81274bf7@nvidia.com>
On Tue, Mar 31, 2026 at 06:12:18PM +0100, Jon Hunter wrote:
> I noticed that a couple of our Tegra boards are no longer booting -next and
> bisect pointed to this commit. Reverting this does fix it.
>
> This is impacting our Tegra186 (using nvidia,tegra186-smmu compatible
> string) and Tegra194 (using nvidia,tegra194-smmu compatible string) boards.
> There is no specific crash I see, but the boards just appear to hang on
> boot. If you have any thoughts or things to try let me know.
Thanks, I was able to guess what the problem is:
https://patch.msgid.link/r/0-v1-664d3acaabb9+78b-iommu_gather_always_jgg@nvidia.com
Please let me know if it doesn't solve the problem
Jason
^ permalink raw reply
* Re: [PATCH 3/3] arm64: tegra: Add GTE nodes for Tegra264
From: Dipen Patel @ 2026-03-31 19:33 UTC (permalink / raw)
To: Suneel Garapati, jonathanh, thierry.reding, krzk+dt, conor+dt,
amhetre, sheetal, kkarthik, timestamp, devicetree, linux-tegra,
linux-kernel, robh
In-Reply-To: <20260330170657.185854-4-suneelg@nvidia.com>
On 3/30/26 10:06 AM, Suneel Garapati wrote:
> Add AON GPIO and system LIC GTE instances for Tegra264.
>
> Signed-off-by: Suneel Garapati <suneelg@nvidia.com>
> ---
> arch/arm64/boot/dts/nvidia/tegra264.dtsi | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
> index 7644a41d5f72..9b1aa69d4a79 100644
> --- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi
> +++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
> @@ -3207,6 +3207,15 @@ agic_page5: interrupt-controller@99b0000 {
> };
> };
>
> + hte_lic: hardware-timestamp@8380000 {
> + compatible = "nvidia,tegra264-gte-lic";
> + reg = <0x0 0x08380000 0x0 0x10000>;
> + interrupts = <GIC_SPI 0x00000268 IRQ_TYPE_LEVEL_HIGH>;
> + nvidia,int-threshold = <1>;
> + #timestamp-cells = <1>;
> + status = "disabled";
> + };
> +
> gpcdma: dma-controller@8400000 {
> compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma";
> reg = <0x0 0x08400000 0x0 0x210000>;
> @@ -3267,6 +3276,16 @@ hsp_top: hsp@8800000 {
> #mbox-cells = <2>;
> };
>
> + hte_aon: hardware-timestamp@c2b0000 {
> + compatible = "nvidia,tegra264-gte-aon";
> + reg = <0x0 0x0c2b0000 0x0 0x10000>;
> + interrupts = <GIC_SPI 0x00000226 IRQ_TYPE_LEVEL_HIGH>;
> + nvidia,int-threshold = <1>;
> + #timestamp-cells = <1>;
> + nvidia,gpio-controller = <&gpio_aon>;
> + status = "disabled";
> + };
> +
> rtc: rtc@c2c0000 {
> compatible = "nvidia,tegra264-rtc", "nvidia,tegra20-rtc";
> reg = <0x0 0x0c2c0000 0x0 0x10000>;
Reviewed-by: Dipen Patel <dipenp@nvidia.com>
^ permalink raw reply
* Re: [PATCH v6 00/10] Add GPCDMA support in Tegra264
From: Jon Hunter @ 2026-03-31 18:06 UTC (permalink / raw)
To: Akhil R, Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Laxman Dewangan, Philipp Zabel,
dmaengine, devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
On 31/03/2026 11:22, Akhil R wrote:
> This series adds support for GPCDMA in Tegra264 with additional
> support for separate stream ID for each channel. Tegra264 GPCDMA
> controller has changes in the register offsets and uses 41-bit
> addressing for memory. Add changes in the tegra186-gpc-dma driver
> to support these.
>
> v5->v6:
> - Replace dev_err() with dev_err_probe() in the probe function for fixed
> return values also.
> v4->v5:
> - Use dev_err_probe() when returning error from the probe function.
> - Remove tegra194 and tegra234 compatible from the reset 'if' condition
> in the bindings as suggested in v2 (which I missed).
> v3->v4:
> - Split device tree changes to two patches.
> - Reordered patches to have fixes first.
> - Added fixes tag to dt-bindings and device tree changes.
> v2->v3:
> - Add description for iommu-map property and update commit descriptions.
> - Use enum for compatible string instead of const.
> - Remove unused registers from struct tegra_dma_channel_regs.
> - Use devm_of_dma_controller_register() to register the DMA controller.
> - Remove return value check for mask setting in the driver as the bitmask
> value is always greater than 32.
> v1->v2:
> - Fix dt_bindings_check warnings
> - Drop fallback compatible "nvidia,tegra186-gpcdma" from Tegra264 DT
> - Use dma_addr_t for sg_req src/dst fields and drop separate high_add
> variable and check for the addr_bits only when programming the
> registers.
> - Update address width to 39 bits for Tegra234 and before since the SMMU
> supports only up to 39 bits till Tegra234.
> - Add a patch to do managed DMA controller registration.
> - Describe the second iteration in the probe.
> - Update commit descriptions.
>
> Akhil R (10):
> dt-bindings: dma: nvidia,tegra186-gpc-dma: Make reset optional
> arm64: tegra: Remove fallback compatible for GPCDMA
> dt-bindings: dma: nvidia,tegra186-gpc-dma: Add iommu-map property
> dmaengine: tegra: Make reset control optional
> dmaengine: tegra: Use struct for register offsets
> dmaengine: tegra: Support address width > 39 bits
> dmaengine: tegra: Use managed DMA controller registration
> dmaengine: tegra: Use iommu-map for stream ID
> dmaengine: tegra: Add Tegra264 support
> arm64: tegra: Enable GPCDMA in Tegra264 and add iommu-map
>
> .../bindings/dma/nvidia,tegra186-gpc-dma.yaml | 32 +-
> .../arm64/boot/dts/nvidia/tegra264-p3834.dtsi | 4 +
> arch/arm64/boot/dts/nvidia/tegra264.dtsi | 3 +-
> drivers/dma/tegra186-gpc-dma.c | 429 +++++++++++-------
> 4 files changed, 284 insertions(+), 184 deletions(-)
>
For the series ...
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Thanks!
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH 2/3] hte: tegra194: Add Tegra264 GTE support
From: Dipen Patel @ 2026-03-31 17:35 UTC (permalink / raw)
To: Krzysztof Kozlowski, Suneel Garapati, jonathanh, thierry.reding,
krzk+dt, conor+dt, amhetre, sheetal, kkarthik, timestamp,
devicetree, linux-tegra, linux-kernel, robh
In-Reply-To: <0cc95f5e-a5c7-498f-ae2e-32017141b619@kernel.org>
On 3/30/26 12:33 PM, Krzysztof Kozlowski wrote:
> On 30/03/2026 21:32, Dipen Patel wrote:
>> On 3/30/26 11:39 AM, Krzysztof Kozlowski wrote:
>>> On 30/03/2026 20:35, Dipen Patel wrote:
>>>>> MODULE_DEVICE_TABLE(of, tegra_hte_of_match);
>>>
>>> Please kindly trim the replies from unnecessary context. It makes it
>>> much easier to find new content.
>>>
>>>> Acked-by: Dipen Patel <dipenp@nvidia.com>
>>>> Signed-off-by: Dipen Patel <dipenp@nvidia.com>
>>>
>>> What are you certifying here with SoB?
>> I was preemptively adding my SoB since I had to integrate this patch into my HTE
>> subsystem tree. But for now, please ignore my SoB.
>
> So you wanted to say that you applied a patch? Why not sending ty
> letters with b4?
Please ignore my SoB and consider that as a mistake.
>
> Best regards,
> Krzysztof
^ permalink raw reply
* Re: [PATCH rc 1/2] iommu: Do not call drivers for empty gathers
From: Jon Hunter @ 2026-03-31 17:12 UTC (permalink / raw)
To: Jason Gunthorpe, iommu, Joerg Roedel, Robin Murphy, Will Deacon
Cc: Alejandro Jimenez, Janusz Krzysztofik, Joerg Roedel, Kevin Tian,
Pasha Tatashin, patches, Samiullah Khawaja, stable,
linux-tegra@vger.kernel.org
In-Reply-To: <1-v1-13a02eb0e031+a5-iommu_gather_jgg@nvidia.com>
Hi Jason,
On 02/03/2026 22:22, Jason Gunthorpe wrote:
> An empty gather is coded with start=U64_MAX, end=0 and several drivers go
> on to convert that to a size with:
>
> end - start + 1
>
> Which gives 2 for an empty gather. This then causes Weird Stuff to
> happen (for example an UBSAN splat in VT-d) that is hopefully harmless,
> but maybe not.
>
> Prevent drivers from being called right in iommu_iotlb_sync().
>
> Auditing shows that AMD, Intel, Mediatek and RSIC-V drivers all do things
> on these empty gathers.
>
> Further, there are several callers that can trigger empty gathers,
> especially in unusual conditions. For example iommu_map_nosync() will call
> a 0 size unmap on some error paths. Also in VFIO, iommupt and other
> places.
>
> Cc: stable@vger.kernel.org
> Reported-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
> Closes: https://lore.kernel.org/r/11145826.aFP6jjVeTY@jkrzyszt-mobl2.ger.corp.intel.com
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
> include/linux/iommu.h | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index 54b8b48c762e88..555597b54083cd 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -980,7 +980,8 @@ static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
> static inline void iommu_iotlb_sync(struct iommu_domain *domain,
> struct iommu_iotlb_gather *iotlb_gather)
> {
> - if (domain->ops->iotlb_sync)
> + if (domain->ops->iotlb_sync &&
> + likely(iotlb_gather->start < iotlb_gather->end))
> domain->ops->iotlb_sync(domain, iotlb_gather);
>
> iommu_iotlb_gather_init(iotlb_gather);
I noticed that a couple of our Tegra boards are no longer booting -next
and bisect pointed to this commit. Reverting this does fix it.
This is impacting our Tegra186 (using nvidia,tegra186-smmu compatible
string) and Tegra194 (using nvidia,tegra194-smmu compatible string)
boards. There is no specific crash I see, but the boards just appear to
hang on boot. If you have any thoughts or things to try let me know.
Thanks!
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH v6 08/10] dmaengine: tegra: Use iommu-map for stream ID
From: Frank Li @ 2026-03-31 14:12 UTC (permalink / raw)
To: Akhil R
Cc: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260331102303.33181-9-akhilrajeev@nvidia.com>
On Tue, Mar 31, 2026 at 03:53:01PM +0530, Akhil R wrote:
> Use 'iommu-map', when provided, to get the stream ID to be programmed
> for each channel. Iterate over the channels registered and configure
> each channel device separately using of_dma_configure_id() to allow
> it to use a separate IOMMU domain for the transfer. However, do this
> in a second loop since the first loop populates the DMA device channels
> list and async_device_register() registers the channels. Both are
> prerequisites for using the channel device in the next loop.
>
> Channels will continue to use the same global stream ID if the
> 'iommu-map' property is not present in the device tree.
>
> Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/dma/tegra186-gpc-dma.c | 53 ++++++++++++++++++++++++++++------
> 1 file changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
> index 9bea2ffb3b9e..cd480d047204 100644
> --- a/drivers/dma/tegra186-gpc-dma.c
> +++ b/drivers/dma/tegra186-gpc-dma.c
> @@ -15,6 +15,7 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_dma.h>
> +#include <linux/of_device.h>
> #include <linux/platform_device.h>
> #include <linux/reset.h>
> #include <linux/slab.h>
> @@ -1380,9 +1381,13 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
> static int tegra_dma_probe(struct platform_device *pdev)
> {
> const struct tegra_dma_chip_data *cdata = NULL;
> + struct tegra_dma_channel *tdc;
> + struct tegra_dma *tdma;
> + struct dma_chan *chan;
> + struct device *chdev;
> + bool use_iommu_map = false;
> unsigned int i;
> u32 stream_id;
> - struct tegra_dma *tdma;
> int ret;
>
> cdata = of_device_get_match_data(&pdev->dev);
> @@ -1410,9 +1415,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
>
> tdma->dma_dev.dev = &pdev->dev;
>
> - if (!tegra_dev_iommu_get_stream_id(&pdev->dev, &stream_id)) {
> - dev_err(&pdev->dev, "Missing iommu stream-id\n");
> - return -EINVAL;
> + use_iommu_map = of_property_present(pdev->dev.of_node, "iommu-map");
> + if (!use_iommu_map) {
> + if (!tegra_dev_iommu_get_stream_id(&pdev->dev, &stream_id))
> + return dev_err_probe(&pdev->dev, -EINVAL, "Missing iommu stream-id\n");
> }
>
> ret = device_property_read_u32(&pdev->dev, "dma-channel-mask",
> @@ -1424,9 +1430,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
> tdma->chan_mask = TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK;
> }
>
> + /* Initialize vchan for each channel and populate the channels list */
> INIT_LIST_HEAD(&tdma->dma_dev.channels);
> for (i = 0; i < cdata->nr_channels; i++) {
> - struct tegra_dma_channel *tdc = &tdma->channels[i];
> + tdc = &tdma->channels[i];
>
> /* Check for channel mask */
> if (!(tdma->chan_mask & BIT(i)))
> @@ -1446,10 +1453,6 @@ static int tegra_dma_probe(struct platform_device *pdev)
>
> vchan_init(&tdc->vc, &tdma->dma_dev);
> tdc->vc.desc_free = tegra_dma_desc_free;
> -
> - /* program stream-id for this channel */
> - tegra_dma_program_sid(tdc, stream_id);
> - tdc->stream_id = stream_id;
> }
>
> dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(cdata->addr_bits));
> @@ -1483,6 +1486,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
> tdma->dma_dev.device_synchronize = tegra_dma_chan_synchronize;
> tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
>
> + /* Register the DMA device and the channels */
> ret = dmaenginem_async_device_register(&tdma->dma_dev);
> if (ret < 0) {
> dev_err_probe(&pdev->dev, ret,
> @@ -1490,6 +1494,37 @@ static int tegra_dma_probe(struct platform_device *pdev)
> return ret;
> }
>
> + /*
> + * Configure stream ID for each channel from the channels registered
> + * above. This is done in a separate iteration to ensure that only
> + * the channels available and registered for the DMA device are used.
> + */
> + list_for_each_entry(chan, &tdma->dma_dev.channels, device_node) {
> + chdev = &chan->dev->device;
> + tdc = to_tegra_dma_chan(chan);
> +
> + if (use_iommu_map) {
> + chdev->bus = pdev->dev.bus;
> + dma_coerce_mask_and_coherent(chdev, DMA_BIT_MASK(cdata->addr_bits));
> +
> + ret = of_dma_configure_id(chdev, pdev->dev.of_node,
> + true, &tdc->id);
> + if (ret)
> + return dev_err_probe(chdev, ret,
> + "Failed to configure IOMMU for channel %d\n", tdc->id);
> +
> + if (!tegra_dev_iommu_get_stream_id(chdev, &stream_id))
> + return dev_err_probe(chdev, -EINVAL,
> + "Failed to get stream ID for channel %d\n", tdc->id);
> +
> + chan->dev->chan_dma_dev = true;
> + }
> +
> + /* program stream-id for this channel */
> + tegra_dma_program_sid(tdc, stream_id);
> + tdc->stream_id = stream_id;
> + }
> +
> ret = devm_of_dma_controller_register(&pdev->dev, pdev->dev.of_node,
> tegra_dma_of_xlate, tdma);
> if (ret < 0) {
> --
> 2.50.1
>
^ permalink raw reply
* Re: [PATCH 0/2] memory: tegra: Add Tegra238 memory controller support
From: Krzysztof Kozlowski @ 2026-03-31 12:52 UTC (permalink / raw)
To: Ashish Mhetre, robh, conor+dt, jonathanh, sumitg
Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <cf8e568b-c349-44c6-95b4-d1b586c32805@kernel.org>
On 31/03/2026 13:39, Krzysztof Kozlowski wrote:
> On 31/03/2026 13:23, Ashish Mhetre wrote:
>> This series adds Memory Controller driver support for the Tegra238 SoC.
>>
>> Tegra238 is similar to Tegra234 but with a reduced memory controller
>> configuration featuring 8 channels instead of 16. The driver reuses
>> Tegra234 memory client IDs and ICC operations, with Tegra238-specific
>> stream IDs for SMMU configuration.
>>
>
> Thank you for the patch/patchset. My tree is currently closed for new
> features till the end of the merge window. I will review and/or apply
> the patch after the merge window. No need to resend it, I will keep this
> in my mailbox.
>
> If I misjudged this patch and this is a fix, please let me know.
And FWIW, I did take a quick look and code seemed fine, so I don't have
immediate objections.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/2] dt-bindings: memory: tegra: Add nvidia,tegra238-mc compatible
From: Jon Hunter @ 2026-03-31 12:32 UTC (permalink / raw)
To: Ashish Mhetre, krzk, robh, conor+dt, =thierry.reding, sumitg
Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <20260331112347.3897841-3-amhetre@nvidia.com>
On 31/03/2026 12:23, Ashish Mhetre wrote:
> Document the device tree binding for the Tegra238 memory controller.
> Tegra238 has 8 memory controller channels plus broadcast and stream-id
> registers.
>
> Add the stream ID header (nvidia,tegra238-mc.h) defining ISO and NISO
> stream IDs for SMMU configuration.
>
> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
> ---
> .../nvidia,tegra186-mc.yaml | 31 ++++++++
> .../dt-bindings/memory/nvidia,tegra238-mc.h | 74 +++++++++++++++++++
> 2 files changed, 105 insertions(+)
> create mode 100644 include/dt-bindings/memory/nvidia,tegra238-mc.h
>
> diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
> index 7b03b589168b..e008cb1ccd28 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
> +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
> @@ -32,6 +32,7 @@ properties:
> - nvidia,tegra186-mc
> - nvidia,tegra194-mc
> - nvidia,tegra234-mc
> + - nvidia,tegra238-mc
> - nvidia,tegra264-mc
>
> reg:
> @@ -266,6 +267,36 @@ allOf:
>
> interrupt-names: false
>
> + - if:
> + properties:
> + compatible:
> + const: nvidia,tegra238-mc
> + then:
> + properties:
> + reg:
> + minItems: 10
> + maxItems: 10
> + description: 8 memory controller channels, 1 broadcast, and 1 for stream-id registers
To be consistent with existing bindings, this should be "9 memory
controller channels and 1 for stream-id registers". It appears that the
broadcast is just consider to be a memory controller channel.
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH 0/2] memory: tegra: Add Tegra238 memory controller support
From: Krzysztof Kozlowski @ 2026-03-31 11:39 UTC (permalink / raw)
To: Ashish Mhetre, robh, conor+dt, jonathanh, sumitg
Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <20260331112347.3897841-1-amhetre@nvidia.com>
On 31/03/2026 13:23, Ashish Mhetre wrote:
> This series adds Memory Controller driver support for the Tegra238 SoC.
>
> Tegra238 is similar to Tegra234 but with a reduced memory controller
> configuration featuring 8 channels instead of 16. The driver reuses
> Tegra234 memory client IDs and ICC operations, with Tegra238-specific
> stream IDs for SMMU configuration.
>
Thank you for the patch/patchset. My tree is currently closed for new
features till the end of the merge window. I will review and/or apply
the patch after the merge window. No need to resend it, I will keep this
in my mailbox.
If I misjudged this patch and this is a fix, please let me know.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] memory: tegra: Add T238 MC support
From: Jon Hunter @ 2026-03-31 11:38 UTC (permalink / raw)
To: Ashish Mhetre, krzk, robh, conor+dt, =thierry.reding, sumitg
Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <20260331112347.3897841-2-amhetre@nvidia.com>
On 31/03/2026 12:23, Ashish Mhetre wrote:
> Add Memory Controller driver support for Tegra238 SOC, including:
> - MC client definitions with Tegra238-specific stream IDs
> - Reuse of Tegra234 ICC operations for bandwidth management via BPMP-FW
> - Device tree compatible string "nvidia,tegra238-mc"
>
> Export tegra234_mc_icc_ops so it can be shared with the Tegra238 MC
> driver, as both SoCs use the same ICC aggregation and bandwidth
> management logic.
>
> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
> ---
> drivers/memory/tegra/Makefile | 1 +
> drivers/memory/tegra/mc.c | 3 +
> drivers/memory/tegra/mc.h | 6 +
> drivers/memory/tegra/tegra234.c | 2 +-
> drivers/memory/tegra/tegra238.c | 395 ++++++++++++++++++++++++++++++++
> 5 files changed, 406 insertions(+), 1 deletion(-)
> create mode 100644 drivers/memory/tegra/tegra238.c
>
> diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
> index 6334601e6120..0d50e37d43af 100644
> --- a/drivers/memory/tegra/Makefile
> +++ b/drivers/memory/tegra/Makefile
> @@ -10,6 +10,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
> tegra-mc-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
> tegra-mc-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186.o tegra194.o
> tegra-mc-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186.o tegra234.o
> +tegra-mc-$(CONFIG_ARCH_TEGRA_238_SOC) += tegra186.o tegra238.o
> tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
>
> obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
> diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
> index d620660da331..10ef3c323e22 100644
> --- a/drivers/memory/tegra/mc.c
> +++ b/drivers/memory/tegra/mc.c
> @@ -49,6 +49,9 @@ static const struct of_device_id tegra_mc_of_match[] = {
> #ifdef CONFIG_ARCH_TEGRA_234_SOC
> { .compatible = "nvidia,tegra234-mc", .data = &tegra234_mc_soc },
> #endif
> +#ifdef CONFIG_ARCH_TEGRA_238_SOC
> + { .compatible = "nvidia,tegra238-mc", .data = &tegra238_mc_soc },
> +#endif
It is always better/preferred for the dt-binding patch to be 1st in the
series. The above does not exist until after patch 2 is applied.
> #ifdef CONFIG_ARCH_TEGRA_264_SOC
> { .compatible = "nvidia,tegra264-mc", .data = &tegra264_mc_soc },
> #endif
> diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
> index 649b54369263..d0da4a5f192d 100644
> --- a/drivers/memory/tegra/mc.h
> +++ b/drivers/memory/tegra/mc.h
> @@ -238,6 +238,11 @@ extern const struct tegra_mc_soc tegra194_mc_soc;
>
> #ifdef CONFIG_ARCH_TEGRA_234_SOC
> extern const struct tegra_mc_soc tegra234_mc_soc;
> +extern const struct tegra_mc_icc_ops tegra234_mc_icc_ops;
> +#endif
> +
> +#ifdef CONFIG_ARCH_TEGRA_238_SOC
> +extern const struct tegra_mc_soc tegra238_mc_soc;
> #endif
Does this work? Tegra238 is dependent upon stuff in Tegra234, but there
is no guarantee that both of these CONFIG options are always enabled?
>
> #ifdef CONFIG_ARCH_TEGRA_264_SOC
> @@ -256,6 +261,7 @@ extern const struct tegra_mc_ops tegra30_mc_ops;
> #if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
> defined(CONFIG_ARCH_TEGRA_194_SOC) || \
> defined(CONFIG_ARCH_TEGRA_234_SOC) || \
> + defined(CONFIG_ARCH_TEGRA_238_SOC) || \
> defined(CONFIG_ARCH_TEGRA_264_SOC)
> extern const struct tegra_mc_ops tegra186_mc_ops;
> #endif
> diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c
> index 87b22038a5fb..9fbd34d4abe0 100644
> --- a/drivers/memory/tegra/tegra234.c
> +++ b/drivers/memory/tegra/tegra234.c
> @@ -1125,7 +1125,7 @@ static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
> return 0;
> }
>
> -static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
> +const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
> .xlate = tegra_mc_icc_xlate,
> .aggregate = tegra234_mc_icc_aggregate,
> .get_bw = tegra234_mc_icc_get_init_bw,
> diff --git a/drivers/memory/tegra/tegra238.c b/drivers/memory/tegra/tegra238.c
> new file mode 100644
> index 000000000000..5abdca16a275
> --- /dev/null
> +++ b/drivers/memory/tegra/tegra238.c
> @@ -0,0 +1,395 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026, NVIDIA CORPORATION. All rights reserved.
> + */
...
> +const struct tegra_mc_soc tegra238_mc_soc = {
> + .num_clients = ARRAY_SIZE(tegra238_mc_clients),
> + .clients = tegra238_mc_clients,
> + .num_address_bits = 40,
> + .num_channels = 8,
> + .client_id_mask = 0x1ff,
> + .intmasks = tegra238_mc_intmasks,
> + .num_intmasks = ARRAY_SIZE(tegra238_mc_intmasks),
> + .has_addr_hi_reg = true,
> + .ops = &tegra186_mc_ops,
> + .icc_ops = &tegra234_mc_icc_ops,
> + .ch_intmask = 0x0000ff00,
> + .global_intstatus_channel_shift = 8,
> + /*
> + * Additionally, there are lite carveouts but those are not currently
> + * supported.
> + */
I don't know what this means?
> + .num_carveouts = 32,
> + .regs = &tegra20_mc_regs,
> + .handle_irq = tegra30_mc_irq_handlers,
> + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
> + .mc_addr_hi_mask = 0x3,
> + .mc_err_status_type_mask = (0x7 << 28),
> +};
Jon
--
nvpublic
^ permalink raw reply
* Re: [GIT PULL 1/7] dt-bindings: Changes for v7.1-rc1
From: Krzysztof Kozlowski @ 2026-03-31 11:28 UTC (permalink / raw)
To: Thierry Reding
Cc: Thierry Reding, arm, soc, Jon Hunter, linux-tegra,
linux-arm-kernel
In-Reply-To: <acumPszu9kvDsebG@orome>
On 31/03/2026 13:09, Thierry Reding wrote:
> On Tue, Mar 31, 2026 at 11:50:18AM +0200, Krzysztof Kozlowski wrote:
>> On 31/03/2026 10:25, Thierry Reding wrote:
>>>
>>>>> dt-bindings: phy: tegra-xusb: Document Type C support
>>>>
>>>> No acks, but that is waiting for one month so it is fine.
>>>
>>> It's got a Reviewed-by from Rob and there were no corresponding driver
>>> changes associated with it. There's literally no reason for this to go
>>> in through a subsystem tree.
>>
>> There are reasons - process and technical:
>> 1. It's a subsystem maintainer's patch, not yours. You rather should
>> have reason to take someone else's patches.
>>
>> 2. Conflict in that file.
>>
>>
>>>
>>>>> dt-bindings: clock: tegra124-dfll: Convert to json-schema
>>>>> dt-bindings: interrupt-controller: tegra: Fix reg entries
>>>>> dt-bindings: arm: tegra: Add missing compatible strings
>>>>> dt-bindings: phy: tegra: Document Tegra210 USB PHY
>>>>> dt-bindings: memory: Add Tegra210 memory controller bindings
>>>>> dt-bindings: memory: tegra210: Mark EMC as cooling device
>>>>
>>>> That's even my subsystem and I did not ack it. You did not even sent it
>>>> to me as requested by MAINTAINERS file (+dt is ignore alias), so
>>>> obviously I did not even had a chance to ack it.
>>>
>>> Ugh... really? I was Cc'ed to you as a DT maintainer as well as the
>>> devicetree mailing list, so I'm sure you've seen it. This had also been
>>
>> Really, you are supposed to use get_maintainers.pl. Not invent the CC
>> list, not come with own filtered list.
>>
>> I understand that my non dt address disappears when running
>> get_maintainers.pl on entire set.
>>
>> But if you sent that patch targetting subsystem instead of combining 6
>> or 7 subsystems at once, it would pop up.
>>
>> And yes, you are not supposed to mix 7 different subsystems in single
>> patchset. That's basic!
>
> Pft... you're being unreasonable. These are all relatively trivial
> changes that have at one point or another been already reviewed. Do you
> seriously expect me to turn these into 7 different patch series so that
> everyone gets to spend even more time dealing with these?
That's what everyone else is doing, including Qualcomm which is
upstreaming multiple new SoCs per year, multiple patchsets, multiple
patches.
But no, I do not expect you to split it but I expect to use
get_maintainers.pl, unless that would cause a patchbomb cc-ing 50
addresses (I don't suggest that you created such patchbomb -
hypothetical). Removing maintainers from Cc list is not the way to solve
patchbomb problem, if such arises. Splitting a hypothetical patchbomb
would be the solution.
>
>> But sure, let's skip memory controllers patch cc list and:
>>
>>> reviewed by Rob a long time ago, and honestly, it's also quite trivial.
>>> It's been on the list for a month and there were no objections, so it
>>> does pass all of the criteria you mentioned before.
>>
>> No objections because you did not cc people. How can you claim "no
>> objections from person foo" if you do not cc person "foo", because you
>> do not use get_maintainers.pl?
>>
>> Look, find me here phy mantainers:
>>
>> https://lore.kernel.org/all/20260223143305.3771383-7-thierry.reding@kernel.org/
>
> It's an extremely trivial, one-line change to an existing binding. There
> is no interaction with the driver whatsoever, why would anyone outside
> of the DT and Tegra maintainers even want to look at this?
I explained in the beginning why someone could want to look:
1. It's a subsystem maintainer's patch, not yours.
2. Conflict in that file.
But regardless why someone would or would not want, get_maintainers.pl
asked you to Cc them.
>
>>>> And we even had few days ago talk were I explained you how these
>>>> bindings must go. Seeing pull request completely ignoring that
>>>> discussion is just huge surprise.
>>>>
>>>> No, it cannot go in. Send patches to proper maintainers first.
>>>
>>> Stop making these baseless accusations, Krzysztof. You were on Cc and
>>
>> Not using get_maintainers.pl so not ccing right address is not baseless.
>> This is the fact.
>
> I use get_maintainers.pl but filter down based on common sense.
Filtering means you don't use. Following this logic (although not
exactly "common sense" but writing bindings point you that common sense
for driver bindings is driver subsystem):
1. I use get_maintainers.pl on my patch.
2. Then I remove all addresses except linux-kernel@vger.kernel.org.
3. All good and I claim I am using get_maintainers.pl.
>
>> Neither phy, nor interrupts, nor clocks were sent to right people.
>
> Again, these are patches that were all on the list previously, sent to
> the right people at the time. They hadn't been picked up by now, so I
No, they were not sent to the right people at the time. The right people
at the time are pointed by get_maintainers.pl which you filtered out.
Look again, this is the v1:
https://lore.kernel.org/all/20260223143305.3771383-7-thierry.reding@kernel.org/
Where is any phy maintainer or the phy mailing list Cc-ed?
Instead of again using "baseless" arguments, please provide the actual
fact for that claim that you cc-ed right list and right people on that
patch.
> resent them, to the DT maintainers only, to give you guys a chance to
This is not a resent, this is the v1. Do you see "RESEND" in the
subject? I don't.
I am pointing out the facts now. If you disagree, please point me to the
original posting of phy patch with the 'right' people in CC list, as
requested by get_maintainers.pl.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH 1/2] memory: tegra: Add T238 MC support
From: Ashish Mhetre @ 2026-03-31 11:23 UTC (permalink / raw)
To: krzk, robh, conor+dt, =thierry.reding, jonathanh, sumitg
Cc: linux-kernel, devicetree, linux-tegra, Ashish Mhetre
In-Reply-To: <20260331112347.3897841-1-amhetre@nvidia.com>
Add Memory Controller driver support for Tegra238 SOC, including:
- MC client definitions with Tegra238-specific stream IDs
- Reuse of Tegra234 ICC operations for bandwidth management via BPMP-FW
- Device tree compatible string "nvidia,tegra238-mc"
Export tegra234_mc_icc_ops so it can be shared with the Tegra238 MC
driver, as both SoCs use the same ICC aggregation and bandwidth
management logic.
Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
---
drivers/memory/tegra/Makefile | 1 +
drivers/memory/tegra/mc.c | 3 +
drivers/memory/tegra/mc.h | 6 +
drivers/memory/tegra/tegra234.c | 2 +-
drivers/memory/tegra/tegra238.c | 395 ++++++++++++++++++++++++++++++++
5 files changed, 406 insertions(+), 1 deletion(-)
create mode 100644 drivers/memory/tegra/tegra238.c
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index 6334601e6120..0d50e37d43af 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -10,6 +10,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
tegra-mc-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
tegra-mc-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186.o tegra194.o
tegra-mc-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186.o tegra234.o
+tegra-mc-$(CONFIG_ARCH_TEGRA_238_SOC) += tegra186.o tegra238.o
tegra-mc-$(CONFIG_ARCH_TEGRA_264_SOC) += tegra186.o tegra264.o
obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index d620660da331..10ef3c323e22 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -49,6 +49,9 @@ static const struct of_device_id tegra_mc_of_match[] = {
#ifdef CONFIG_ARCH_TEGRA_234_SOC
{ .compatible = "nvidia,tegra234-mc", .data = &tegra234_mc_soc },
#endif
+#ifdef CONFIG_ARCH_TEGRA_238_SOC
+ { .compatible = "nvidia,tegra238-mc", .data = &tegra238_mc_soc },
+#endif
#ifdef CONFIG_ARCH_TEGRA_264_SOC
{ .compatible = "nvidia,tegra264-mc", .data = &tegra264_mc_soc },
#endif
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index 649b54369263..d0da4a5f192d 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -238,6 +238,11 @@ extern const struct tegra_mc_soc tegra194_mc_soc;
#ifdef CONFIG_ARCH_TEGRA_234_SOC
extern const struct tegra_mc_soc tegra234_mc_soc;
+extern const struct tegra_mc_icc_ops tegra234_mc_icc_ops;
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_238_SOC
+extern const struct tegra_mc_soc tegra238_mc_soc;
#endif
#ifdef CONFIG_ARCH_TEGRA_264_SOC
@@ -256,6 +261,7 @@ extern const struct tegra_mc_ops tegra30_mc_ops;
#if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
defined(CONFIG_ARCH_TEGRA_194_SOC) || \
defined(CONFIG_ARCH_TEGRA_234_SOC) || \
+ defined(CONFIG_ARCH_TEGRA_238_SOC) || \
defined(CONFIG_ARCH_TEGRA_264_SOC)
extern const struct tegra_mc_ops tegra186_mc_ops;
#endif
diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c
index 87b22038a5fb..9fbd34d4abe0 100644
--- a/drivers/memory/tegra/tegra234.c
+++ b/drivers/memory/tegra/tegra234.c
@@ -1125,7 +1125,7 @@ static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
return 0;
}
-static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
+const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
.xlate = tegra_mc_icc_xlate,
.aggregate = tegra234_mc_icc_aggregate,
.get_bw = tegra234_mc_icc_get_init_bw,
diff --git a/drivers/memory/tegra/tegra238.c b/drivers/memory/tegra/tegra238.c
new file mode 100644
index 000000000000..5abdca16a275
--- /dev/null
+++ b/drivers/memory/tegra/tegra238.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <soc/tegra/mc.h>
+
+#include <dt-bindings/memory/tegra234-mc.h>
+#include <dt-bindings/memory/nvidia,tegra238-mc.h>
+#include <linux/interconnect.h>
+#include <linux/tegra-icc.h>
+
+#include <soc/tegra/bpmp.h>
+#include "mc.h"
+
+static const struct tegra_mc_client tegra238_mc_clients[] = {
+ {
+ .id = TEGRA234_MEMORY_CLIENT_HDAR,
+ .name = "hdar",
+ .bpmp_id = TEGRA_ICC_BPMP_HDA,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA238_SID_HDA,
+ .regs = {
+ .sid = {
+ .override = 0xa8,
+ .security = 0xac,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_HDAW,
+ .name = "hdaw",
+ .bpmp_id = TEGRA_ICC_BPMP_HDA,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA238_SID_HDA,
+ .regs = {
+ .sid = {
+ .override = 0x1a8,
+ .security = 0x1ac,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB,
+ .name = "sdmmcrab",
+ .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_SDMMC4A,
+ .regs = {
+ .sid = {
+ .override = 0x318,
+ .security = 0x31c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB,
+ .name = "sdmmcwab",
+ .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_SDMMC4A,
+ .regs = {
+ .sid = {
+ .override = 0x338,
+ .security = 0x33c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APER,
+ .name = "aper",
+ .bpmp_id = TEGRA_ICC_BPMP_APE,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA238_SID_ISO_APE0,
+ .regs = {
+ .sid = {
+ .override = 0x3d0,
+ .security = 0x3d4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APEW,
+ .name = "apew",
+ .bpmp_id = TEGRA_ICC_BPMP_APE,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA238_SID_ISO_APE0,
+ .regs = {
+ .sid = {
+ .override = 0x3d8,
+ .security = 0x3dc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR,
+ .name = "nvdisplayr",
+ .bpmp_id = TEGRA_ICC_BPMP_DISPLAY,
+ .type = TEGRA_ICC_ISO_DISPLAY,
+ .sid = TEGRA238_SID_ISO_NVDISPLAY,
+ .regs = {
+ .sid = {
+ .override = 0x490,
+ .security = 0x494,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR1,
+ .name = "nvdisplayr1",
+ .bpmp_id = TEGRA_ICC_BPMP_DISPLAY,
+ .type = TEGRA_ICC_ISO_DISPLAY,
+ .sid = TEGRA238_SID_ISO_NVDISPLAY,
+ .regs = {
+ .sid = {
+ .override = 0x508,
+ .security = 0x50c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPR,
+ .name = "bpmpr",
+ .sid = TEGRA238_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x498,
+ .security = 0x49c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPW,
+ .name = "bpmpw",
+ .sid = TEGRA238_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x4a0,
+ .security = 0x4a4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPDMAR,
+ .name = "bpmpdmar",
+ .sid = TEGRA238_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x4a8,
+ .security = 0x4ac,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPDMAW,
+ .name = "bpmpdmaw",
+ .sid = TEGRA238_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x4b0,
+ .security = 0x4b4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APEDMAR,
+ .name = "apedmar",
+ .bpmp_id = TEGRA_ICC_BPMP_APEDMA,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA238_SID_ISO_APE1,
+ .regs = {
+ .sid = {
+ .override = 0x4f8,
+ .security = 0x4fc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APEDMAW,
+ .name = "apedmaw",
+ .bpmp_id = TEGRA_ICC_BPMP_APEDMA,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA238_SID_ISO_APE1,
+ .regs = {
+ .sid = {
+ .override = 0x500,
+ .security = 0x504,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_VICSRD,
+ .name = "vicsrd",
+ .bpmp_id = TEGRA_ICC_BPMP_VIC,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_VIC,
+ .regs = {
+ .sid = {
+ .override = 0x360,
+ .security = 0x364,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_VICSWR,
+ .name = "vicswr",
+ .bpmp_id = TEGRA_ICC_BPMP_VIC,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_VIC,
+ .regs = {
+ .sid = {
+ .override = 0x368,
+ .security = 0x36c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVDECSRD,
+ .name = "nvdecsrd",
+ .bpmp_id = TEGRA_ICC_BPMP_NVDEC,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_NVDEC,
+ .regs = {
+ .sid = {
+ .override = 0x3c0,
+ .security = 0x3c4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVDECSWR,
+ .name = "nvdecswr",
+ .bpmp_id = TEGRA_ICC_BPMP_NVDEC,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_NVDEC,
+ .regs = {
+ .sid = {
+ .override = 0x3c8,
+ .security = 0x3cc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVENCSRD,
+ .name = "nvencsrd",
+ .bpmp_id = TEGRA_ICC_BPMP_NVENC,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_NVENC,
+ .regs = {
+ .sid = {
+ .override = 0xe0,
+ .security = 0xe4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVENCSWR,
+ .name = "nvencswr",
+ .bpmp_id = TEGRA_ICC_BPMP_NVENC,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_NVENC,
+ .regs = {
+ .sid = {
+ .override = 0x158,
+ .security = 0x15c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE0R,
+ .name = "pcie0r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_0,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE0,
+ .regs = {
+ .sid = {
+ .override = 0x6c0,
+ .security = 0x6c4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE0W,
+ .name = "pcie0w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_0,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE0,
+ .regs = {
+ .sid = {
+ .override = 0x6c8,
+ .security = 0x6cc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE1R,
+ .name = "pcie1r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_1,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE1,
+ .regs = {
+ .sid = {
+ .override = 0x6d0,
+ .security = 0x6d4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE1W,
+ .name = "pcie1w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_1,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE1,
+ .regs = {
+ .sid = {
+ .override = 0x6d8,
+ .security = 0x6dc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE2AR,
+ .name = "pcie2ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_2,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE2,
+ .regs = {
+ .sid = {
+ .override = 0x6e0,
+ .security = 0x6e4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE2AW,
+ .name = "pcie2aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_2,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE2,
+ .regs = {
+ .sid = {
+ .override = 0x6e8,
+ .security = 0x6ec,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE3R,
+ .name = "pcie3r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_3,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE3,
+ .regs = {
+ .sid = {
+ .override = 0x6f0,
+ .security = 0x6f4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE3W,
+ .name = "pcie3w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_3,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA238_SID_PCIE3,
+ .regs = {
+ .sid = {
+ .override = 0x6f8,
+ .security = 0x6fc,
+ },
+ },
+ }, {
+ .id = TEGRA_ICC_MC_CPU_CLUSTER0,
+ .name = "sw_cluster0",
+ .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER0,
+ .type = TEGRA_ICC_NISO,
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVL1R,
+ .name = "nvl1r",
+ .bpmp_id = TEGRA_ICC_BPMP_GPU,
+ .type = TEGRA_ICC_NISO,
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVL1W,
+ .name = "nvl1w",
+ .bpmp_id = TEGRA_ICC_BPMP_GPU,
+ .type = TEGRA_ICC_NISO,
+ }
+};
+
+static const struct tegra_mc_intmask tegra238_mc_intmasks[] = {
+ {
+ .reg = MC_INTMASK,
+ .mask = MC_INT_DECERR_ROUTE_SANITY | MC_INT_DECERR_GENERALIZED_CARVEOUT |
+ MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
+ },
+};
+
+const struct tegra_mc_soc tegra238_mc_soc = {
+ .num_clients = ARRAY_SIZE(tegra238_mc_clients),
+ .clients = tegra238_mc_clients,
+ .num_address_bits = 40,
+ .num_channels = 8,
+ .client_id_mask = 0x1ff,
+ .intmasks = tegra238_mc_intmasks,
+ .num_intmasks = ARRAY_SIZE(tegra238_mc_intmasks),
+ .has_addr_hi_reg = true,
+ .ops = &tegra186_mc_ops,
+ .icc_ops = &tegra234_mc_icc_ops,
+ .ch_intmask = 0x0000ff00,
+ .global_intstatus_channel_shift = 8,
+ /*
+ * Additionally, there are lite carveouts but those are not currently
+ * supported.
+ */
+ .num_carveouts = 32,
+ .regs = &tegra20_mc_regs,
+ .handle_irq = tegra30_mc_irq_handlers,
+ .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
+ .mc_addr_hi_mask = 0x3,
+ .mc_err_status_type_mask = (0x7 << 28),
+};
--
2.50.1
^ permalink raw reply related
* [PATCH 2/2] dt-bindings: memory: tegra: Add nvidia,tegra238-mc compatible
From: Ashish Mhetre @ 2026-03-31 11:23 UTC (permalink / raw)
To: krzk, robh, conor+dt, =thierry.reding, jonathanh, sumitg
Cc: linux-kernel, devicetree, linux-tegra, Ashish Mhetre
In-Reply-To: <20260331112347.3897841-1-amhetre@nvidia.com>
Document the device tree binding for the Tegra238 memory controller.
Tegra238 has 8 memory controller channels plus broadcast and stream-id
registers.
Add the stream ID header (nvidia,tegra238-mc.h) defining ISO and NISO
stream IDs for SMMU configuration.
Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
---
.../nvidia,tegra186-mc.yaml | 31 ++++++++
.../dt-bindings/memory/nvidia,tegra238-mc.h | 74 +++++++++++++++++++
2 files changed, 105 insertions(+)
create mode 100644 include/dt-bindings/memory/nvidia,tegra238-mc.h
diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
index 7b03b589168b..e008cb1ccd28 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
@@ -32,6 +32,7 @@ properties:
- nvidia,tegra186-mc
- nvidia,tegra194-mc
- nvidia,tegra234-mc
+ - nvidia,tegra238-mc
- nvidia,tegra264-mc
reg:
@@ -266,6 +267,36 @@ allOf:
interrupt-names: false
+ - if:
+ properties:
+ compatible:
+ const: nvidia,tegra238-mc
+ then:
+ properties:
+ reg:
+ minItems: 10
+ maxItems: 10
+ description: 8 memory controller channels, 1 broadcast, and 1 for stream-id registers
+
+ reg-names:
+ items:
+ - const: sid
+ - const: broadcast
+ - const: ch0
+ - const: ch1
+ - const: ch2
+ - const: ch3
+ - const: ch4
+ - const: ch5
+ - const: ch6
+ - const: ch7
+
+ interrupts:
+ items:
+ - description: MC general interrupt
+
+ interrupt-names: false
+
- if:
properties:
compatible:
diff --git a/include/dt-bindings/memory/nvidia,tegra238-mc.h b/include/dt-bindings/memory/nvidia,tegra238-mc.h
new file mode 100644
index 000000000000..be24c0eb3f15
--- /dev/null
+++ b/include/dt-bindings/memory/nvidia,tegra238-mc.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/* Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved. */
+
+#ifndef DT_BINDINGS_MEMORY_TEGRA238_MC_H
+#define DT_BINDINGS_MEMORY_TEGRA238_MC_H
+
+/* special clients */
+#define TEGRA238_SID_INVALID 0x0
+#define TEGRA238_SID_PASSTHROUGH 0x7f
+
+/* ISO stream IDs */
+#define TEGRA238_SID_ISO_NVDISPLAY 0x1
+#define TEGRA238_SID_ISO_APE0 0x2
+#define TEGRA238_SID_ISO_APE1 0x3
+
+/* NISO stream IDs */
+#define TEGRA238_SID_AON 0x1
+#define TEGRA238_SID_BPMP 0x2
+#define TEGRA238_SID_ETR 0x3
+#define TEGRA238_SID_FDE 0x4
+#define TEGRA238_SID_HC 0x5
+#define TEGRA238_SID_HDA 0x6
+#define TEGRA238_SID_NVDEC 0x7
+#define TEGRA238_SID_NVDISPLAY 0x8
+#define TEGRA238_SID_NVENC 0x9
+#define TEGRA238_SID_OFA 0xa
+#define TEGRA238_SID_PCIE0 0xb
+#define TEGRA238_SID_PCIE1 0xc
+#define TEGRA238_SID_PCIE2 0xd
+#define TEGRA238_SID_PCIE3 0xe
+#define TEGRA238_SID_HWMP_PMA 0xf
+#define TEGRA238_SID_PSC 0x10
+#define TEGRA238_SID_SDMMC1A 0x11
+#define TEGRA238_SID_SDMMC4A 0x12
+#define TEGRA238_SID_SES_SE0 0x13
+#define TEGRA238_SID_SES_SE1 0x14
+#define TEGRA238_SID_SES_SE2 0x15
+#define TEGRA238_SID_SEU1_SE0 0x16
+#define TEGRA238_SID_SEU1_SE1 0x17
+#define TEGRA238_SID_SEU1_SE2 0x18
+#define TEGRA238_SID_TSEC 0x19
+#define TEGRA238_SID_UFSHC 0x1a
+#define TEGRA238_SID_VIC 0x1b
+#define TEGRA238_SID_XUSB_HOST 0x1c
+#define TEGRA238_SID_XUSB_DEV 0x1d
+#define TEGRA238_SID_GPCDMA_0 0x1e
+#define TEGRA238_SID_SMMU_TEST 0x1f
+
+/* Host1x virtualization clients. */
+#define TEGRA238_SID_HOST1X_CTX0 0x20
+#define TEGRA238_SID_HOST1X_CTX1 0x21
+#define TEGRA238_SID_HOST1X_CTX2 0x22
+#define TEGRA238_SID_HOST1X_CTX3 0x23
+#define TEGRA238_SID_HOST1X_CTX4 0x24
+#define TEGRA238_SID_HOST1X_CTX5 0x25
+#define TEGRA238_SID_HOST1X_CTX6 0x26
+#define TEGRA238_SID_HOST1X_CTX7 0x27
+
+#define TEGRA238_SID_XUSB_VF0 0x28
+#define TEGRA238_SID_XUSB_VF1 0x29
+#define TEGRA238_SID_XUSB_VF2 0x2a
+#define TEGRA238_SID_XUSB_VF3 0x2b
+
+/* Host1x command buffers */
+#define TEGRA238_SID_HC_VM0 0x2c
+#define TEGRA238_SID_HC_VM1 0x2d
+#define TEGRA238_SID_HC_VM2 0x2e
+#define TEGRA238_SID_HC_VM3 0x2f
+#define TEGRA238_SID_HC_VM4 0x30
+#define TEGRA238_SID_HC_VM5 0x31
+#define TEGRA238_SID_HC_VM6 0x32
+#define TEGRA238_SID_HC_VM7 0x33
+
+#endif
--
2.50.1
^ permalink raw reply related
* [PATCH 0/2] memory: tegra: Add Tegra238 memory controller support
From: Ashish Mhetre @ 2026-03-31 11:23 UTC (permalink / raw)
To: krzk, robh, conor+dt, =thierry.reding, jonathanh, sumitg
Cc: linux-kernel, devicetree, linux-tegra, Ashish Mhetre
This series adds Memory Controller driver support for the Tegra238 SoC.
Tegra238 is similar to Tegra234 but with a reduced memory controller
configuration featuring 8 channels instead of 16. The driver reuses
Tegra234 memory client IDs and ICC operations, with Tegra238-specific
stream IDs for SMMU configuration.
Ashish Mhetre (2):
memory: tegra: Add T238 MC support
dt-bindings: memory: tegra: Add nvidia,tegra238-mc compatible
.../nvidia,tegra186-mc.yaml | 31 ++
drivers/memory/tegra/Makefile | 1 +
drivers/memory/tegra/mc.c | 3 +
drivers/memory/tegra/mc.h | 6 +
drivers/memory/tegra/tegra234.c | 2 +-
drivers/memory/tegra/tegra238.c | 395 ++++++++++++++++++
.../dt-bindings/memory/nvidia,tegra238-mc.h | 74 ++++
7 files changed, 511 insertions(+), 1 deletion(-)
create mode 100644 drivers/memory/tegra/tegra238.c
create mode 100644 include/dt-bindings/memory/nvidia,tegra238-mc.h
--
2.50.1
^ permalink raw reply
* Re: [GIT PULL 1/7] dt-bindings: Changes for v7.1-rc1
From: Thierry Reding @ 2026-03-31 11:09 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Thierry Reding, arm, soc, Jon Hunter, linux-tegra,
linux-arm-kernel
In-Reply-To: <1bdf911d-383a-4ea3-9a33-f8ee6e8f26e4@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 4512 bytes --]
On Tue, Mar 31, 2026 at 11:50:18AM +0200, Krzysztof Kozlowski wrote:
> On 31/03/2026 10:25, Thierry Reding wrote:
> >
> >>> dt-bindings: phy: tegra-xusb: Document Type C support
> >>
> >> No acks, but that is waiting for one month so it is fine.
> >
> > It's got a Reviewed-by from Rob and there were no corresponding driver
> > changes associated with it. There's literally no reason for this to go
> > in through a subsystem tree.
>
> There are reasons - process and technical:
> 1. It's a subsystem maintainer's patch, not yours. You rather should
> have reason to take someone else's patches.
>
> 2. Conflict in that file.
>
>
> >
> >>> dt-bindings: clock: tegra124-dfll: Convert to json-schema
> >>> dt-bindings: interrupt-controller: tegra: Fix reg entries
> >>> dt-bindings: arm: tegra: Add missing compatible strings
> >>> dt-bindings: phy: tegra: Document Tegra210 USB PHY
> >>> dt-bindings: memory: Add Tegra210 memory controller bindings
> >>> dt-bindings: memory: tegra210: Mark EMC as cooling device
> >>
> >> That's even my subsystem and I did not ack it. You did not even sent it
> >> to me as requested by MAINTAINERS file (+dt is ignore alias), so
> >> obviously I did not even had a chance to ack it.
> >
> > Ugh... really? I was Cc'ed to you as a DT maintainer as well as the
> > devicetree mailing list, so I'm sure you've seen it. This had also been
>
> Really, you are supposed to use get_maintainers.pl. Not invent the CC
> list, not come with own filtered list.
>
> I understand that my non dt address disappears when running
> get_maintainers.pl on entire set.
>
> But if you sent that patch targetting subsystem instead of combining 6
> or 7 subsystems at once, it would pop up.
>
> And yes, you are not supposed to mix 7 different subsystems in single
> patchset. That's basic!
Pft... you're being unreasonable. These are all relatively trivial
changes that have at one point or another been already reviewed. Do you
seriously expect me to turn these into 7 different patch series so that
everyone gets to spend even more time dealing with these?
> But sure, let's skip memory controllers patch cc list and:
>
> > reviewed by Rob a long time ago, and honestly, it's also quite trivial.
> > It's been on the list for a month and there were no objections, so it
> > does pass all of the criteria you mentioned before.
>
> No objections because you did not cc people. How can you claim "no
> objections from person foo" if you do not cc person "foo", because you
> do not use get_maintainers.pl?
>
> Look, find me here phy mantainers:
>
> https://lore.kernel.org/all/20260223143305.3771383-7-thierry.reding@kernel.org/
It's an extremely trivial, one-line change to an existing binding. There
is no interaction with the driver whatsoever, why would anyone outside
of the DT and Tegra maintainers even want to look at this?
> >> And we even had few days ago talk were I explained you how these
> >> bindings must go. Seeing pull request completely ignoring that
> >> discussion is just huge surprise.
> >>
> >> No, it cannot go in. Send patches to proper maintainers first.
> >
> > Stop making these baseless accusations, Krzysztof. You were on Cc and
>
> Not using get_maintainers.pl so not ccing right address is not baseless.
> This is the fact.
I use get_maintainers.pl but filter down based on common sense.
> Neither phy, nor interrupts, nor clocks were sent to right people.
Again, these are patches that were all on the list previously, sent to
the right people at the time. They hadn't been picked up by now, so I
resent them, to the DT maintainers only, to give you guys a chance to
object in case there were any new things you were looking for since the
original submissions.
> You mixed 6 or 7 different subsystems in on patchset, but you call my
> remarks as baseless. You use several adjectives "trivial", "baseless",
> but no actual facts.
>
> Final commentary:
> Stop taking patches from other subsystems, just because you want to
> streamline your DTS. You are bypassing other subsystems review, other
> people trees, and that's not acceptable.
You know, I'll do just that. In fact, I'll just stop working on these
cleanup patches. It's a shame because I really wanted to get off your
wall of shame by this year's LPC, but you're making this needlessly
complicated and I'm out of patience.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH V3 1/3] net: stmmac: Fix PTP ref clock for Tegra234
From: Jon Hunter @ 2026-03-31 10:48 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, netdev, devicetree, linux-tegra
In-Reply-To: <5b3eaba5-eba2-43f9-8ef5-d305ca50ddf0@kernel.org>
On 31/03/2026 11:18, Krzysztof Kozlowski wrote:
> On 31/03/2026 12:14, Jon Hunter wrote:
>>
>> On 26/03/2026 08:32, Krzysztof Kozlowski wrote:
>>
>> ...
>>
>>>> @@ -257,9 +258,23 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
>>>> if (!mgbe->clks)
>>>> return -ENOMEM;
>>>>
>>>> - for (i = 0; i < ARRAY_SIZE(mgbe_clks); i++)
>>>> + /*
>>>> + * Older device-trees use 'ptp-ref' rather than 'ptp_ref'.
>>>> + * Fall back to the legacy name when 'ptp_ref' is absent.
>>>> + */
>>>> + use_legacy_ptp = of_property_match_string(pdev->dev.of_node,
>>>> + "clock-names", "ptp_ref") < 0;
>>>> +
>>>> + for (i = 0; i < ARRAY_SIZE(mgbe_clks); i++) {
>>>> mgbe->clks[i].id = mgbe_clks[i];
>>>>
>>>> + if (use_legacy_ptp && !strcmp(mgbe_clks[i], "ptp_ref")) {
>>>
>>> Why index 0 is not valid? And why -EINVAL would be considered as legacy
>>> clock present?
>>
>> Index 0 is valid. However, yes I guess that treating an -EINVAL from
>> of_property_match_string() is not correct. I will switch the logic to be ...
>>
>> use_legacy_ptp = of_property_match_string(pdev->dev.of_node,
>> "clock-names", "ptp-ref") >= 0;
>
> No, apologies, I think my comment was not correct and your reply made me
> rethink. I missed final "< 0" in of_property_match_string().
>
> So the code is good, you do not store index in 'use_legacy_ptp', but the
> error return value.
>
> Can you however make it more obvious code, so something like:
>
> if (of_property_match_string...))
> use_legacy_ptp = true;;
Yes I can do that. Before I was avoiding the need to pre-initialise the
variable, but I am happy either way to get this fixed!
Jon
--
nvpublic
^ permalink raw reply
* [PATCH v6 10/10] arm64: tegra: Enable GPCDMA in Tegra264 and add iommu-map
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
Enable GPCDMA in Tegra264 and add the iommu-map property so that each
channel uses a separate stream ID and gets its own IOMMU domain for
memory.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi | 4 ++++
arch/arm64/boot/dts/nvidia/tegra264.dtsi | 1 +
2 files changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi b/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi
index 7e2c3e66c2ab..58cd81bc33d7 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264-p3834.dtsi
@@ -9,6 +9,10 @@ aliases {
};
bus@0 {
+ dma-controller@8400000 {
+ status = "okay";
+ };
+
serial@c4e0000 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
index af077420d7d9..b2f20d4b567a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
@@ -3244,6 +3244,7 @@ gpcdma: dma-controller@8400000 {
<GIC_SPI 615 IRQ_TYPE_LEVEL_HIGH>;
#dma-cells = <1>;
iommus = <&smmu1 0x00000800>;
+ iommu-map = <1 &smmu1 0x801 31>;
dma-coherent;
dma-channel-mask = <0xfffffffe>;
status = "disabled";
--
2.50.1
^ permalink raw reply related
* [PATCH v6 09/10] dmaengine: tegra: Add Tegra264 support
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
Add compatible and chip data to support GPCDMA in Tegra264, which has
differences in register layout and address bits compared to previous
versions.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
drivers/dma/tegra186-gpc-dma.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index cd480d047204..2383a2fe73f1 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1319,6 +1319,23 @@ static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
.fixed_pattern = 0x34,
};
+static const struct tegra_dma_channel_regs tegra264_reg_offsets = {
+ .csr = 0x0,
+ .status = 0x4,
+ .csre = 0x8,
+ .src = 0xc,
+ .dst = 0x10,
+ .src_high = 0x14,
+ .dst_high = 0x18,
+ .mc_seq = 0x1c,
+ .mmio_seq = 0x20,
+ .wcount = 0x24,
+ .wxfer = 0x28,
+ .wstatus = 0x2c,
+ .err_status = 0x34,
+ .fixed_pattern = 0x38,
+};
+
static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
.nr_channels = 32,
.addr_bits = 39,
@@ -1349,6 +1366,16 @@ static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
.terminate = tegra_dma_pause_noerr,
};
+static const struct tegra_dma_chip_data tegra264_dma_chip_data = {
+ .nr_channels = 32,
+ .addr_bits = 41,
+ .channel_reg_size = SZ_64K,
+ .max_dma_count = SZ_1G,
+ .hw_support_pause = true,
+ .channel_regs = &tegra264_reg_offsets,
+ .terminate = tegra_dma_pause_noerr,
+};
+
static const struct of_device_id tegra_dma_of_match[] = {
{
.compatible = "nvidia,tegra186-gpcdma",
@@ -1359,6 +1386,9 @@ static const struct of_device_id tegra_dma_of_match[] = {
}, {
.compatible = "nvidia,tegra234-gpcdma",
.data = &tegra234_dma_chip_data,
+ }, {
+ .compatible = "nvidia,tegra264-gpcdma",
+ .data = &tegra264_dma_chip_data,
}, {
},
};
--
2.50.1
^ permalink raw reply related
* [PATCH v6 08/10] dmaengine: tegra: Use iommu-map for stream ID
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
Use 'iommu-map', when provided, to get the stream ID to be programmed
for each channel. Iterate over the channels registered and configure
each channel device separately using of_dma_configure_id() to allow
it to use a separate IOMMU domain for the transfer. However, do this
in a second loop since the first loop populates the DMA device channels
list and async_device_register() registers the channels. Both are
prerequisites for using the channel device in the next loop.
Channels will continue to use the same global stream ID if the
'iommu-map' property is not present in the device tree.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/dma/tegra186-gpc-dma.c | 53 ++++++++++++++++++++++++++++------
1 file changed, 44 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 9bea2ffb3b9e..cd480d047204 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/slab.h>
@@ -1380,9 +1381,13 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
static int tegra_dma_probe(struct platform_device *pdev)
{
const struct tegra_dma_chip_data *cdata = NULL;
+ struct tegra_dma_channel *tdc;
+ struct tegra_dma *tdma;
+ struct dma_chan *chan;
+ struct device *chdev;
+ bool use_iommu_map = false;
unsigned int i;
u32 stream_id;
- struct tegra_dma *tdma;
int ret;
cdata = of_device_get_match_data(&pdev->dev);
@@ -1410,9 +1415,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdma->dma_dev.dev = &pdev->dev;
- if (!tegra_dev_iommu_get_stream_id(&pdev->dev, &stream_id)) {
- dev_err(&pdev->dev, "Missing iommu stream-id\n");
- return -EINVAL;
+ use_iommu_map = of_property_present(pdev->dev.of_node, "iommu-map");
+ if (!use_iommu_map) {
+ if (!tegra_dev_iommu_get_stream_id(&pdev->dev, &stream_id))
+ return dev_err_probe(&pdev->dev, -EINVAL, "Missing iommu stream-id\n");
}
ret = device_property_read_u32(&pdev->dev, "dma-channel-mask",
@@ -1424,9 +1430,10 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdma->chan_mask = TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK;
}
+ /* Initialize vchan for each channel and populate the channels list */
INIT_LIST_HEAD(&tdma->dma_dev.channels);
for (i = 0; i < cdata->nr_channels; i++) {
- struct tegra_dma_channel *tdc = &tdma->channels[i];
+ tdc = &tdma->channels[i];
/* Check for channel mask */
if (!(tdma->chan_mask & BIT(i)))
@@ -1446,10 +1453,6 @@ static int tegra_dma_probe(struct platform_device *pdev)
vchan_init(&tdc->vc, &tdma->dma_dev);
tdc->vc.desc_free = tegra_dma_desc_free;
-
- /* program stream-id for this channel */
- tegra_dma_program_sid(tdc, stream_id);
- tdc->stream_id = stream_id;
}
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(cdata->addr_bits));
@@ -1483,6 +1486,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdma->dma_dev.device_synchronize = tegra_dma_chan_synchronize;
tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+ /* Register the DMA device and the channels */
ret = dmaenginem_async_device_register(&tdma->dma_dev);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret,
@@ -1490,6 +1494,37 @@ static int tegra_dma_probe(struct platform_device *pdev)
return ret;
}
+ /*
+ * Configure stream ID for each channel from the channels registered
+ * above. This is done in a separate iteration to ensure that only
+ * the channels available and registered for the DMA device are used.
+ */
+ list_for_each_entry(chan, &tdma->dma_dev.channels, device_node) {
+ chdev = &chan->dev->device;
+ tdc = to_tegra_dma_chan(chan);
+
+ if (use_iommu_map) {
+ chdev->bus = pdev->dev.bus;
+ dma_coerce_mask_and_coherent(chdev, DMA_BIT_MASK(cdata->addr_bits));
+
+ ret = of_dma_configure_id(chdev, pdev->dev.of_node,
+ true, &tdc->id);
+ if (ret)
+ return dev_err_probe(chdev, ret,
+ "Failed to configure IOMMU for channel %d\n", tdc->id);
+
+ if (!tegra_dev_iommu_get_stream_id(chdev, &stream_id))
+ return dev_err_probe(chdev, -EINVAL,
+ "Failed to get stream ID for channel %d\n", tdc->id);
+
+ chan->dev->chan_dma_dev = true;
+ }
+
+ /* program stream-id for this channel */
+ tegra_dma_program_sid(tdc, stream_id);
+ tdc->stream_id = stream_id;
+ }
+
ret = devm_of_dma_controller_register(&pdev->dev, pdev->dev.of_node,
tegra_dma_of_xlate, tdma);
if (ret < 0) {
--
2.50.1
^ permalink raw reply related
* [PATCH v6 07/10] dmaengine: tegra: Use managed DMA controller registration
From: Akhil R @ 2026-03-31 10:23 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
Switch to managed registration in probe. This simplifies the error
paths in the probe and also removes the requirement of the driver
remove function.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Suggested-by: Frank Li <frank.li@nxp.com>
---
drivers/dma/tegra186-gpc-dma.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 3ac43ad19ed6..9bea2ffb3b9e 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1483,37 +1483,27 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdma->dma_dev.device_synchronize = tegra_dma_chan_synchronize;
tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
- ret = dma_async_device_register(&tdma->dma_dev);
+ ret = dmaenginem_async_device_register(&tdma->dma_dev);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret,
"GPC DMA driver registration failed\n");
return ret;
}
- ret = of_dma_controller_register(pdev->dev.of_node,
- tegra_dma_of_xlate, tdma);
+ ret = devm_of_dma_controller_register(&pdev->dev, pdev->dev.of_node,
+ tegra_dma_of_xlate, tdma);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret,
"GPC DMA OF registration failed\n");
-
- dma_async_device_unregister(&tdma->dma_dev);
return ret;
}
- dev_info(&pdev->dev, "GPC DMA driver register %lu channels\n",
+ dev_info(&pdev->dev, "GPC DMA driver registered %lu channels\n",
hweight_long(tdma->chan_mask));
return 0;
}
-static void tegra_dma_remove(struct platform_device *pdev)
-{
- struct tegra_dma *tdma = platform_get_drvdata(pdev);
-
- of_dma_controller_free(pdev->dev.of_node);
- dma_async_device_unregister(&tdma->dma_dev);
-}
-
static int __maybe_unused tegra_dma_pm_suspend(struct device *dev)
{
struct tegra_dma *tdma = dev_get_drvdata(dev);
@@ -1564,7 +1554,6 @@ static struct platform_driver tegra_dma_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove = tegra_dma_remove,
};
module_platform_driver(tegra_dma_driver);
--
2.50.1
^ permalink raw reply related
* [PATCH v6 06/10] dmaengine: tegra: Support address width > 39 bits
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
Tegra264 supports address width of 41 bits. Unlike older SoCs which use
a common high_addr register for upper address bits, Tegra264 has separate
src_high and dst_high registers to accommodate this wider address space.
Add an addr_bits property to the device data structure to specify the
number of address bits supported on each device and use that to program
the appropriate registers.
Update the sg_req struct to remove the high_addr field and use
dma_addr_t for src and dst to store the complete addresses. Extract
the high address bits only when programming the registers.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
drivers/dma/tegra186-gpc-dma.c | 83 +++++++++++++++++++++-------------
1 file changed, 52 insertions(+), 31 deletions(-)
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index b213c4ae07d2..3ac43ad19ed6 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -146,6 +146,7 @@ struct tegra_dma_channel;
*/
struct tegra_dma_chip_data {
bool hw_support_pause;
+ unsigned int addr_bits;
unsigned int nr_channels;
unsigned int channel_reg_size;
unsigned int max_dma_count;
@@ -161,6 +162,8 @@ struct tegra_dma_channel_regs {
u32 src;
u32 dst;
u32 high_addr;
+ u32 src_high;
+ u32 dst_high;
u32 mc_seq;
u32 mmio_seq;
u32 wcount;
@@ -179,10 +182,9 @@ struct tegra_dma_channel_regs {
*/
struct tegra_dma_sg_req {
unsigned int len;
+ dma_addr_t src;
+ dma_addr_t dst;
u32 csr;
- u32 src;
- u32 dst;
- u32 high_addr;
u32 mc_seq;
u32 mmio_seq;
u32 wcount;
@@ -266,6 +268,25 @@ static inline struct device *tdc2dev(struct tegra_dma_channel *tdc)
return tdc->vc.chan.device->dev;
}
+static void tegra_dma_program_addr(struct tegra_dma_channel *tdc,
+ struct tegra_dma_sg_req *sg_req)
+{
+ tdc_write(tdc, tdc->regs->src, lower_32_bits(sg_req->src));
+ tdc_write(tdc, tdc->regs->dst, lower_32_bits(sg_req->dst));
+
+ if (tdc->tdma->chip_data->addr_bits > 39) {
+ tdc_write(tdc, tdc->regs->src_high, upper_32_bits(sg_req->src));
+ tdc_write(tdc, tdc->regs->dst_high, upper_32_bits(sg_req->dst));
+ } else {
+ u32 src_high = FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR,
+ upper_32_bits(sg_req->src));
+ u32 dst_high = FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR,
+ upper_32_bits(sg_req->dst));
+
+ tdc_write(tdc, tdc->regs->high_addr, src_high | dst_high);
+ }
+}
+
static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
{
dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n",
@@ -274,10 +295,20 @@ static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
tdc_read(tdc, tdc->regs->csr),
tdc_read(tdc, tdc->regs->status),
tdc_read(tdc, tdc->regs->csre));
- dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
- tdc_read(tdc, tdc->regs->src),
- tdc_read(tdc, tdc->regs->dst),
- tdc_read(tdc, tdc->regs->high_addr));
+
+ if (tdc->tdma->chip_data->addr_bits > 39) {
+ dev_dbg(tdc2dev(tdc), "SRC %x SRC HI %x DST %x DST HI %x\n",
+ tdc_read(tdc, tdc->regs->src),
+ tdc_read(tdc, tdc->regs->src_high),
+ tdc_read(tdc, tdc->regs->dst),
+ tdc_read(tdc, tdc->regs->dst_high));
+ } else {
+ dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
+ tdc_read(tdc, tdc->regs->src),
+ tdc_read(tdc, tdc->regs->dst),
+ tdc_read(tdc, tdc->regs->high_addr));
+ }
+
dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x WSTA %x\n",
tdc_read(tdc, tdc->regs->mc_seq),
tdc_read(tdc, tdc->regs->mmio_seq),
@@ -480,9 +511,7 @@ static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
- tdc_write(tdc, tdc->regs->src, sg_req->src);
- tdc_write(tdc, tdc->regs->dst, sg_req->dst);
- tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
+ tegra_dma_program_addr(tdc, sg_req);
/* Start DMA */
tdc_write(tdc, tdc->regs->csr,
@@ -510,11 +539,9 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc)
sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
+ tegra_dma_program_addr(tdc, sg_req);
tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
tdc_write(tdc, tdc->regs->csr, 0);
- tdc_write(tdc, tdc->regs->src, sg_req->src);
- tdc_write(tdc, tdc->regs->dst, sg_req->dst);
- tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
tdc_write(tdc, tdc->regs->fixed_pattern, sg_req->fixed_pattern);
tdc_write(tdc, tdc->regs->mmio_seq, sg_req->mmio_seq);
tdc_write(tdc, tdc->regs->mc_seq, sg_req->mc_seq);
@@ -819,7 +846,7 @@ static unsigned int get_burst_size(struct tegra_dma_channel *tdc,
static int get_transfer_param(struct tegra_dma_channel *tdc,
enum dma_transfer_direction direction,
- u32 *apb_addr,
+ dma_addr_t *apb_addr,
u32 *mmio_seq,
u32 *csr,
unsigned int *burst_size,
@@ -897,11 +924,9 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
dma_desc->bytes_req = len;
dma_desc->sg_count = 1;
sg_req = dma_desc->sg_req;
-
sg_req[0].src = 0;
sg_req[0].dst = dest;
- sg_req[0].high_addr =
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
+
sg_req[0].fixed_pattern = value;
/* Word count reg takes value as (N +1) words */
sg_req[0].wcount = ((len - 4) >> 2);
@@ -969,10 +994,7 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
sg_req[0].src = src;
sg_req[0].dst = dest;
- sg_req[0].high_addr =
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32));
- sg_req[0].high_addr |=
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
+
/* Word count reg takes value as (N +1) words */
sg_req[0].wcount = ((len - 4) >> 2);
sg_req[0].csr = csr;
@@ -992,7 +1014,8 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
unsigned int max_dma_count = tdc->tdma->chip_data->max_dma_count;
enum dma_slave_buswidth slave_bw = DMA_SLAVE_BUSWIDTH_UNDEFINED;
- u32 csr, mc_seq, apb_ptr = 0, mmio_seq = 0;
+ u32 csr, mc_seq, mmio_seq = 0;
+ dma_addr_t apb_ptr = 0;
struct tegra_dma_sg_req *sg_req;
struct tegra_dma_desc *dma_desc;
struct scatterlist *sg;
@@ -1080,13 +1103,9 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
if (direction == DMA_MEM_TO_DEV) {
sg_req[i].src = mem;
sg_req[i].dst = apb_ptr;
- sg_req[i].high_addr =
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
} else if (direction == DMA_DEV_TO_MEM) {
sg_req[i].src = apb_ptr;
sg_req[i].dst = mem;
- sg_req[i].high_addr =
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
}
/*
@@ -1110,7 +1129,8 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
unsigned long flags)
{
enum dma_slave_buswidth slave_bw = DMA_SLAVE_BUSWIDTH_UNDEFINED;
- u32 csr, mc_seq, apb_ptr = 0, mmio_seq = 0, burst_size;
+ u32 csr, mc_seq, mmio_seq = 0, burst_size;
+ dma_addr_t apb_ptr = 0;
unsigned int max_dma_count, len, period_count, i;
struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
struct tegra_dma_desc *dma_desc;
@@ -1201,13 +1221,9 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
if (direction == DMA_MEM_TO_DEV) {
sg_req[i].src = mem;
sg_req[i].dst = apb_ptr;
- sg_req[i].high_addr =
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
} else if (direction == DMA_DEV_TO_MEM) {
sg_req[i].src = apb_ptr;
sg_req[i].dst = mem;
- sg_req[i].high_addr =
- FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
}
/*
* Word count register takes input in words. Writing a value
@@ -1304,6 +1320,7 @@ static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
.nr_channels = 32,
+ .addr_bits = 39,
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = false,
@@ -1313,6 +1330,7 @@ static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
.nr_channels = 32,
+ .addr_bits = 39,
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = true,
@@ -1322,6 +1340,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
.nr_channels = 32,
+ .addr_bits = 39,
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = true,
@@ -1433,6 +1452,8 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdc->stream_id = stream_id;
}
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(cdata->addr_bits));
+
dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask);
dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask);
dma_cap_set(DMA_MEMCPY, tdma->dma_dev.cap_mask);
--
2.50.1
^ permalink raw reply related
* [PATCH v6 05/10] dmaengine: tegra: Use struct for register offsets
From: Akhil R @ 2026-03-31 10:22 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
Cc: Akhil R, Frank Li
In-Reply-To: <20260331102303.33181-1-akhilrajeev@nvidia.com>
Repurpose the struct tegra_dma_channel_regs to define offsets for all the
channel registers. Previously, the struct only held the register values
for each transfer and was wrapped within tegra_dma_sg_req. Move the
values directly into tegra_dma_sg_req and use channel_regs for
storing the register offsets. Update all register reads/writes to use
the struct channel_regs. This prepares for the register offset change
in Tegra264.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
drivers/dma/tegra186-gpc-dma.c | 282 +++++++++++++++++----------------
1 file changed, 142 insertions(+), 140 deletions(-)
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index a0522a992ebc..b213c4ae07d2 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -22,7 +22,6 @@
#include "virt-dma.h"
/* CSR register */
-#define TEGRA_GPCDMA_CHAN_CSR 0x00
#define TEGRA_GPCDMA_CSR_ENB BIT(31)
#define TEGRA_GPCDMA_CSR_IE_EOC BIT(30)
#define TEGRA_GPCDMA_CSR_ONCE BIT(27)
@@ -58,7 +57,6 @@
#define TEGRA_GPCDMA_CSR_WEIGHT GENMASK(13, 10)
/* STATUS register */
-#define TEGRA_GPCDMA_CHAN_STATUS 0x004
#define TEGRA_GPCDMA_STATUS_BUSY BIT(31)
#define TEGRA_GPCDMA_STATUS_ISE_EOC BIT(30)
#define TEGRA_GPCDMA_STATUS_PING_PONG BIT(28)
@@ -70,22 +68,13 @@
#define TEGRA_GPCDMA_STATUS_IRQ_STA BIT(21)
#define TEGRA_GPCDMA_STATUS_IRQ_TRIG_STA BIT(20)
-#define TEGRA_GPCDMA_CHAN_CSRE 0x008
#define TEGRA_GPCDMA_CHAN_CSRE_PAUSE BIT(31)
-/* Source address */
-#define TEGRA_GPCDMA_CHAN_SRC_PTR 0x00C
-
-/* Destination address */
-#define TEGRA_GPCDMA_CHAN_DST_PTR 0x010
-
/* High address pointer */
-#define TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR 0x014
#define TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR GENMASK(7, 0)
#define TEGRA_GPCDMA_HIGH_ADDR_DST_PTR GENMASK(23, 16)
/* MC sequence register */
-#define TEGRA_GPCDMA_CHAN_MCSEQ 0x18
#define TEGRA_GPCDMA_MCSEQ_DATA_SWAP BIT(31)
#define TEGRA_GPCDMA_MCSEQ_REQ_COUNT GENMASK(30, 25)
#define TEGRA_GPCDMA_MCSEQ_BURST GENMASK(24, 23)
@@ -101,7 +90,6 @@
#define TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK GENMASK(6, 0)
/* MMIO sequence register */
-#define TEGRA_GPCDMA_CHAN_MMIOSEQ 0x01c
#define TEGRA_GPCDMA_MMIOSEQ_DBL_BUF BIT(31)
#define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH GENMASK(30, 28)
#define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_8 \
@@ -120,17 +108,7 @@
#define TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD GENMASK(18, 16)
#define TEGRA_GPCDMA_MMIOSEQ_MMIO_PROT GENMASK(8, 7)
-/* Channel WCOUNT */
-#define TEGRA_GPCDMA_CHAN_WCOUNT 0x20
-
-/* Transfer count */
-#define TEGRA_GPCDMA_CHAN_XFER_COUNT 0x24
-
-/* DMA byte count status */
-#define TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS 0x28
-
/* Error Status Register */
-#define TEGRA_GPCDMA_CHAN_ERR_STATUS 0x30
#define TEGRA_GPCDMA_CHAN_ERR_TYPE_SHIFT 8
#define TEGRA_GPCDMA_CHAN_ERR_TYPE_MASK 0xF
#define TEGRA_GPCDMA_CHAN_ERR_TYPE(err) ( \
@@ -143,16 +121,6 @@
#define TEGRA_DMA_MC_SLAVE_ERR 0xB
#define TEGRA_DMA_MMIO_SLAVE_ERR 0xA
-/* Fixed Pattern */
-#define TEGRA_GPCDMA_CHAN_FIXED_PATTERN 0x34
-
-#define TEGRA_GPCDMA_CHAN_TZ 0x38
-#define TEGRA_GPCDMA_CHAN_TZ_MMIO_PROT_1 BIT(0)
-#define TEGRA_GPCDMA_CHAN_TZ_MC_PROT_1 BIT(1)
-
-#define TEGRA_GPCDMA_CHAN_SPARE 0x3c
-#define TEGRA_GPCDMA_CHAN_SPARE_EN_LEGACY_FC BIT(16)
-
/*
* If any burst is in flight and DMA paused then this is the time to complete
* on-flight burst and update DMA status register.
@@ -181,18 +149,24 @@ struct tegra_dma_chip_data {
unsigned int nr_channels;
unsigned int channel_reg_size;
unsigned int max_dma_count;
+ const struct tegra_dma_channel_regs *channel_regs;
int (*terminate)(struct tegra_dma_channel *tdc);
};
/* DMA channel registers */
struct tegra_dma_channel_regs {
u32 csr;
- u32 src_ptr;
- u32 dst_ptr;
- u32 high_addr_ptr;
+ u32 status;
+ u32 csre;
+ u32 src;
+ u32 dst;
+ u32 high_addr;
u32 mc_seq;
u32 mmio_seq;
u32 wcount;
+ u32 wxfer;
+ u32 wstatus;
+ u32 err_status;
u32 fixed_pattern;
};
@@ -205,7 +179,14 @@ struct tegra_dma_channel_regs {
*/
struct tegra_dma_sg_req {
unsigned int len;
- struct tegra_dma_channel_regs ch_regs;
+ u32 csr;
+ u32 src;
+ u32 dst;
+ u32 high_addr;
+ u32 mc_seq;
+ u32 mmio_seq;
+ u32 wcount;
+ u32 fixed_pattern;
};
/*
@@ -228,19 +209,20 @@ struct tegra_dma_desc {
* tegra_dma_channel: Channel specific information
*/
struct tegra_dma_channel {
- bool config_init;
- char name[30];
- enum dma_transfer_direction sid_dir;
- enum dma_status status;
- int id;
- int irq;
- int slave_id;
+ const struct tegra_dma_channel_regs *regs;
struct tegra_dma *tdma;
struct virt_dma_chan vc;
struct tegra_dma_desc *dma_desc;
struct dma_slave_config dma_sconfig;
+ enum dma_transfer_direction sid_dir;
+ enum dma_status status;
unsigned int stream_id;
unsigned long chan_base_offset;
+ bool config_init;
+ char name[30];
+ int id;
+ int irq;
+ int slave_id;
};
/*
@@ -288,22 +270,22 @@ static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc)
{
dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n",
tdc->id, tdc->name);
- dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x SRC %x DST %x\n",
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_DST_PTR)
- );
- dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x BSTA %x\n",
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_WCOUNT),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT),
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS)
- );
+ dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x\n",
+ tdc_read(tdc, tdc->regs->csr),
+ tdc_read(tdc, tdc->regs->status),
+ tdc_read(tdc, tdc->regs->csre));
+ dev_dbg(tdc2dev(tdc), "SRC %x DST %x HI ADDR %x\n",
+ tdc_read(tdc, tdc->regs->src),
+ tdc_read(tdc, tdc->regs->dst),
+ tdc_read(tdc, tdc->regs->high_addr));
+ dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x WSTA %x\n",
+ tdc_read(tdc, tdc->regs->mc_seq),
+ tdc_read(tdc, tdc->regs->mmio_seq),
+ tdc_read(tdc, tdc->regs->wcount),
+ tdc_read(tdc, tdc->regs->wxfer),
+ tdc_read(tdc, tdc->regs->wstatus));
dev_dbg(tdc2dev(tdc), "DMA ERR_STA %x\n",
- tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS));
+ tdc_read(tdc, tdc->regs->err_status));
}
static int tegra_dma_sid_reserve(struct tegra_dma_channel *tdc,
@@ -377,13 +359,13 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
int ret;
u32 val;
- val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
+ val = tdc_read(tdc, tdc->regs->csre);
val |= TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+ tdc_write(tdc, tdc->regs->csre, val);
/* Wait until busy bit is de-asserted */
ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
- tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
+ tdc->chan_base_offset + tdc->regs->status,
val,
!(val & TEGRA_GPCDMA_STATUS_BUSY),
TEGRA_GPCDMA_BURST_COMPLETE_TIME,
@@ -419,9 +401,9 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
{
u32 val;
- val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
+ val = tdc_read(tdc, tdc->regs->csre);
val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+ tdc_write(tdc, tdc->regs->csre, val);
tdc->status = DMA_IN_PROGRESS;
}
@@ -456,27 +438,27 @@ static void tegra_dma_disable(struct tegra_dma_channel *tdc)
{
u32 csr, status;
- csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
+ csr = tdc_read(tdc, tdc->regs->csr);
/* Disable interrupts */
csr &= ~TEGRA_GPCDMA_CSR_IE_EOC;
/* Disable DMA */
csr &= ~TEGRA_GPCDMA_CSR_ENB;
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
+ tdc_write(tdc, tdc->regs->csr, csr);
/* Clear interrupt status if it is there */
- status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+ status = tdc_read(tdc, tdc->regs->status);
if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) {
dev_dbg(tdc2dev(tdc), "%s():clearing interrupt\n", __func__);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, status);
+ tdc_write(tdc, tdc->regs->status, status);
}
}
static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
{
struct tegra_dma_desc *dma_desc = tdc->dma_desc;
- struct tegra_dma_channel_regs *ch_regs;
+ struct tegra_dma_sg_req *sg_req;
int ret;
u32 val;
@@ -488,29 +470,29 @@ static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc)
/* Configure next transfer immediately after DMA is busy */
ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
- tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS,
+ tdc->chan_base_offset + tdc->regs->status,
val,
(val & TEGRA_GPCDMA_STATUS_BUSY), 0,
TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT);
if (ret)
return;
- ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
+ sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
+ tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
+ tdc_write(tdc, tdc->regs->src, sg_req->src);
+ tdc_write(tdc, tdc->regs->dst, sg_req->dst);
+ tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
/* Start DMA */
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
- ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
+ tdc_write(tdc, tdc->regs->csr,
+ sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
}
static void tegra_dma_start(struct tegra_dma_channel *tdc)
{
struct tegra_dma_desc *dma_desc = tdc->dma_desc;
- struct tegra_dma_channel_regs *ch_regs;
+ struct tegra_dma_sg_req *sg_req;
struct virt_dma_desc *vdesc;
if (!dma_desc) {
@@ -526,21 +508,21 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc)
tegra_dma_resume(tdc);
}
- ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs;
+ sg_req = &dma_desc->sg_req[dma_desc->sg_idx];
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, 0);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_FIXED_PATTERN, ch_regs->fixed_pattern);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ, ch_regs->mmio_seq);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, ch_regs->mc_seq);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, ch_regs->csr);
+ tdc_write(tdc, tdc->regs->wcount, sg_req->wcount);
+ tdc_write(tdc, tdc->regs->csr, 0);
+ tdc_write(tdc, tdc->regs->src, sg_req->src);
+ tdc_write(tdc, tdc->regs->dst, sg_req->dst);
+ tdc_write(tdc, tdc->regs->high_addr, sg_req->high_addr);
+ tdc_write(tdc, tdc->regs->fixed_pattern, sg_req->fixed_pattern);
+ tdc_write(tdc, tdc->regs->mmio_seq, sg_req->mmio_seq);
+ tdc_write(tdc, tdc->regs->mc_seq, sg_req->mc_seq);
+ tdc_write(tdc, tdc->regs->csr, sg_req->csr);
/* Start DMA */
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR,
- ch_regs->csr | TEGRA_GPCDMA_CSR_ENB);
+ tdc_write(tdc, tdc->regs->csr,
+ sg_req->csr | TEGRA_GPCDMA_CSR_ENB);
}
static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
@@ -601,19 +583,19 @@ static irqreturn_t tegra_dma_isr(int irq, void *dev_id)
u32 status;
/* Check channel error status register */
- status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS);
+ status = tdc_read(tdc, tdc->regs->err_status);
if (status) {
tegra_dma_chan_decode_error(tdc, status);
tegra_dma_dump_chan_regs(tdc);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF);
+ tdc_write(tdc, tdc->regs->err_status, 0xFFFFFFFF);
}
spin_lock(&tdc->vc.lock);
- status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+ status = tdc_read(tdc, tdc->regs->status);
if (!(status & TEGRA_GPCDMA_STATUS_ISE_EOC))
goto irq_done;
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS,
+ tdc_write(tdc, tdc->regs->status,
TEGRA_GPCDMA_STATUS_ISE_EOC);
if (!dma_desc)
@@ -673,10 +655,10 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
* to stop DMA engine from starting any more bursts for
* the given client and wait for in flight bursts to complete
*/
- csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR);
+ csr = tdc_read(tdc, tdc->regs->csr);
csr &= ~(TEGRA_GPCDMA_CSR_REQ_SEL_MASK);
csr |= TEGRA_GPCDMA_CSR_REQ_SEL_UNUSED;
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr);
+ tdc_write(tdc, tdc->regs->csr, csr);
/* Wait for in flight data transfer to finish */
udelay(TEGRA_GPCDMA_BURST_COMPLETE_TIME);
@@ -687,7 +669,7 @@ static int tegra_dma_stop_client(struct tegra_dma_channel *tdc)
ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr +
tdc->chan_base_offset +
- TEGRA_GPCDMA_CHAN_STATUS,
+ tdc->regs->status,
status,
!(status & (TEGRA_GPCDMA_STATUS_CHANNEL_TX |
TEGRA_GPCDMA_STATUS_CHANNEL_RX)),
@@ -739,14 +721,14 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
unsigned int bytes_xfer, residual;
u32 wcount = 0, status;
- wcount = tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT);
+ wcount = tdc_read(tdc, tdc->regs->wxfer);
/*
* Set wcount = 0 if EOC bit is set. The transfer would have
* already completed and the CHAN_XFER_COUNT could have updated
* for the next transfer, specifically in case of cyclic transfers.
*/
- status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS);
+ status = tdc_read(tdc, tdc->regs->status);
if (status & TEGRA_GPCDMA_STATUS_ISE_EOC)
wcount = 0;
@@ -893,7 +875,7 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
/* Configure default priority weight for the channel */
csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
- mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+ mc_seq = tdc_read(tdc, tdc->regs->mc_seq);
/* retain stream-id and clean rest */
mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
@@ -916,16 +898,16 @@ tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value,
dma_desc->sg_count = 1;
sg_req = dma_desc->sg_req;
- sg_req[0].ch_regs.src_ptr = 0;
- sg_req[0].ch_regs.dst_ptr = dest;
- sg_req[0].ch_regs.high_addr_ptr =
+ sg_req[0].src = 0;
+ sg_req[0].dst = dest;
+ sg_req[0].high_addr =
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
- sg_req[0].ch_regs.fixed_pattern = value;
+ sg_req[0].fixed_pattern = value;
/* Word count reg takes value as (N +1) words */
- sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
- sg_req[0].ch_regs.csr = csr;
- sg_req[0].ch_regs.mmio_seq = 0;
- sg_req[0].ch_regs.mc_seq = mc_seq;
+ sg_req[0].wcount = ((len - 4) >> 2);
+ sg_req[0].csr = csr;
+ sg_req[0].mmio_seq = 0;
+ sg_req[0].mc_seq = mc_seq;
sg_req[0].len = len;
dma_desc->cyclic = false;
@@ -961,7 +943,7 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
/* Configure default priority weight for the channel */
csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1);
- mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+ mc_seq = tdc_read(tdc, tdc->regs->mc_seq);
/* retain stream-id and clean rest */
mc_seq &= (TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK) |
(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
@@ -985,17 +967,17 @@ tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest,
dma_desc->sg_count = 1;
sg_req = dma_desc->sg_req;
- sg_req[0].ch_regs.src_ptr = src;
- sg_req[0].ch_regs.dst_ptr = dest;
- sg_req[0].ch_regs.high_addr_ptr =
+ sg_req[0].src = src;
+ sg_req[0].dst = dest;
+ sg_req[0].high_addr =
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32));
- sg_req[0].ch_regs.high_addr_ptr |=
+ sg_req[0].high_addr |=
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32));
/* Word count reg takes value as (N +1) words */
- sg_req[0].ch_regs.wcount = ((len - 4) >> 2);
- sg_req[0].ch_regs.csr = csr;
- sg_req[0].ch_regs.mmio_seq = 0;
- sg_req[0].ch_regs.mc_seq = mc_seq;
+ sg_req[0].wcount = ((len - 4) >> 2);
+ sg_req[0].csr = csr;
+ sg_req[0].mmio_seq = 0;
+ sg_req[0].mc_seq = mc_seq;
sg_req[0].len = len;
dma_desc->cyclic = false;
@@ -1049,7 +1031,7 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
if (flags & DMA_PREP_INTERRUPT)
csr |= TEGRA_GPCDMA_CSR_IE_EOC;
- mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+ mc_seq = tdc_read(tdc, tdc->regs->mc_seq);
/* retain stream-id and clean rest */
mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
@@ -1096,14 +1078,14 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
dma_desc->bytes_req += len;
if (direction == DMA_MEM_TO_DEV) {
- sg_req[i].ch_regs.src_ptr = mem;
- sg_req[i].ch_regs.dst_ptr = apb_ptr;
- sg_req[i].ch_regs.high_addr_ptr =
+ sg_req[i].src = mem;
+ sg_req[i].dst = apb_ptr;
+ sg_req[i].high_addr =
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
} else if (direction == DMA_DEV_TO_MEM) {
- sg_req[i].ch_regs.src_ptr = apb_ptr;
- sg_req[i].ch_regs.dst_ptr = mem;
- sg_req[i].ch_regs.high_addr_ptr =
+ sg_req[i].src = apb_ptr;
+ sg_req[i].dst = mem;
+ sg_req[i].high_addr =
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
}
@@ -1111,10 +1093,10 @@ tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl,
* Word count register takes input in words. Writing a value
* of N into word count register means a req of (N+1) words.
*/
- sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
- sg_req[i].ch_regs.csr = csr;
- sg_req[i].ch_regs.mmio_seq = mmio_seq;
- sg_req[i].ch_regs.mc_seq = mc_seq;
+ sg_req[i].wcount = ((len - 4) >> 2);
+ sg_req[i].csr = csr;
+ sg_req[i].mmio_seq = mmio_seq;
+ sg_req[i].mc_seq = mc_seq;
sg_req[i].len = len;
}
@@ -1186,7 +1168,7 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
mmio_seq |= FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD, 1);
- mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+ mc_seq = tdc_read(tdc, tdc->regs->mc_seq);
/* retain stream-id and clean rest */
mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK;
@@ -1217,24 +1199,24 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_l
for (i = 0; i < period_count; i++) {
mmio_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
if (direction == DMA_MEM_TO_DEV) {
- sg_req[i].ch_regs.src_ptr = mem;
- sg_req[i].ch_regs.dst_ptr = apb_ptr;
- sg_req[i].ch_regs.high_addr_ptr =
+ sg_req[i].src = mem;
+ sg_req[i].dst = apb_ptr;
+ sg_req[i].high_addr =
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32));
} else if (direction == DMA_DEV_TO_MEM) {
- sg_req[i].ch_regs.src_ptr = apb_ptr;
- sg_req[i].ch_regs.dst_ptr = mem;
- sg_req[i].ch_regs.high_addr_ptr =
+ sg_req[i].src = apb_ptr;
+ sg_req[i].dst = mem;
+ sg_req[i].high_addr =
FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32));
}
/*
* Word count register takes input in words. Writing a value
* of N into word count register means a req of (N+1) words.
*/
- sg_req[i].ch_regs.wcount = ((len - 4) >> 2);
- sg_req[i].ch_regs.csr = csr;
- sg_req[i].ch_regs.mmio_seq = mmio_seq;
- sg_req[i].ch_regs.mc_seq = mc_seq;
+ sg_req[i].wcount = ((len - 4) >> 2);
+ sg_req[i].csr = csr;
+ sg_req[i].mmio_seq = mmio_seq;
+ sg_req[i].mc_seq = mc_seq;
sg_req[i].len = len;
mem += len;
@@ -1304,11 +1286,28 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
return chan;
}
+static const struct tegra_dma_channel_regs tegra186_reg_offsets = {
+ .csr = 0x0,
+ .status = 0x4,
+ .csre = 0x8,
+ .src = 0xc,
+ .dst = 0x10,
+ .high_addr = 0x14,
+ .mc_seq = 0x18,
+ .mmio_seq = 0x1c,
+ .wcount = 0x20,
+ .wxfer = 0x24,
+ .wstatus = 0x28,
+ .err_status = 0x30,
+ .fixed_pattern = 0x34,
+};
+
static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
.nr_channels = 32,
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = false,
+ .channel_regs = &tegra186_reg_offsets,
.terminate = tegra_dma_stop_client,
};
@@ -1317,6 +1316,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = true,
+ .channel_regs = &tegra186_reg_offsets,
.terminate = tegra_dma_pause,
};
@@ -1325,6 +1325,7 @@ static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
.channel_reg_size = SZ_64K,
.max_dma_count = SZ_1G,
.hw_support_pause = true,
+ .channel_regs = &tegra186_reg_offsets,
.terminate = tegra_dma_pause_noerr,
};
@@ -1345,7 +1346,7 @@ MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
{
- unsigned int reg_val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ);
+ unsigned int reg_val = tdc_read(tdc, tdc->regs->mc_seq);
reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK);
reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK);
@@ -1353,7 +1354,7 @@ static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id)
reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK, stream_id);
reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK, stream_id);
- tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, reg_val);
+ tdc_write(tdc, tdc->regs->mc_seq, reg_val);
return 0;
}
@@ -1419,6 +1420,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET +
i * cdata->channel_reg_size;
snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i);
+ tdc->regs = cdata->channel_regs;
tdc->tdma = tdma;
tdc->id = i;
tdc->slave_id = -1;
--
2.50.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox