From b8a177f18df1b439aac708da2d8bd9fcd68bb1eb Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:10 +0000 Subject: memory: tegra: Group error handling related registers Group MC error related registers into a struct as they could have SoC specific values. Tegra264 has different register offsets than the existing devices and so in order to add support for Tegra264 we need to first make this change. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-2-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- include/soc/tegra/mc.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 6ee4c59db620..372f47e824d5 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2014 NVIDIA Corporation + * Copyright (C) 2014-2026 NVIDIA Corporation */ #ifndef __SOC_TEGRA_MC_H__ @@ -168,6 +168,23 @@ struct tegra_mc_ops { int (*probe_device)(struct tegra_mc *mc, struct device *dev); }; +struct tegra_mc_regs { + unsigned int cfg_channel_enable; + unsigned int err_status; + unsigned int err_add; + unsigned int err_add_hi; + unsigned int err_vpr_status; + unsigned int err_vpr_add; + unsigned int err_sec_status; + unsigned int err_sec_add; + unsigned int err_mts_status; + unsigned int err_mts_add; + unsigned int err_gen_co_status; + unsigned int err_gen_co_add; + unsigned int err_route_status; + unsigned int err_route_add; +}; + struct tegra_mc_soc { const struct tegra_mc_client *clients; unsigned int num_clients; @@ -196,6 +213,7 @@ struct tegra_mc_soc { const struct tegra_mc_icc_ops *icc_ops; const struct tegra_mc_ops *ops; + const struct tegra_mc_regs *regs; }; struct tegra_mc { @@ -256,4 +274,6 @@ tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id, } #endif +extern const struct tegra_mc_regs tegra20_mc_regs; + #endif /* __SOC_TEGRA_MC_H__ */ -- cgit v1.2.3 From 4d865a2374037d2d0842f88822fd753f0918b370 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:12 +0000 Subject: memory: tegra: Add support for multiple IRQs Add support to handle multiple MC interrupts lines, as supported by Tegra264. Turn the single IRQ handler callback into a counted array to allow specifying a separate handler for each interrupt. Move IRQ handlers into tegra_mc_soc struct, so as to specify SoC specific values. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-4-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 34 +++++++++++++++++++++------------- drivers/memory/tegra/mc.h | 1 + drivers/memory/tegra/tegra114.c | 2 ++ drivers/memory/tegra/tegra124.c | 4 ++++ drivers/memory/tegra/tegra186.c | 3 ++- drivers/memory/tegra/tegra194.c | 2 ++ drivers/memory/tegra/tegra20.c | 7 ++++++- drivers/memory/tegra/tegra210.c | 2 ++ drivers/memory/tegra/tegra234.c | 2 ++ drivers/memory/tegra/tegra30.c | 2 ++ include/soc/tegra/mc.h | 8 +++++--- 11 files changed, 49 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 63f402aa1976..8114574374d5 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -398,6 +398,10 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc) } EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count); +const irq_handler_t tegra30_mc_irq_handlers[] = { + tegra30_mc_handle_irq +}; + #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \ defined(CONFIG_ARCH_TEGRA_114_SOC) || \ defined(CONFIG_ARCH_TEGRA_124_SOC) || \ @@ -542,7 +546,6 @@ int tegra30_mc_probe(struct tegra_mc *mc) const struct tegra_mc_ops tegra30_mc_ops = { .probe = tegra30_mc_probe, - .handle_irq = tegra30_mc_handle_irq, }; #endif @@ -943,26 +946,31 @@ static int tegra_mc_probe(struct platform_device *pdev) tegra_mc_num_channel_enabled(mc); - if (mc->soc->ops && mc->soc->ops->handle_irq) { - mc->irq = platform_get_irq(pdev, 0); - if (mc->irq < 0) - return mc->irq; + if (mc->soc->handle_irq) { + unsigned int i; WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n"); + for (i = 0; i < mc->soc->num_interrupts; i++) { + int irq; + + irq = platform_get_irq(pdev, i); + if (irq < 0) + return irq; + + err = devm_request_irq(&pdev->dev, irq, mc->soc->handle_irq[i], 0, + dev_name(&pdev->dev), mc); + if (err < 0) { + dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err); + return err; + } + } + if (mc->soc->num_channels) mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask, MC_INTMASK); else mc_writel(mc, mc->soc->intmask, MC_INTMASK); - - err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0, - dev_name(&pdev->dev), mc); - if (err < 0) { - dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq, - err); - return err; - } } if (mc->soc->reset_ops) { diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 5f816d703d81..34ce03ebc51c 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -193,6 +193,7 @@ extern const struct tegra_mc_ops tegra186_mc_ops; #endif irqreturn_t tegra30_mc_handle_irq(int irq, void *data); +extern const irq_handler_t tegra30_mc_irq_handlers[1]; extern const char * const tegra_mc_status_names[32]; extern const char * const tegra_mc_error_names[8]; diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index ea7e4c7bb5f8..fffb28eea57f 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1115,4 +1115,6 @@ const struct tegra_mc_soc tegra114_mc_soc = { .num_resets = ARRAY_SIZE(tegra114_mc_resets), .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index f0cfe14bb475..2cf733198782 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1276,6 +1276,8 @@ const struct tegra_mc_soc tegra124_mc_soc = { .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1309,5 +1311,7 @@ const struct tegra_mc_soc tegra132_mc_soc = { .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 51e2dd628fb4..eb1eaaffc79a 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -174,7 +174,6 @@ const struct tegra_mc_ops tegra186_mc_ops = { .remove = tegra186_mc_remove, .resume = tegra186_mc_resume, .probe_device = tegra186_mc_probe_device, - .handle_irq = tegra30_mc_handle_irq, }; #if defined(CONFIG_ARCH_TEGRA_186_SOC) @@ -915,5 +914,7 @@ const struct tegra_mc_soc tegra186_mc_soc = { .ch_intmask = 0x0000000f, .global_intstatus_channel_shift = 0, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index 5b7ff2dd6812..cb0e7886857d 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1359,4 +1359,6 @@ const struct tegra_mc_soc tegra194_mc_soc = { .ch_intmask = 0x00000f00, .global_intstatus_channel_shift = 8, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 1b2b598ab564..6750b08d875f 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -761,9 +761,12 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) return IRQ_HANDLED; } +static const irq_handler_t tegra20_mc_irq_handlers[] = { + tegra20_mc_handle_irq +}; + static const struct tegra_mc_ops tegra20_mc_ops = { .probe = tegra20_mc_probe, - .handle_irq = tegra20_mc_handle_irq, }; const struct tegra_mc_soc tegra20_mc_soc = { @@ -779,4 +782,6 @@ const struct tegra_mc_soc tegra20_mc_soc = { .icc_ops = &tegra20_mc_icc_ops, .ops = &tegra20_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra20_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index e166b33848e9..8283601ab52c 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1288,4 +1288,6 @@ const struct tegra_mc_soc tegra210_mc_soc = { .num_resets = ARRAY_SIZE(tegra210_mc_resets), .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 512d054d7592..9586d7528fb7 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1153,4 +1153,6 @@ const struct tegra_mc_soc tegra234_mc_soc = { */ .num_carveouts = 32, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index 337501a30a73..ff89b9078772 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1401,4 +1401,6 @@ const struct tegra_mc_soc tegra30_mc_soc = { .icc_ops = &tegra30_mc_icc_ops, .ops = &tegra30_mc_ops, .regs = &tegra20_mc_regs, + .handle_irq = tegra30_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 372f47e824d5..d07de04c0f33 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -10,10 +10,11 @@ #include #include #include +#include #include #include -#include #include +#include struct clk; struct device; @@ -164,7 +165,6 @@ struct tegra_mc_ops { int (*probe)(struct tegra_mc *mc); void (*remove)(struct tegra_mc *mc); int (*resume)(struct tegra_mc *mc); - irqreturn_t (*handle_irq)(int irq, void *data); int (*probe_device)(struct tegra_mc *mc, struct device *dev); }; @@ -214,6 +214,9 @@ struct tegra_mc_soc { const struct tegra_mc_icc_ops *icc_ops; const struct tegra_mc_ops *ops; const struct tegra_mc_regs *regs; + + const irq_handler_t *handle_irq; + unsigned int num_interrupts; }; struct tegra_mc { @@ -224,7 +227,6 @@ struct tegra_mc { void __iomem *bcast_ch_regs; void __iomem **ch_regs; struct clk *clk; - int irq; const struct tegra_mc_soc *soc; unsigned long tick; -- cgit v1.2.3 From 2e4cfaa78eb98d2623367818c859225c6b6bf701 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:13 +0000 Subject: memory: tegra: Group SoC specific fields Introduce new SoC specific fields in tegra_mc_soc struct for high address mask and error status type mask because Tegra264 has different values for these than the existing devices. Error status registers e.g. MC_ERR_STATUS_0 has few bits which indicate the type of the error. In order to obtain such type of error from error status register, we use error status type mask. Similarly, these error status registers have bits which indicate the higher address bits of the address responsible for mc error. In order to obtain such higher address, we use high address mask. Make this change to prepare for adding MC interrupt support for Tegra264. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-5-ketanp@nvidia.com [krzk: Fix checkpatch warning] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 11 +++++++---- drivers/memory/tegra/mc.h | 2 -- drivers/memory/tegra/tegra114.c | 1 + drivers/memory/tegra/tegra124.c | 4 ++++ drivers/memory/tegra/tegra186.c | 2 ++ drivers/memory/tegra/tegra194.c | 2 ++ drivers/memory/tegra/tegra20.c | 1 + drivers/memory/tegra/tegra210.c | 2 ++ drivers/memory/tegra/tegra234.c | 2 ++ drivers/memory/tegra/tegra30.c | 1 + include/soc/tegra/mc.h | 2 ++ 11 files changed, 24 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 8114574374d5..5d0d9b7fc534 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -658,9 +658,12 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) addr = mc_ch_readl(mc, channel, addr_hi_reg); else addr = mc_readl(mc, addr_hi_reg); - } else { + } else if (mc->soc->mc_addr_hi_mask) { addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) & - MC_ERR_STATUS_ADR_HI_MASK); + mc->soc->mc_addr_hi_mask); + } else { + dev_err_ratelimited(mc->dev, "Unable to determine high address!"); + return IRQ_NONE; } addr <<= 32; } @@ -685,11 +688,11 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) } } - type = (value & MC_ERR_STATUS_TYPE_MASK) >> + type = (value & mc->soc->mc_err_status_type_mask) >> MC_ERR_STATUS_TYPE_SHIFT; desc = tegra_mc_error_names[type]; - switch (value & MC_ERR_STATUS_TYPE_MASK) { + switch (value & mc->soc->mc_err_status_type_mask) { case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE: perm[0] = ' '; perm[1] = '['; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 34ce03ebc51c..b286c2558fd5 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -78,10 +78,8 @@ #define MC_ERR_STATUS_TYPE_SHIFT 28 #define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28) -#define MC_ERR_STATUS_TYPE_MASK (0x7 << 28) #define MC_ERR_STATUS_ADR_HI_SHIFT 20 -#define MC_ERR_STATUS_ADR_HI_MASK 0x3 #define MC_BROADCAST_CHANNEL ~0 diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index fffb28eea57f..3a061a2d881e 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1117,4 +1117,5 @@ const struct tegra_mc_soc tegra114_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 2cf733198782..4d394889c1e9 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1278,6 +1278,8 @@ const struct tegra_mc_soc tegra124_mc_soc = { .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), }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1313,5 +1315,7 @@ const struct tegra_mc_soc tegra132_mc_soc = { .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), }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index eb1eaaffc79a..94cad76c52ac 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -916,5 +916,7 @@ const struct tegra_mc_soc tegra186_mc_soc = { .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), }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index cb0e7886857d..38852b2a0f44 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1361,4 +1361,6 @@ const struct tegra_mc_soc tegra194_mc_soc = { .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), }; diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 6750b08d875f..a5cc770437ae 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -784,4 +784,5 @@ const struct tegra_mc_soc tegra20_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra20_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers), + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index 8283601ab52c..aa606df8a679 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1290,4 +1290,6 @@ const struct tegra_mc_soc tegra210_mc_soc = { .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), }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 9586d7528fb7..67d5d4e01a65 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1155,4 +1155,6 @@ const struct tegra_mc_soc tegra234_mc_soc = { .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), }; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index ff89b9078772..8a26a2f204e9 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1403,4 +1403,5 @@ const struct tegra_mc_soc tegra30_mc_soc = { .regs = &tegra20_mc_regs, .handle_irq = tegra30_mc_irq_handlers, .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), + .mc_err_status_type_mask = (0x7 << 28), }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index d07de04c0f33..b9b1763b10b5 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -217,6 +217,8 @@ struct tegra_mc_soc { const irq_handler_t *handle_irq; unsigned int num_interrupts; + unsigned int mc_addr_hi_mask; + unsigned int mc_err_status_type_mask; }; struct tegra_mc { -- cgit v1.2.3 From 9f2614510960f0761144d14e1b4c4d82e0c098e9 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:14 +0000 Subject: memory: tegra: Prepare for supporting multiple intmask registers Add a new structure for the intmask register e.g. MC_INTMASK_0 and it's mask value. Add an array of these new structures to prepare for supporting multiple intmask registers. This is done in preparation for adding support for Tegra264 which supports multiple intmask registers. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-6-ketanp@nvidia.com [krzk: Fix checkpatch warning] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 16 +++++++++------- drivers/memory/tegra/tegra114.c | 12 ++++++++++-- drivers/memory/tegra/tegra124.c | 28 ++++++++++++++++++++++------ drivers/memory/tegra/tegra186.c | 14 +++++++++++--- drivers/memory/tegra/tegra194.c | 15 +++++++++++---- drivers/memory/tegra/tegra20.c | 14 +++++++++++--- drivers/memory/tegra/tegra210.c | 14 +++++++++++--- drivers/memory/tegra/tegra234.c | 15 +++++++++++---- drivers/memory/tegra/tegra264.c | 17 ++++++++++++----- drivers/memory/tegra/tegra30.c | 12 ++++++++++-- include/soc/tegra/mc.h | 8 +++++++- 11 files changed, 125 insertions(+), 40 deletions(-) (limited to 'include') diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 5d0d9b7fc534..dccebbed7833 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -586,9 +586,9 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) } /* mask all interrupts to avoid flooding */ - status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask; + status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmasks[0].mask; } else { - status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; + status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask; } if (!status) @@ -969,11 +969,13 @@ static int tegra_mc_probe(struct platform_device *pdev) } } - if (mc->soc->num_channels) - mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask, - MC_INTMASK); - else - mc_writel(mc, mc->soc->intmask, MC_INTMASK); + for (i = 0; i < mc->soc->num_intmasks; i++) { + if (mc->soc->num_channels) + mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmasks[i].mask, + mc->soc->intmasks[i].reg); + else + mc_writel(mc, mc->soc->intmasks[i].mask, mc->soc->intmasks[i].reg); + } } if (mc->soc->reset_ops) { diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index 3a061a2d881e..02dd4e26288a 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1101,6 +1101,14 @@ static const struct tegra_mc_reset tegra114_mc_resets[] = { TEGRA114_MC_RESET(VI, 0x200, 0x204, 17), }; +static const struct tegra_mc_intmask tegra114_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra114_mc_soc = { .clients = tegra114_mc_clients, .num_clients = ARRAY_SIZE(tegra114_mc_clients), @@ -1108,8 +1116,8 @@ 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, + .intmasks = tegra114_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra114_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra114_mc_resets, .num_resets = ARRAY_SIZE(tegra114_mc_resets), diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 4d394889c1e9..df87c5038625 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1258,6 +1258,15 @@ static const struct tegra_smmu_soc tegra124_smmu_soc = { .num_asids = 128, }; +static const struct tegra_mc_intmask tegra124_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = 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, + }, +}; + const struct tegra_mc_soc tegra124_mc_soc = { .clients = tegra124_mc_clients, .num_clients = ARRAY_SIZE(tegra124_mc_clients), @@ -1267,9 +1276,8 @@ 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, + .intmasks = tegra124_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra124_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra124_mc_resets, .num_resets = ARRAY_SIZE(tegra124_mc_resets), @@ -1297,6 +1305,15 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = { .num_asids = 128, }; +static const struct tegra_mc_intmask tegra132_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = 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, + }, +}; + const struct tegra_mc_soc tegra132_mc_soc = { .clients = tegra124_mc_clients, .num_clients = ARRAY_SIZE(tegra124_mc_clients), @@ -1304,9 +1321,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, + .intmasks = tegra132_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra132_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra124_mc_resets, .num_resets = ARRAY_SIZE(tegra124_mc_resets), diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 94cad76c52ac..91d56165605f 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -901,15 +901,23 @@ static const struct tegra_mc_client tegra186_mc_clients[] = { }, }; +static const struct tegra_mc_intmask tegra186_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = 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 tegra186_mc_soc = { .num_clients = ARRAY_SIZE(tegra186_mc_clients), .clients = tegra186_mc_clients, .num_address_bits = 40, .num_channels = 4, .client_id_mask = 0xff, - .intmask = 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, + .intmasks = tegra186_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks), .ops = &tegra186_mc_ops, .ch_intmask = 0x0000000f, .global_intstatus_channel_shift = 0, diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index 38852b2a0f44..a8cc57690696 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1343,16 +1343,23 @@ static const struct tegra_mc_client tegra194_mc_clients[] = { }, }; +static const struct tegra_mc_intmask tegra194_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 tegra194_mc_soc = { .num_clients = ARRAY_SIZE(tegra194_mc_clients), .clients = tegra194_mc_clients, .num_address_bits = 40, .num_channels = 16, .client_id_mask = 0xff, - .intmask = 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, + .intmasks = tegra194_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra194_mc_intmasks), .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra_mc_icc_ops, diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index a5cc770437ae..ff9e151b5a4c 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -695,7 +695,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) unsigned int bit; /* mask all interrupts to avoid flooding */ - status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; + status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask; if (!status) return IRQ_NONE; @@ -769,13 +769,21 @@ static const struct tegra_mc_ops tegra20_mc_ops = { .probe = tegra20_mc_probe, }; +static const struct tegra_mc_intmask tegra20_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | + MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra20_mc_soc = { .clients = tegra20_mc_clients, .num_clients = ARRAY_SIZE(tegra20_mc_clients), .num_address_bits = 32, .client_id_mask = 0x3f, - .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | - MC_INT_DECERR_EMEM, + .intmasks = tegra20_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra20_mc_intmasks), .reset_ops = &tegra20_mc_reset_ops, .resets = tegra20_mc_resets, .num_resets = ARRAY_SIZE(tegra20_mc_resets), diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index aa606df8a679..f58f3ef6f681 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1273,6 +1273,15 @@ static const struct tegra_mc_reset tegra210_mc_resets[] = { TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13), }; +static const struct tegra_mc_intmask tegra210_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = 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, + }, +}; + const struct tegra_mc_soc tegra210_mc_soc = { .clients = tegra210_mc_clients, .num_clients = ARRAY_SIZE(tegra210_mc_clients), @@ -1280,9 +1289,8 @@ 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, + .intmasks = tegra210_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra210_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra210_mc_resets, .num_resets = ARRAY_SIZE(tegra210_mc_resets), diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 67d5d4e01a65..87b22038a5fb 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1132,16 +1132,23 @@ static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { .set = tegra234_mc_icc_set, }; +static const struct tegra_mc_intmask tegra234_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 tegra234_mc_soc = { .num_clients = ARRAY_SIZE(tegra234_mc_clients), .clients = tegra234_mc_clients, .num_address_bits = 40, .num_channels = 16, .client_id_mask = 0x1ff, - .intmask = 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, + .intmasks = tegra234_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra234_mc_intmasks), .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra234_mc_icc_ops, diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index 5203e6c11372..172a48b56484 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2025, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2025-2026, NVIDIA CORPORATION. All rights reserved. */ #include @@ -290,16 +290,23 @@ static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = { .set = tegra264_mc_icc_set, }; +static const struct tegra_mc_intmask tegra264_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 tegra264_mc_soc = { .num_clients = ARRAY_SIZE(tegra264_mc_clients), .clients = tegra264_mc_clients, .num_address_bits = 40, .num_channels = 16, .client_id_mask = 0x1ff, - .intmask = 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, + .intmasks = tegra264_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra264_mc_intmasks), .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra264_mc_icc_ops, diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index 8a26a2f204e9..8389e3af0121 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1384,6 +1384,14 @@ static const struct tegra_mc_icc_ops tegra30_mc_icc_ops = { .set = tegra30_mc_icc_set, }; +static const struct tegra_mc_intmask tegra30_mc_intmasks[] = { + { + .reg = MC_INTMASK, + .mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | + MC_INT_DECERR_EMEM, + }, +}; + const struct tegra_mc_soc tegra30_mc_soc = { .clients = tegra30_mc_clients, .num_clients = ARRAY_SIZE(tegra30_mc_clients), @@ -1393,8 +1401,8 @@ const struct tegra_mc_soc tegra30_mc_soc = { .smmu = &tegra30_smmu_soc, .emem_regs = tegra30_mc_emem_regs, .num_emem_regs = ARRAY_SIZE(tegra30_mc_emem_regs), - .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | - MC_INT_DECERR_EMEM, + .intmasks = tegra30_mc_intmasks, + .num_intmasks = ARRAY_SIZE(tegra30_mc_intmasks), .reset_ops = &tegra_mc_reset_ops_common, .resets = tegra30_mc_resets, .num_resets = ARRAY_SIZE(tegra30_mc_resets), diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index b9b1763b10b5..e6da035d1306 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -185,6 +185,11 @@ struct tegra_mc_regs { unsigned int err_route_add; }; +struct tegra_mc_intmask { + u32 reg; + u32 mask; +}; + struct tegra_mc_soc { const struct tegra_mc_client *clients; unsigned int num_clients; @@ -202,7 +207,6 @@ struct tegra_mc_soc { const struct tegra_smmu_soc *smmu; - u32 intmask; u32 ch_intmask; u32 global_intstatus_channel_shift; bool has_addr_hi_reg; @@ -219,6 +223,8 @@ struct tegra_mc_soc { unsigned int num_interrupts; unsigned int mc_addr_hi_mask; unsigned int mc_err_status_type_mask; + const struct tegra_mc_intmask *intmasks; + unsigned int num_intmasks; }; struct tegra_mc { -- cgit v1.2.3