Memory controller hot reset
v3 cover Memory controller hot reset
Tegra's memory controller has a "memory hot reset" functionality that blocks all memory transactions for the memory client, which is required for a proper HW resetting. HW could perform DMA while being reset and this could lead to a system hang or memory corruption, so here comes the memory hot reset that blocks all interactions of HW with memory so that it could be reset safely. Memory hot reset is urgently required for multimedia (on Tegra20 especially), like GPU or video decoder, as it is quite easy to get in a trouble without a proper HW reset.
Changelog:
V3:
Addressed review comments to V2 from Thierry Reding. MC now uses generic reset controller API instead of a custom one, hence DT changes are now involved and so Rob Herring is CC'd for a review.
Added couple minor cleanup/correction patches.
V2:
Basically a re-send of V1 with some minor changes.
Dmitry Osipenko (14):
dt-bindings: arm: tegra: Remove duplicated Tegra30+ MC binding
dt-bindings: memory: tegra: Document #reset-cells property of the
Tegra30 MC
dt-bindings: arm: tegra: Document #reset-cells property of the Tegra20
MC
dt-bindings: memory: tegra: Add hot resets definitions
memory: tegra: Do not handle spurious interrupts
memory: tegra: Setup interrupts mask before requesting IRQ
memory: tegra: Apply interrupts mask per SoC
memory: tegra: Remove unused headers inclusions
memory: tegra: Squash tegra20-mc into common tegra-mc driver
memory: tegra: Introduce memory client hot reset
memory: tegra: Add Tegra124 memory controller hot resets
memory: tegra: Add Tegra114 memory controller hot resets
memory: tegra: Add Tegra30 memory controller hot resets
memory: tegra: Add Tegra20 memory controller hot resets
Thierry Reding (1):
memory: tegra: Add Tegra210 memory controller hot resets
.../bindings/arm/tegra/nvidia,tegra20-mc.txt | 12 +- .../bindings/arm/tegra/nvidia,tegra30-mc.txt | 18 -- .../memory-controllers/nvidia,tegra30-mc.txt | 5 + drivers/memory/Kconfig | 10 - drivers/memory/Makefile | 1 - drivers/memory/tegra/Makefile | 1 + drivers/memory/tegra/mc.c | 358 +++++++++++++++++++-- drivers/memory/tegra/mc.h | 22 ++ drivers/memory/tegra/tegra114.c | 35 ++ drivers/memory/tegra/tegra124.c | 48 +++ drivers/memory/tegra/tegra20.c | 296 +++++++++++++++++ drivers/memory/tegra/tegra210.c | 53 ++- drivers/memory/tegra/tegra30.c | 35 ++ drivers/memory/tegra20-mc.c | 254 --------------- include/dt-bindings/memory/tegra114-mc.h | 19 ++ include/dt-bindings/memory/tegra124-mc.h | 25 ++ include/dt-bindings/memory/tegra20-mc.h | 21 ++ include/dt-bindings/memory/tegra210-mc.h | 31 ++ include/dt-bindings/memory/tegra30-mc.h | 19 ++ include/soc/tegra/mc.h | 37 ++- 20 files changed, 978 insertions(+), 322 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt create mode 100644 drivers/memory/tegra/tegra20.c delete mode 100644 drivers/memory/tegra20-mc.c create mode 100644 include/dt-bindings/memory/tegra20-mc.h
Signature · 1 line
2.16.1
PATCH v3 1/15 dt-bindings: arm: tegra: Remove duplicated Tegra30+ MC binding
There are two bindings for the same Memory Controller. One of the bindings became obsolete long time ago and probably was left unnoticed, remove it for consistency.
--- .../bindings/arm/tegra/nvidia,tegra30-mc.txt | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt deleted +0 -18
@@ -1,18 +0,0 @@ -NVIDIA Tegra30 MC(Memory Controller) - -Required properties: -- compatible : "nvidia,tegra30-mc" -- reg : Should contain 4 register ranges(address and length); see the - example below. Note that the MC registers are interleaved with the - SMMU registers, and hence must be represented as multiple ranges. -- interrupts : Should contain MC General interrupt. - -Example: - memory-controller { - compatible = "nvidia,tegra30-mc"; - reg = <0x7000f000 0x010 - 0x7000f03c 0x1b4 - 0x7000f200 0x028 - 0x7000f284 0x17c>; - interrupts = <0 77 0x04>; - };
Signature · 1 line
2.16.1
Re: [PATCH v3 01/15] dt-bindings: arm: tegra: Remove duplicated Tegra30+ MC binding
Quoted 9 lines · Dmitry Osipenko
There are two bindings for the same Memory Controller. One of the bindings became obsolete long time ago and probably was left unnoticed, remove it for consistency.
Signed-off-by Dmitry Osipenko <[email protected]>--- .../bindings/arm/tegra/nvidia,tegra30-mc.txt | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
PATCH v3 2/15 dt-bindings: memory: tegra: Document #reset-cells property of the Tegra30 MC
In reply to Dmitry OsipenkoMemory Controller has a memory client "hot reset" functionality, which resets the DMA interface of a memory client. So MC is a reset controller in addition to IOMMU. Documentation the new property.
--- .../devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt | 5 +++++ 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt +5 -0
@@ -12,6 +12,9 @@ Required properties: - clock-names: Must include the following entries: - mc: the module's clock input - interrupts: The interrupt outputs from the controller. +- #reset-cells : Should be 1. This cell represents memory client module ID. + The assignments may be found in header file <dt-bindings/memory/tegra30-mc.h> + or in the TRM documentation. Required properties for Tegra30, Tegra114, Tegra124, Tegra132 and Tegra210: - #iommu-cells: Should be 1. The single cell of the IOMMU specifier defines
@@ -72,12 +75,14 @@ Example SoC include file: interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; #iommu-cells = <1>; + #reset-cells = <1>; }; sdhci@700b0000 { compatible = "nvidia,tegra124-sdhci"; ... iommus = <&mc TEGRA_SWGROUP_SDMMC1A>; + resets = <&mc TEGRA124_MC_RESET_SDMMC1>; }; };
Signature · 1 line
2.16.1
Re: [PATCH v3 02/15] dt-bindings: memory: tegra: Document #reset-cells property of the Tegra30 MC
Quoted 8 lines · Dmitry Osipenko
Memory Controller has a memory client "hot reset" functionality, which resets the DMA interface of a memory client. So MC is a reset controller in addition to IOMMU. Documentation the new property.
Signed-off-by Dmitry Osipenko <[email protected]>--- .../devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt | 5 +++++ 1 file changed, 5 insertions(+)
PATCH v3 3/15 dt-bindings: arm: tegra: Document #reset-cells property of the Tegra20 MC
In reply to Dmitry OsipenkoMemory Controller has a memory client "hot reset" functionality, which resets the DMA interface of a memory client, so MC is a reset controller. Documentation the new property.
--- .../devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt +11 -1
@@ -6,11 +6,21 @@ Required properties: example below. Note that the MC registers are interleaved with the GART registers, and hence must be represented as multiple ranges. - interrupts : Should contain MC General interrupt. +- #reset-cells : Should be 1. This cell represents memory client module ID. + The assignments may be found in header file <dt-bindings/memory/tegra20-mc.h> + or in the TRM documentation. Example: - memory-controller@7000f000 { + mc: memory-controller@7000f000 { compatible = "nvidia,tegra20-mc"; reg = <0x7000f000 0x024 0x7000f03c 0x3c4>; interrupts = <0 77 0x04>; + #reset-cells = <1>; + }; + + video-codec@6001a000 { + compatible = "nvidia,tegra20-vde"; + ... + resets = <&mc TEGRA20_MC_RESET_VDE>; };
Signature · 1 line
2.16.1
Re: [PATCH v3 03/15] dt-bindings: arm: tegra: Document #reset-cells property of the Tegra20 MC
Quoted 8 lines · Dmitry Osipenko
Memory Controller has a memory client "hot reset" functionality, which resets the DMA interface of a memory client, so MC is a reset controller. Documentation the new property.
Signed-off-by Dmitry Osipenko <[email protected]>--- .../devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
PATCH v3 4/15 dt-bindings: memory: tegra: Add hot resets definitions
In reply to Dmitry OsipenkoAdd definitions for the Tegra20+ memory controller hot resets.
--- include/dt-bindings/memory/tegra114-mc.h | 19 +++++++++++++++++++ include/dt-bindings/memory/tegra124-mc.h | 25 +++++++++++++++++++++++++ include/dt-bindings/memory/tegra20-mc.h | 21 +++++++++++++++++++++ include/dt-bindings/memory/tegra210-mc.h | 31 +++++++++++++++++++++++++++++++ include/dt-bindings/memory/tegra30-mc.h | 19 +++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 include/dt-bindings/memory/tegra20-mc.h
include/dt-bindings/memory/tegra114-mc.h +19 -0
@@ -23,4 +23,23 @@#define TEGRA_SWGROUP_EMUCIF 18#define TEGRA_SWGROUP_TSEC 19 +#define TEGRA114_MC_RESET_AFI 0 +#define TEGRA114_MC_RESET_AVPC 1 +#define TEGRA114_MC_RESET_DC 2 +#define TEGRA114_MC_RESET_DCB 3 +#define TEGRA114_MC_RESET_EPP 4 +#define TEGRA114_MC_RESET_2D 5 +#define TEGRA114_MC_RESET_HC 6 +#define TEGRA114_MC_RESET_HDA 7 +#define TEGRA114_MC_RESET_ISP 8 +#define TEGRA114_MC_RESET_MPCORE 9 +#define TEGRA114_MC_RESET_MPCORELP 10 +#define TEGRA114_MC_RESET_MPE 11 +#define TEGRA114_MC_RESET_3D 12 +#define TEGRA114_MC_RESET_3D2 13 +#define TEGRA114_MC_RESET_PPCS 14 +#define TEGRA114_MC_RESET_SATA 15 +#define TEGRA114_MC_RESET_VDE 16 +#define TEGRA114_MC_RESET_VI 17 +#endif
include/dt-bindings/memory/tegra124-mc.h +25 -0
@@ -29,4 +29,29 @@#define TEGRA_SWGROUP_VIC 24#define TEGRA_SWGROUP_VI 25 +#define TEGRA124_MC_RESET_AFI 0 +#define TEGRA124_MC_RESET_AVPC 1 +#define TEGRA124_MC_RESET_DC 2 +#define TEGRA124_MC_RESET_DCB 3 +#define TEGRA124_MC_RESET_HC 4 +#define TEGRA124_MC_RESET_HDA 5 +#define TEGRA124_MC_RESET_ISP2 6 +#define TEGRA124_MC_RESET_MPCORE 7 +#define TEGRA124_MC_RESET_MPCORELP 8 +#define TEGRA124_MC_RESET_MSENC 9 +#define TEGRA124_MC_RESET_PPCS 10 +#define TEGRA124_MC_RESET_SATA 11 +#define TEGRA124_MC_RESET_VDE 12 +#define TEGRA124_MC_RESET_VI 13 +#define TEGRA124_MC_RESET_VIC 14 +#define TEGRA124_MC_RESET_XUSB_HOST 15 +#define TEGRA124_MC_RESET_XUSB_DEV 16 +#define TEGRA124_MC_RESET_TSEC 17 +#define TEGRA124_MC_RESET_SDMMC1 18 +#define TEGRA124_MC_RESET_SDMMC2 19 +#define TEGRA124_MC_RESET_SDMMC3 20 +#define TEGRA124_MC_RESET_SDMMC4 21 +#define TEGRA124_MC_RESET_ISP2B 22 +#define TEGRA124_MC_RESET_GPU 23 +#endif
include/dt-bindings/memory/tegra20-mc.h new file +21 -0
@@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef DT_BINDINGS_MEMORY_TEGRA20_MC_H +#define DT_BINDINGS_MEMORY_TEGRA20_MC_H + +#define TEGRA20_MC_RESET_AVPC 0 +#define TEGRA20_MC_RESET_DC 1 +#define TEGRA20_MC_RESET_DCB 2 +#define TEGRA20_MC_RESET_EPP 3 +#define TEGRA20_MC_RESET_2D 4 +#define TEGRA20_MC_RESET_HC 5 +#define TEGRA20_MC_RESET_ISP 6 +#define TEGRA20_MC_RESET_MPCORE 7 +#define TEGRA20_MC_RESET_MPEA 8 +#define TEGRA20_MC_RESET_MPEB 9 +#define TEGRA20_MC_RESET_MPEC 10 +#define TEGRA20_MC_RESET_3D 11 +#define TEGRA20_MC_RESET_PPCS 12 +#define TEGRA20_MC_RESET_VDE 13 +#define TEGRA20_MC_RESET_VI 14 + +#endif
include/dt-bindings/memory/tegra210-mc.h +31 -0
@@ -34,4 +34,35 @@#define TEGRA_SWGROUP_ETR 29#define TEGRA_SWGROUP_TSECB 30 +#define TEGRA210_MC_RESET_AFI 0 +#define TEGRA210_MC_RESET_AVPC 1 +#define TEGRA210_MC_RESET_DC 2 +#define TEGRA210_MC_RESET_DCB 3 +#define TEGRA210_MC_RESET_HC 4 +#define TEGRA210_MC_RESET_HDA 5 +#define TEGRA210_MC_RESET_ISP2 6 +#define TEGRA210_MC_RESET_MPCORE 7 +#define TEGRA210_MC_RESET_NVENC 8 +#define TEGRA210_MC_RESET_PPCS 9 +#define TEGRA210_MC_RESET_SATA 10 +#define TEGRA210_MC_RESET_VI 11 +#define TEGRA210_MC_RESET_VIC 12 +#define TEGRA210_MC_RESET_XUSB_HOST 13 +#define TEGRA210_MC_RESET_XUSB_DEV 14 +#define TEGRA210_MC_RESET_A9AVP 15 +#define TEGRA210_MC_RESET_TSEC 16 +#define TEGRA210_MC_RESET_SDMMC1 17 +#define TEGRA210_MC_RESET_SDMMC2 18 +#define TEGRA210_MC_RESET_SDMMC3 19 +#define TEGRA210_MC_RESET_SDMMC4 20 +#define TEGRA210_MC_RESET_ISP2B 21 +#define TEGRA210_MC_RESET_GPU 22 +#define TEGRA210_MC_RESET_NVDEC 23 +#define TEGRA210_MC_RESET_APE 24 +#define TEGRA210_MC_RESET_SE 25 +#define TEGRA210_MC_RESET_NVJPG 26 +#define TEGRA210_MC_RESET_AXIAP 27 +#define TEGRA210_MC_RESET_ETR 28 +#define TEGRA210_MC_RESET_TSECB 29 +#endif
include/dt-bindings/memory/tegra30-mc.h +19 -0
@@ -22,4 +22,23 @@#define TEGRA_SWGROUP_MPCORE 17#define TEGRA_SWGROUP_ISP 18 +#define TEGRA30_MC_RESET_AFI 0 +#define TEGRA30_MC_RESET_AVPC 1 +#define TEGRA30_MC_RESET_DC 2 +#define TEGRA30_MC_RESET_DCB 3 +#define TEGRA30_MC_RESET_EPP 4 +#define TEGRA30_MC_RESET_2D 5 +#define TEGRA30_MC_RESET_HC 6 +#define TEGRA30_MC_RESET_HDA 7 +#define TEGRA30_MC_RESET_ISP 8 +#define TEGRA30_MC_RESET_MPCORE 9 +#define TEGRA30_MC_RESET_MPCORELP 10 +#define TEGRA30_MC_RESET_MPE 11 +#define TEGRA30_MC_RESET_3D 12 +#define TEGRA30_MC_RESET_3D2 13 +#define TEGRA30_MC_RESET_PPCS 14 +#define TEGRA30_MC_RESET_SATA 15 +#define TEGRA30_MC_RESET_VDE 16 +#define TEGRA30_MC_RESET_VI 17 +#endif
Signature · 1 line
2.16.1
Re: [PATCH v3 04/15] dt-bindings: memory: tegra: Add hot resets definitions
Quoted 11 lines · Dmitry Osipenko
Add definitions for the Tegra20+ memory controller hot resets.
Signed-off-by Dmitry Osipenko <[email protected]>--- include/dt-bindings/memory/tegra114-mc.h | 19 +++++++++++++++++++ include/dt-bindings/memory/tegra124-mc.h | 25 +++++++++++++++++++++++++ include/dt-bindings/memory/tegra20-mc.h | 21 +++++++++++++++++++++ include/dt-bindings/memory/tegra210-mc.h | 31 +++++++++++++++++++++++++++++++ include/dt-bindings/memory/tegra30-mc.h | 19 +++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 include/dt-bindings/memory/tegra20-mc.h
PATCH v3 5/15 memory: tegra: Do not handle spurious interrupts
In reply to Dmitry OsipenkoThe ISR reads interrupts-enable mask, but doesn't utilize it. Apply the mask to the interrupt status and don't handle interrupts that MC driver haven't asked for. Kernel would disable spurious MC IRQ and report the error. This would happen only in a case of a very severe bug.
--- drivers/memory/tegra/mc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/memory/tegra/mc.c +4 -1
@@ -252,8 +252,11 @@ static irqreturn_t tegra_mc_irq(int irq, void *data)unsigned int bit;/* mask all interrupts to avoid flooding */ - status =mc_readl (mc,MC_INTSTATUS ); mask =mc_readl (mc,MC_INTMASK ); + status =mc_readl (mc,MC_INTSTATUS ) & mask; + +if (!status) +return IRQ_NONE ;for_each_set_bit (bit, &status,32 ) {const char *error = status_names[bit] ?:"unknown" ;
Signature · 1 line
2.16.1
PATCH v3 6/15 memory: tegra: Setup interrupts mask before requesting IRQ
In reply to Dmitry OsipenkoThis avoids unwanted interrupt during MC driver probe.
--- drivers/memory/tegra/mc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/memory/tegra/mc.c +8 -8
@@ -407,14 +407,6 @@ static int tegra_mc_probe(struct platform_device *pdev)return mc->irq; } - err =devm_request_irq (&pdev->dev, mc->irq, tegra_mc_irq,IRQF_SHARED , -dev_name (&pdev->dev), mc); -if (err <0 ) { -dev_err (&pdev->dev,"failed to request IRQ#%u: %d\n" , mc->irq, - err); -return err; - } -WARN (!mc->soc->client_id_mask,"Missing client ID mask for this SoC\n" ); value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
@@ -423,6 +415,14 @@ static int tegra_mc_probe(struct platform_device *pdev)mc_writel (mc, value,MC_INTMASK ); + err =devm_request_irq (&pdev->dev, mc->irq, tegra_mc_irq,IRQF_SHARED , +dev_name (&pdev->dev), mc); +if (err <0 ) { +dev_err (&pdev->dev,"failed to request IRQ#%u: %d\n" , mc->irq, + err); +return err; + } +return 0 ; }
Signature · 1 line
2.16.1
PATCH v3 7/15 memory: tegra: Apply interrupts mask per SoC
In reply to Dmitry OsipenkoCurrently we are enabling handling of interrupts specific to Tegra124+ which happen to overlap with previous generations. Let's specify interrupts mask per SoC generation for consistency and in a preparation of squashing of Tegra20 driver into the common one that will enable handling of GART faults which may be undesirable by newer generations.
--- drivers/memory/tegra/mc.c | 21 +++------------------ drivers/memory/tegra/mc.h | 9 +++++++++ drivers/memory/tegra/tegra114.c | 2 ++ drivers/memory/tegra/tegra124.c | 6 ++++++ drivers/memory/tegra/tegra210.c | 3 +++ drivers/memory/tegra/tegra30.c | 2 ++ include/soc/tegra/mc.h | 2 ++ 7 files changed, 27 insertions(+), 18 deletions(-)
drivers/memory/tegra/mc.c +3 -18
@@ -20,14 +20,6 @@#include "mc.h" #define MC_INTSTATUS 0x000 -#define MC_INT_DECERR_MTS (1 << 16) -#define MC_INT_SECERR_SEC (1 << 13) -#define MC_INT_DECERR_VPR (1 << 12) -#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11) -#define MC_INT_INVALID_SMMU_PAGE (1 << 10) -#define MC_INT_ARBITRATION_EMEM (1 << 9) -#define MC_INT_SECURITY_VIOLATION (1 << 8) -#define MC_INT_DECERR_EMEM (1 << 6)#define MC_INTMASK 0x004
@@ -248,13 +240,11 @@ static const char *const error_names[8] = {static irqreturn_t tegra_mc_irq (int irq,void *data) {struct tegra_mc *mc = data; -unsigned long status, mask; +unsigned long status;unsigned int bit;/* mask all interrupts to avoid flooding */ - mask =mc_readl (mc,MC_INTMASK ); - status =mc_readl (mc,MC_INTSTATUS ) & mask; - + status =mc_readl (mc,MC_INTSTATUS ) & mc->soc->intmask;if (!status)return IRQ_NONE ;
@@ -349,7 +339,6 @@ static int tegra_mc_probe(struct platform_device *pdev)const struct of_device_id *match;struct resource *res;struct tegra_mc *mc; -u32 value;int err; match =of_match_node (tegra_mc_of_match, pdev->dev.of_node);
@@ -409,11 +398,7 @@ static int tegra_mc_probe(struct platform_device *pdev)WARN (!mc->soc->client_id_mask,"Missing client ID mask for this SoC\n" ); - value =MC_INT_DECERR_MTS |MC_INT_SECERR_SEC |MC_INT_DECERR_VPR | -MC_INT_INVALID_APB_ASID_UPDATE |MC_INT_INVALID_SMMU_PAGE | -MC_INT_SECURITY_VIOLATION |MC_INT_DECERR_EMEM ; - -mc_writel (mc, value,MC_INTMASK ); +mc_writel (mc, mc->soc->intmask,MC_INTMASK ); err =devm_request_irq (&pdev->dev, mc->irq, tegra_mc_irq,IRQF_SHARED ,dev_name (&pdev->dev), mc);
drivers/memory/tegra/mc.h +9 -0
@@ -14,6 +14,15 @@#include <soc/tegra/mc.h> +#define MC_INT_DECERR_MTS (1 << 16) +#define MC_INT_SECERR_SEC (1 << 13) +#define MC_INT_DECERR_VPR (1 << 12) +#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11) +#define MC_INT_INVALID_SMMU_PAGE (1 << 10) +#define MC_INT_ARBITRATION_EMEM (1 << 9) +#define MC_INT_SECURITY_VIOLATION (1 << 8) +#define MC_INT_DECERR_EMEM (1 << 6) +static inline u32 mc_readl (struct tegra_mc *mc,unsigned long offset) {return readl (mc->regs + offset);
drivers/memory/tegra/tegra114.c +2 -0
@@ -945,4 +945,6 @@ const struct tegra_mc_soc tegra114_mc_soc = { .atom_size = 32, .client_id_mask = 0x7f, .smmu = &tegra114_smmu_soc, + .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, };
drivers/memory/tegra/tegra124.c +6 -0
@@ -1035,6 +1035,9 @@ const struct tegra_mc_soc tegra124_mc_soc = { .smmu = &tegra124_smmu_soc, .emem_regs = tegra124_mc_emem_regs, .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs), + .intmask =MC_INT_DECERR_MTS |MC_INT_SECERR_SEC |MC_INT_DECERR_VPR | +MC_INT_INVALID_APB_ASID_UPDATE |MC_INT_INVALID_SMMU_PAGE | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, };#endif /* CONFIG_ARCH_TEGRA_124_SOC */
@@ -1059,5 +1062,8 @@ const struct tegra_mc_soc tegra132_mc_soc = { .atom_size = 32, .client_id_mask = 0x7f, .smmu = &tegra132_smmu_soc, + .intmask =MC_INT_DECERR_MTS |MC_INT_SECERR_SEC |MC_INT_DECERR_VPR | +MC_INT_INVALID_APB_ASID_UPDATE |MC_INT_INVALID_SMMU_PAGE | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, };#endif /* CONFIG_ARCH_TEGRA_132_SOC */
drivers/memory/tegra/tegra210.c +3 -0
@@ -1092,4 +1092,7 @@ const struct tegra_mc_soc tegra210_mc_soc = { .atom_size = 64, .client_id_mask = 0xff, .smmu = &tegra210_smmu_soc, + .intmask =MC_INT_DECERR_MTS |MC_INT_SECERR_SEC |MC_INT_DECERR_VPR | +MC_INT_INVALID_APB_ASID_UPDATE |MC_INT_INVALID_SMMU_PAGE | + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, };
drivers/memory/tegra/tegra30.c +2 -0
@@ -967,4 +967,6 @@ const struct tegra_mc_soc tegra30_mc_soc = { .atom_size = 16, .client_id_mask = 0x7f, .smmu = &tegra30_smmu_soc, + .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, };
include/soc/tegra/mc.h +2 -0
@@ -108,6 +108,8 @@ struct tegra_mc_soc {u8 client_id_mask;const struct tegra_smmu_soc *smmu; + +u32 intmask; };struct tegra_mc {
Signature · 1 line
2.16.1
PATCH v3 8/15 memory: tegra: Remove unused headers inclusions
In reply to Dmitry OsipenkoTegra210 contains some unused leftover headers, remove them for consistency.
--- drivers/memory/tegra/tegra210.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/memory/tegra/tegra210.c +0 -5
@@ -6,11 +6,6 @@* published by the Free Software Foundation. */ -#include <linux/of.h> -#include <linux/mm.h> - -#include <asm/cacheflush.h> -#include <dt-bindings/memory/tegra210-mc.h> #include "mc.h"
Signature · 1 line
2.16.1
PATCH v3 9/15 memory: tegra: Squash tegra20-mc into common tegra-mc driver
In reply to Dmitry OsipenkoTegra30+ has some minor differences in registers / bits layout compared to Tegra20. Let's squash Tegra20 driver into the common tegra-mc driver in a preparation for the upcoming MC hot reset controls implementation, avoiding code duplication.
--- drivers/memory/Kconfig | 10 -- drivers/memory/Makefile | 1 - drivers/memory/tegra/Makefile | 1 + drivers/memory/tegra/mc.c | 120 +++++++++++++++++-- drivers/memory/tegra/mc.h | 11 ++ drivers/memory/tegra/tegra20.c | 178 +++++++++++++++++++++++++++++ drivers/memory/tegra20-mc.c | 254 ----------------------------------------- include/soc/tegra/mc.h | 2 +- 8 files changed, 299 insertions(+), 278 deletions(-) create mode 100644 drivers/memory/tegra/tegra20.c delete mode 100644 drivers/memory/tegra20-mc.c
drivers/memory/Kconfig +0 -10
@@ -104,16 +104,6 @@ config MVEBU_DEVBUS Armada 370 and Armada XP. This controller allows to handle flash devices such as NOR, NAND, SRAM, and FPGA. -config TEGRA20_MC - bool "Tegra20 Memory Controller(MC) driver" - default y - depends on ARCH_TEGRA_2x_SOC - help - This driver is for the Memory Controller(MC) module available - in Tegra20 SoCs, mainly for a address translation fault - analysis, especially for IOMMU/GART(Graphics Address - Relocation Table) module. - config FSL_CORENET_CF tristate "Freescale CoreNet Error Reporting" depends on FSL_SOC_BOOKE
drivers/memory/Makefile +0 -1
@@ -16,7 +16,6 @@ obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o obj-$(CONFIG_FSL_IFC) += fsl_ifc.o obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o -obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o obj-$(CONFIG_MTK_SMI) += mtk-smi.o obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o
drivers/memory/tegra/Makefile +1 -0
@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 tegra-mc-y := mc.o +tegra-mc-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
drivers/memory/tegra/mc.c +108 -12
162 lines not on this page · raw message
drivers/memory/tegra/mc.h +11 -0
@@ -21,19 +21,30 @@#define MC_INT_INVALID_SMMU_PAGE (1 << 10)#define MC_INT_ARBITRATION_EMEM (1 << 9)#define MC_INT_SECURITY_VIOLATION (1 << 8) +#define MC_INT_INVALID_GART_PAGE (1 << 7)#define MC_INT_DECERR_EMEM (1 << 6)static inline u32 mc_readl (struct tegra_mc *mc,unsigned long offset) { +if (mc->regs2 && offset >=0x24 ) +return readl (mc->regs2 + offset -0x3c ); +return readl (mc->regs + offset); }static inline void mc_writel (struct tegra_mc *mc,u32 value,unsigned long offset) { +if (mc->regs2 && offset >=0x24 ) +return writel (value, mc->regs2 + offset -0x3c ); +writel (value, mc->regs + offset); } +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +extern const struct tegra_mc_soc tegra20_mc_soc; +#endif +#ifdef CONFIG_ARCH_TEGRA_3x_SOCextern const struct tegra_mc_soc tegra30_mc_soc;#endif
drivers/memory/tegra/tegra20.c new file +178 -0
178 lines not on this page · raw message
drivers/memory/tegra20-mc.c deleted +0 -254
254 lines not on this page · raw message
include/soc/tegra/mc.h +1 -1
@@ -115,7 +115,7 @@ struct tegra_mc_soc {struct tegra_mc {struct device *dev;struct tegra_smmu *smmu; -void __iomem *regs; +void __iomem *regs, *regs2;struct clk *clk;int irq;
Signature · 1 line
2.16.1
PATCH v3 10/15 memory: tegra: Introduce memory client hot reset
In reply to Dmitry OsipenkoIn order to reset busy HW properly, memory controller needs to be involved, otherwise it is possible to get corrupted memory or hang machine if HW was reset during DMA. Introduce memory client 'hot reset' that will be used for resetting of busy HW.
--- drivers/memory/tegra/mc.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/memory/tegra/mc.h | 2 + include/soc/tegra/mc.h | 33 ++++++++ 3 files changed, 245 insertions(+)
drivers/memory/tegra/mc.c +210 -0
@@ -7,6 +7,7 @@*/ #include <linux/clk.h> +#include <linux/delay.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h>
@@ -72,6 +73,207 @@ static const struct of_device_id tegra_mc_of_match[] = { };MODULE_DEVICE_TABLE (of, tegra_mc_of_match); +static int terga_mc_block_dma_common (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +unsigned long flags; +u32 value; + +spin_lock_irqsave (&mc->lock, flags); + + value =mc_readl (mc, rst->control) |BIT (rst->bit); +mc_writel (mc, value, rst->control); + +spin_unlock_irqrestore (&mc->lock, flags); + +return 0 ; +} + +static bool terga_mc_dma_idling_common (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +return (mc_readl (mc, rst->status) &BIT (rst->bit)) !=0 ; +} + +static int terga_mc_unblock_dma_common (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +unsigned long flags; +u32 value; + +spin_lock_irqsave (&mc->lock, flags); + + value =mc_readl (mc, rst->control) & ~BIT (rst->bit); +mc_writel (mc, value, rst->control); + +spin_unlock_irqrestore (&mc->lock, flags); + +return 0 ; +} + +static int terga_mc_reset_status_common (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +return (mc_readl (mc, rst->control) &BIT (rst->bit)) !=0 ; +} + +const struct tegra_mc_reset_ops terga_mc_resets_ops_common = { + .block_dma = terga_mc_block_dma_common, + .dma_idling = terga_mc_dma_idling_common, + .unblock_dma = terga_mc_unblock_dma_common, + .reset_status = terga_mc_reset_status_common, +}; + +static inline struct tegra_mc *reset_to_mc (struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct tegra_mc, reset); +} + +static const struct tegra_mc_reset *tegra_mc_reset_find (struct tegra_mc *mc, +unsigned long id) +{ +unsigned int i; + +for (i =0 ; i < mc->soc->num_resets; i++) +if (mc->soc->resets[i].id == id) +return &mc->soc->resets[i]; + +return NULL ; +} + +static int tegra_mc_hotreset_assert (struct reset_controller_dev *rcdev, +unsigned long id) +{ +struct tegra_mc *mc =reset_to_mc (rcdev); +const struct tegra_mc_reset_ops *rst_ops; +const struct tegra_mc_reset *rst; +int retries =500 ; +int err; + + rst =tegra_mc_reset_find (mc, id); +if (!rst) +return -ENODEV ; + + rst_ops = mc->soc->resets_ops; +if (!rst_ops) +return -ENODEV ; + +if (rst_ops->block_dma) { +/* block clients DMA requests */ + err = rst_ops->block_dma (mc, rst); +if (err) { +dev_err (mc->dev,"Failed to block %s DMA: %d\n" , + rst->name, err); +return err; + } + } + +if (rst_ops->dma_idling) { +/* wait for completion of the outstanding DMA requests */ +while (!rst_ops->dma_idling (mc, rst)) { +if (!retries--) { +dev_err (mc->dev,"Failed to flush %s DMA\n" , + rst->name); +return -EBUSY ; + } + +usleep_range (10 ,100 ); + } + } + +if (rst_ops->hotreset_assert) { +/* clear clients DMA requests sitting before arbitration */ + err = rst_ops->hotreset_assert (mc, rst); +if (err) { +dev_err (mc->dev,"Failed to hot reset %s: %d\n" , + rst->name, err); +return err; + } + } + +return 0 ; +} + +static int tegra_mc_hotreset_deassert (struct reset_controller_dev *rcdev, +unsigned long id) +{ +struct tegra_mc *mc =reset_to_mc (rcdev); +const struct tegra_mc_reset_ops *rst_ops; +const struct tegra_mc_reset *rst; +int err; + + rst =tegra_mc_reset_find (mc, id); +if (!rst) +return -ENODEV ; + + rst_ops = mc->soc->resets_ops; +if (!rst_ops) +return -ENODEV ; + +if (rst_ops->hotreset_deassert) { +/* take out client from hot reset */ + err = rst_ops->hotreset_deassert (mc, rst); +if (err) { +dev_err (mc->dev,"Failed to deassert hot reset %s: %d\n" , + rst->name, err); +return err; + } + } + +if (rst_ops->unblock_dma) { +/* allow new DMA requests to proceed to arbitration */ + err = rst_ops->unblock_dma (mc, rst); +if (err) { +dev_err (mc->dev,"Failed to unblock %s DMA : %d\n" , + rst->name, err); +return err; + } + } + +return 0 ; +} + +static int tegra_mc_hotreset_status (struct reset_controller_dev *rcdev, +unsigned long id) +{ +struct tegra_mc *mc =reset_to_mc (rcdev); +const struct tegra_mc_reset_ops *rst_ops; +const struct tegra_mc_reset *rst; + + rst =tegra_mc_reset_find (mc, id); +if (!rst) +return -ENODEV ; + + rst_ops = mc->soc->resets_ops; +if (!rst_ops) +return -ENODEV ; + +return rst_ops->reset_status (mc, rst); +} + +static const struct reset_control_ops tegra_mc_reset_ops = { + .assert = tegra_mc_hotreset_assert, + .deassert = tegra_mc_hotreset_deassert, + .status = tegra_mc_hotreset_status, +}; + +static int tegra_mc_reset_setup (struct tegra_mc *mc) +{ +int err; + + mc->reset.ops = &tegra_mc_reset_ops; + mc->reset.owner =THIS_MODULE ; + mc->reset.of_node = mc->dev->of_node; + mc->reset.of_reset_n_cells =1 ; + mc->reset.nr_resets = mc->soc->num_resets; + + err =reset_controller_register (&mc->reset); +if (err <0 ) +return err; + +return 0 ; +} +static int tegra_mc_setup_latency_allowance (struct tegra_mc *mc) {unsigned long long tick;
@@ -432,6 +634,7 @@ static int tegra_mc_probe(struct platform_device *pdev)return -ENOMEM ;platform_set_drvdata (pdev, mc); +spin_lock_init (&mc->lock); mc->soc = match->data; mc->dev = &pdev->dev;
@@ -486,6 +689,13 @@ static int tegra_mc_probe(struct platform_device *pdev) } } + err =tegra_mc_reset_setup (mc); +if (err <0 ) { +dev_err (&pdev->dev,"failed to register reset controller: %d\n" , + err); +return err; + } + mc->irq =platform_get_irq (pdev,0 );if (mc->irq <0 ) {dev_err (&pdev->dev,"interrupt not specified\n" );
drivers/memory/tegra/mc.h +2 -0
@@ -41,6 +41,8 @@ static inline void mc_writel(struct tegra_mc *mc, u32 value,writel (value, mc->regs + offset); } +extern const struct tegra_mc_reset_ops terga_mc_resets_ops_common; +#ifdef CONFIG_ARCH_TEGRA_2x_SOCextern const struct tegra_mc_soc tegra20_mc_soc;#endif
include/soc/tegra/mc.h +33 -0
@@ -9,6 +9,7 @@#ifndef __SOC_TEGRA_MC_H__#define __SOC_TEGRA_MC_H__ +#include <linux/reset-controller.h> #include <linux/types.h> struct clk ;
@@ -95,6 +96,30 @@ static inline void tegra_smmu_remove(struct tegra_smmu *smmu) }#endif +struct tegra_mc_reset { +const char *name; +unsigned long id; +unsigned int control; +unsigned int status; +unsigned int reset; +unsigned int bit; +}; + +struct tegra_mc_reset_ops { +int (*hotreset_assert)(struct tegra_mc *mc, +const struct tegra_mc_reset *rst); +int (*hotreset_deassert)(struct tegra_mc *mc, +const struct tegra_mc_reset *rst); +int (*block_dma)(struct tegra_mc *mc, +const struct tegra_mc_reset *rst); +bool (*dma_idling)(struct tegra_mc *mc, +const struct tegra_mc_reset *rst); +int (*unblock_dma)(struct tegra_mc *mc, +const struct tegra_mc_reset *rst); +int (*reset_status)(struct tegra_mc *mc, +const struct tegra_mc_reset *rst); +}; +struct tegra_mc_soc {const struct tegra_mc_client *clients;unsigned int num_clients;
@@ -110,6 +135,10 @@ struct tegra_mc_soc {const struct tegra_smmu_soc *smmu;u32 intmask; + +const struct tegra_mc_reset_ops *resets_ops; +const struct tegra_mc_reset *resets; +unsigned int num_resets; };struct tegra_mc {
@@ -124,6 +153,10 @@ struct tegra_mc {struct tegra_mc_timing *timings;unsigned int num_timings; + +struct reset_controller_dev reset; + +spinlock_t lock; };void tegra_mc_write_emem_configuration (struct tegra_mc *mc,unsigned long rate);
Signature · 1 line
2.16.1
PATCH v3 11/15 memory: tegra: Add Tegra210 memory controller hot resets
From: Thierry Reding <[email protected]>
Define the table of memory controller hot resets for Tegra210.
--- drivers/memory/tegra/tegra210.c | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
drivers/memory/tegra/tegra210.c +45 -0
@@ -1080,6 +1080,48 @@ static const struct tegra_smmu_soc tegra210_smmu_soc = { .num_asids = 128, }; +#define TEGRA210_MC_RESET (_name, _control, _status, _bit) \ + { \ + .name = #_name, \ + .id = TEGRA210_MC_RESET_##_name, \ + .control = _control, \ + .status = _status, \ + .bit = _bit, \ + } + +static const struct tegra_mc_reset tegra210_mc_resets[] = { +TEGRA210_MC_RESET (AFI ,0x200 ,0x204 ,0 ), +TEGRA210_MC_RESET (AVPC ,0x200 ,0x204 ,1 ), +TEGRA210_MC_RESET (DC ,0x200 ,0x204 ,2 ), +TEGRA210_MC_RESET (DCB ,0x200 ,0x204 ,3 ), +TEGRA210_MC_RESET (HC ,0x200 ,0x204 ,6 ), +TEGRA210_MC_RESET (HDA ,0x200 ,0x204 ,7 ), +TEGRA210_MC_RESET (ISP2 ,0x200 ,0x204 ,8 ), +TEGRA210_MC_RESET (MPCORE ,0x200 ,0x204 ,9 ), +TEGRA210_MC_RESET (NVENC ,0x200 ,0x204 ,11 ), +TEGRA210_MC_RESET (PPCS ,0x200 ,0x204 ,14 ), +TEGRA210_MC_RESET (SATA ,0x200 ,0x204 ,15 ), +TEGRA210_MC_RESET (VI ,0x200 ,0x204 ,17 ), +TEGRA210_MC_RESET (VIC ,0x200 ,0x204 ,18 ), +TEGRA210_MC_RESET (XUSB_HOST ,0x200 ,0x204 ,19 ), +TEGRA210_MC_RESET (XUSB_DEV ,0x200 ,0x204 ,20 ), +TEGRA210_MC_RESET (A9AVP ,0x200 ,0x204 ,21 ), +TEGRA210_MC_RESET (TSEC ,0x200 ,0x204 ,22 ), +TEGRA210_MC_RESET (SDMMC1 ,0x200 ,0x204 ,29 ), +TEGRA210_MC_RESET (SDMMC2 ,0x200 ,0x204 ,30 ), +TEGRA210_MC_RESET (SDMMC3 ,0x200 ,0x204 ,31 ), +TEGRA210_MC_RESET (SDMMC4 ,0x970 ,0x974 ,0 ), +TEGRA210_MC_RESET (ISP2B ,0x970 ,0x974 ,1 ), +TEGRA210_MC_RESET (GPU ,0x970 ,0x974 ,2 ), +TEGRA210_MC_RESET (NVDEC ,0x970 ,0x974 ,5 ), +TEGRA210_MC_RESET (APE ,0x970 ,0x974 ,6 ), +TEGRA210_MC_RESET (SE ,0x970 ,0x974 ,7 ), +TEGRA210_MC_RESET (NVJPG ,0x970 ,0x974 ,8 ), +TEGRA210_MC_RESET (AXIAP ,0x970 ,0x974 ,11 ), +TEGRA210_MC_RESET (ETR ,0x970 ,0x974 ,12 ), +TEGRA210_MC_RESET (TSECB ,0x970 ,0x974 ,13 ), +}; +const struct tegra_mc_soc tegra210_mc_soc = { .clients = tegra210_mc_clients, .num_clients =ARRAY_SIZE (tegra210_mc_clients),
@@ -1090,4 +1132,7 @@ const struct tegra_mc_soc tegra210_mc_soc = { .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .resets_ops = &terga_mc_resets_ops_common, + .resets = tegra210_mc_resets, + .num_resets = ARRAY_SIZE(tegra210_mc_resets), };
Signature · 1 line
2.16.1
PATCH v3 12/15 memory: tegra: Add Tegra124 memory controller hot resets
In reply to Dmitry OsipenkoDefine the table of memory controller hot resets for Tegra124.
--- drivers/memory/tegra/tegra124.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
drivers/memory/tegra/tegra124.c +42 -0
@@ -1012,6 +1012,42 @@ static const struct tegra_smmu_group_soc tegra124_groups[] = { }, }; +#define TEGRA124_MC_RESET (_name, _control, _status, _bit) \ + { \ + .name = #_name, \ + .id = TEGRA124_MC_RESET_##_name, \ + .control = _control, \ + .status = _status, \ + .bit = _bit, \ + } + +static const struct tegra_mc_reset tegra124_mc_resets[] = { +TEGRA124_MC_RESET (AFI ,0x200 ,0x204 ,0 ), +TEGRA124_MC_RESET (AVPC ,0x200 ,0x204 ,1 ), +TEGRA124_MC_RESET (DC ,0x200 ,0x204 ,2 ), +TEGRA124_MC_RESET (DCB ,0x200 ,0x204 ,3 ), +TEGRA124_MC_RESET (HC ,0x200 ,0x204 ,6 ), +TEGRA124_MC_RESET (HDA ,0x200 ,0x204 ,7 ), +TEGRA124_MC_RESET (ISP2 ,0x200 ,0x204 ,8 ), +TEGRA124_MC_RESET (MPCORE ,0x200 ,0x204 ,9 ), +TEGRA124_MC_RESET (MPCORELP ,0x200 ,0x204 ,10 ), +TEGRA124_MC_RESET (MSENC ,0x200 ,0x204 ,11 ), +TEGRA124_MC_RESET (PPCS ,0x200 ,0x204 ,14 ), +TEGRA124_MC_RESET (SATA ,0x200 ,0x204 ,15 ), +TEGRA124_MC_RESET (VDE ,0x200 ,0x204 ,16 ), +TEGRA124_MC_RESET (VI ,0x200 ,0x204 ,17 ), +TEGRA124_MC_RESET (VIC ,0x200 ,0x204 ,18 ), +TEGRA124_MC_RESET (XUSB_HOST ,0x200 ,0x204 ,19 ), +TEGRA124_MC_RESET (XUSB_DEV ,0x200 ,0x204 ,20 ), +TEGRA124_MC_RESET (TSEC ,0x200 ,0x204 ,21 ), +TEGRA124_MC_RESET (SDMMC1 ,0x200 ,0x204 ,22 ), +TEGRA124_MC_RESET (SDMMC2 ,0x200 ,0x204 ,23 ), +TEGRA124_MC_RESET (SDMMC3 ,0x200 ,0x204 ,25 ), +TEGRA124_MC_RESET (SDMMC4 ,0x970 ,0x974 ,0 ), +TEGRA124_MC_RESET (ISP2B ,0x970 ,0x974 ,1 ), +TEGRA124_MC_RESET (GPU ,0x970 ,0x974 ,2 ), +}; +#ifdef CONFIG_ARCH_TEGRA_124_SOC static const struct tegra_smmu_soc tegra124_smmu_soc = { .clients = tegra124_mc_clients,
@@ -1038,6 +1074,9 @@ const struct tegra_mc_soc tegra124_mc_soc = { .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |MC_INT_INVALID_APB_ASID_UPDATE |MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .resets_ops = &terga_mc_resets_ops_common, + .resets = tegra124_mc_resets, + .num_resets = ARRAY_SIZE(tegra124_mc_resets), };#endif /* CONFIG_ARCH_TEGRA_124_SOC */
@@ -1065,5 +1104,8 @@ const struct tegra_mc_soc tegra132_mc_soc = { .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |MC_INT_INVALID_APB_ASID_UPDATE |MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .resets_ops = &terga_mc_resets_ops_common, + .resets = tegra124_mc_resets, + .num_resets = ARRAY_SIZE(tegra124_mc_resets), };#endif /* CONFIG_ARCH_TEGRA_132_SOC */
Signature · 1 line
2.16.1
PATCH v3 13/15 memory: tegra: Add Tegra114 memory controller hot resets
In reply to Dmitry OsipenkoDefine the table of memory controller hot resets for Tegra114.
--- drivers/memory/tegra/tegra114.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/memory/tegra/tegra114.c +33 -0
@@ -938,6 +938,36 @@ static const struct tegra_smmu_soc tegra114_smmu_soc = { .num_asids = 4, }; +#define TEGRA114_MC_RESET (_name, _control, _status, _bit) \ + { \ + .name = #_name, \ + .id = TEGRA114_MC_RESET_##_name, \ + .control = _control, \ + .status = _status, \ + .bit = _bit, \ + } + +static const struct tegra_mc_reset tegra114_mc_resets[] = { +TEGRA114_MC_RESET (AFI ,0x200 ,0x204 ,0 ), +TEGRA114_MC_RESET (AVPC ,0x200 ,0x204 ,1 ), +TEGRA114_MC_RESET (DC ,0x200 ,0x204 ,2 ), +TEGRA114_MC_RESET (DCB ,0x200 ,0x204 ,3 ), +TEGRA114_MC_RESET (EPP ,0x200 ,0x204 ,4 ), +TEGRA114_MC_RESET (2D ,0x200 ,0x204 ,5 ), +TEGRA114_MC_RESET (HC ,0x200 ,0x204 ,6 ), +TEGRA114_MC_RESET (HDA ,0x200 ,0x204 ,7 ), +TEGRA114_MC_RESET (ISP ,0x200 ,0x204 ,8 ), +TEGRA114_MC_RESET (MPCORE ,0x200 ,0x204 ,9 ), +TEGRA114_MC_RESET (MPCORELP ,0x200 ,0x204 ,10 ), +TEGRA114_MC_RESET (MPE ,0x200 ,0x204 ,11 ), +TEGRA114_MC_RESET (3D ,0x200 ,0x204 ,12 ), + TEGRA114_MC_RESET(3D2, 0x200, 0x204, 13), +TEGRA114_MC_RESET (PPCS ,0x200 ,0x204 ,14 ), +TEGRA114_MC_RESET (SATA ,0x200 ,0x204 ,15 ), +TEGRA114_MC_RESET (VDE ,0x200 ,0x204 ,16 ), +TEGRA114_MC_RESET (VI ,0x200 ,0x204 ,17 ), +}; +const struct tegra_mc_soc tegra114_mc_soc = { .clients = tegra114_mc_clients, .num_clients =ARRAY_SIZE (tegra114_mc_clients),
@@ -947,4 +977,7 @@ const struct tegra_mc_soc tegra114_mc_soc = { .smmu = &tegra114_smmu_soc, .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .resets_ops = &terga_mc_resets_ops_common, + .resets = tegra114_mc_resets, + .num_resets = ARRAY_SIZE(tegra114_mc_resets), };
Signature · 1 line
2.16.1
PATCH v3 14/15 memory: tegra: Add Tegra30 memory controller hot resets
In reply to Dmitry OsipenkoDefine the table of memory controller hot resets for Tegra30.
--- drivers/memory/tegra/tegra30.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/memory/tegra/tegra30.c +33 -0
@@ -960,6 +960,36 @@ static const struct tegra_smmu_soc tegra30_smmu_soc = { .num_asids = 4, }; +#define TEGRA30_MC_RESET (_name, _control, _status, _bit) \ + { \ + .name = #_name, \ + .id = TEGRA30_MC_RESET_##_name, \ + .control = _control, \ + .status = _status, \ + .bit = _bit, \ + } + +static const struct tegra_mc_reset tegra30_mc_resets[] = { +TEGRA30_MC_RESET (AFI ,0x200 ,0x204 ,0 ), +TEGRA30_MC_RESET (AVPC ,0x200 ,0x204 ,1 ), +TEGRA30_MC_RESET (DC ,0x200 ,0x204 ,2 ), +TEGRA30_MC_RESET (DCB ,0x200 ,0x204 ,3 ), +TEGRA30_MC_RESET (EPP ,0x200 ,0x204 ,4 ), +TEGRA30_MC_RESET (2D ,0x200 ,0x204 ,5 ), +TEGRA30_MC_RESET (HC ,0x200 ,0x204 ,6 ), +TEGRA30_MC_RESET (HDA ,0x200 ,0x204 ,7 ), +TEGRA30_MC_RESET (ISP ,0x200 ,0x204 ,8 ), +TEGRA30_MC_RESET (MPCORE ,0x200 ,0x204 ,9 ), +TEGRA30_MC_RESET (MPCORELP ,0x200 ,0x204 ,10 ), +TEGRA30_MC_RESET (MPE ,0x200 ,0x204 ,11 ), +TEGRA30_MC_RESET (3D ,0x200 ,0x204 ,12 ), + TEGRA30_MC_RESET(3D2, 0x200, 0x204, 13), +TEGRA30_MC_RESET (PPCS ,0x200 ,0x204 ,14 ), +TEGRA30_MC_RESET (SATA ,0x200 ,0x204 ,15 ), +TEGRA30_MC_RESET (VDE ,0x200 ,0x204 ,16 ), +TEGRA30_MC_RESET (VI ,0x200 ,0x204 ,17 ), +}; +const struct tegra_mc_soc tegra30_mc_soc = { .clients = tegra30_mc_clients, .num_clients =ARRAY_SIZE (tegra30_mc_clients),
@@ -969,4 +999,7 @@ const struct tegra_mc_soc tegra30_mc_soc = { .smmu = &tegra30_smmu_soc, .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, + .resets_ops = &terga_mc_resets_ops_common, + .resets = tegra30_mc_resets, + .num_resets = ARRAY_SIZE(tegra30_mc_resets), };
Signature · 1 line
2.16.1
PATCH v3 15/15 memory: tegra: Add Tegra20 memory controller hot resets
In reply to Dmitry OsipenkoDefine the table of memory controller hot resets for Tegra20 and add specific to Tegra20 hot reset operations.
--- drivers/memory/tegra/tegra20.c | 118 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
drivers/memory/tegra/tegra20.c +118 -0
@@ -6,6 +6,8 @@* published by the Free Software Foundation. */ +#include <dt-bindings/memory/tegra20-mc.h> +#include "mc.h" static const struct tegra_mc_client tegra20_mc_clients[] = {
@@ -168,6 +170,119 @@ static const struct tegra_mc_client tegra20_mc_clients[] = { }, }; +#define TEGRA20_MC_RESET (_name, _control, _status, _reset, _bit) \ + { \ + .name = #_name, \ + .id = TEGRA20_MC_RESET_##_name, \ + .control = _control, \ + .status = _status, \ + .reset = _reset, \ + .bit = _bit, \ + } + +static const struct tegra_mc_reset tegra20_mc_resets[] = { +TEGRA20_MC_RESET (AVPC ,0x100 ,0x140 ,0x104 ,0 ), +TEGRA20_MC_RESET (DC ,0x100 ,0x144 ,0x104 ,1 ), +TEGRA20_MC_RESET (DCB ,0x100 ,0x148 ,0x104 ,2 ), +TEGRA20_MC_RESET (EPP ,0x100 ,0x14c ,0x104 ,3 ), +TEGRA20_MC_RESET (2D ,0x100 ,0x150 ,0x104 ,4 ), +TEGRA20_MC_RESET (HC ,0x100 ,0x154 ,0x104 ,5 ), +TEGRA20_MC_RESET (ISP ,0x100 ,0x158 ,0x104 ,6 ), +TEGRA20_MC_RESET (MPCORE ,0x100 ,0x15c ,0x104 ,7 ), +TEGRA20_MC_RESET (MPEA ,0x100 ,0x160 ,0x104 ,8 ), +TEGRA20_MC_RESET (MPEB ,0x100 ,0x164 ,0x104 ,9 ), +TEGRA20_MC_RESET (MPEC ,0x100 ,0x168 ,0x104 ,10 ), +TEGRA20_MC_RESET (3D ,0x100 ,0x16c ,0x104 ,11 ), +TEGRA20_MC_RESET (PPCS ,0x100 ,0x170 ,0x104 ,12 ), +TEGRA20_MC_RESET (VDE ,0x100 ,0x174 ,0x104 ,13 ), +TEGRA20_MC_RESET (VI ,0x100 ,0x178 ,0x104 ,14 ), +}; + +static int terga20_mc_hotreset_assert (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +unsigned long flags; +u32 value; + +spin_lock_irqsave (&mc->lock, flags); + + value =mc_readl (mc, rst->reset); +mc_writel (mc, value & ~BIT (rst->bit), rst->reset); + +spin_unlock_irqrestore (&mc->lock, flags); + +return 0 ; +} + +static int terga20_mc_hotreset_deassert (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +unsigned long flags; +u32 value; + +spin_lock_irqsave (&mc->lock, flags); + + value =mc_readl (mc, rst->reset); +mc_writel (mc, value |BIT (rst->bit), rst->reset); + +spin_unlock_irqrestore (&mc->lock, flags); + +return 0 ; +} + +static int terga20_mc_block_dma (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +unsigned long flags; +u32 value; + +spin_lock_irqsave (&mc->lock, flags); + + value =mc_readl (mc, rst->control) & ~BIT (rst->bit); +mc_writel (mc, value, rst->control); + +spin_unlock_irqrestore (&mc->lock, flags); + +return 0 ; +} + +static bool terga20_mc_dma_idling (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +return mc_readl (mc, rst->status) ==0 ; +} + +static int terga20_mc_reset_status (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +return (mc_readl (mc, rst->reset) &BIT (rst->bit)) ==0 ; +} + +static int terga20_mc_unblock_dma (struct tegra_mc *mc, +const struct tegra_mc_reset *rst) +{ +unsigned long flags; +u32 value; + +spin_lock_irqsave (&mc->lock, flags); + + value =mc_readl (mc, rst->control) |BIT (rst->bit); +mc_writel (mc, value, rst->control); + +spin_unlock_irqrestore (&mc->lock, flags); + +return 0 ; +} + +const struct tegra_mc_reset_ops terga20_mc_resets_ops = { + .hotreset_assert = terga20_mc_hotreset_assert, + .hotreset_deassert = terga20_mc_hotreset_deassert, + .block_dma = terga20_mc_block_dma, + .dma_idling = terga20_mc_dma_idling, + .unblock_dma = terga20_mc_unblock_dma, + .reset_status = terga20_mc_reset_status, +}; +const struct tegra_mc_soc tegra20_mc_soc = { .clients = tegra20_mc_clients, .num_clients =ARRAY_SIZE (tegra20_mc_clients),
@@ -175,4 +290,7 @@ const struct tegra_mc_soc tegra20_mc_soc = { .client_id_mask = 0x3f, .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | MC_INT_DECERR_EMEM, + .resets_ops = &terga20_mc_resets_ops, + .resets = tegra20_mc_resets, + .num_resets = ARRAY_SIZE(tegra20_mc_resets), };
Signature · 1 line
2.16.1