From ef4d7b9975d6d87a21574f98473945c8e499a0d2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 16 Jan 2026 13:37:32 +0100 Subject: memory: tegra: Add support for DBB clock on Tegra264 The DBB clock is needed by many IP blocks in order to access system memory via the data backbone. The memory controller and external memory controllers are the central place where these accesses are managed, so make sure that the clock can be controlled from the corresponding driver. Note that not all drivers fully register bandwidth requests, and hence the EMC driver doesn't have enough information to know when it's safe to switch the clock off, so for now it will be kept on permanently. Signed-off-by: Thierry Reding Reviewed-by: Jon Hunter Link: https://patch.msgid.link/20260116123732.140813-1-thierry.reding@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra186-emc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index dfddceecdd1a..03ebab6fbe68 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -22,6 +22,7 @@ struct tegra186_emc { struct tegra_bpmp *bpmp; struct device *dev; struct clk *clk; + struct clk *clk_dbb; struct tegra186_emc_dvfs *dvfs; unsigned int num_dvfs; @@ -328,6 +329,13 @@ static int tegra186_emc_probe(struct platform_device *pdev) goto put_bpmp; } + emc->clk_dbb = devm_clk_get_optional_enabled(&pdev->dev, "dbb"); + if (IS_ERR(emc->clk_dbb)) { + err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk_dbb), + "failed to get DBB clock\n"); + goto put_bpmp; + } + platform_set_drvdata(pdev, emc); emc->dev = &pdev->dev; -- cgit v1.2.3 From 9597ab9a8296ab337e6820f8a717ff621078b632 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 26 Jan 2026 15:50:42 +0900 Subject: memory: tegra124-emc: Fix dll_change check The code checking whether the specified memory timing enables DLL in the EMRS register was reversed. DLL is enabled if bit A0 is low. Fix the check. Fixes: 73a7f0a90641 ("memory: tegra: Add EMC (external memory controller) driver") Signed-off-by: Mikko Perttunen Link: https://patch.msgid.link/20260126-fix-emc-dllchange-v1-1-47ad3bb63262@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra124-emc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index ff26815e51f1..5cfbc169c5f9 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -608,7 +608,7 @@ static int tegra124_emc_prepare_timing_change(struct tegra_emc *emc, if ((last->emc_mode_1 & 0x1) == (timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_NONE; - else if (timing->emc_mode_1 & 0x1) + else if (!(timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_ON; else dll_change = DLL_CHANGE_OFF; -- cgit v1.2.3 From 0a93f2355cf4922ad2399dbef5ea1049fef116d4 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 26 Jan 2026 15:50:43 +0900 Subject: memory: tegra30-emc: Fix dll_change check The code checking whether the specified memory timing enables DLL in the EMRS register was reversed. DLL is enabled if bit A0 is low. Fix the check. Fixes: e34212c75a68 ("memory: tegra: Introduce Tegra30 EMC driver") Signed-off-by: Mikko Perttunen Link: https://patch.msgid.link/20260126-fix-emc-dllchange-v1-2-47ad3bb63262@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra30-emc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c index 606106dd2b32..5812c8cd6ce4 100644 --- a/drivers/memory/tegra/tegra30-emc.c +++ b/drivers/memory/tegra/tegra30-emc.c @@ -554,14 +554,14 @@ static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate) emc->emc_cfg = readl_relaxed(emc->regs + EMC_CFG); emc_dbg = readl_relaxed(emc->regs + EMC_DBG); - if (emc->dll_on == !!(timing->emc_mode_1 & 0x1)) + if (emc->dll_on == !(timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_NONE; - else if (timing->emc_mode_1 & 0x1) + else if (!(timing->emc_mode_1 & 0x1)) dll_change = DLL_CHANGE_ON; else dll_change = DLL_CHANGE_OFF; - emc->dll_on = !!(timing->emc_mode_1 & 0x1); + emc->dll_on = !(timing->emc_mode_1 & 0x1); if (timing->data[80] && !readl_relaxed(emc->regs + EMC_ZCAL_INTERVAL)) emc->zcal_long = true; -- cgit v1.2.3 From d455e0f602d7e4d4ba709418009c39be48fc2149 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 25 Feb 2026 18:37:20 +0100 Subject: memory: bt1-l2-ctl: Remove not-going-to-be-supported code for Baikal SoC As noticed in the discussion [1] the Baikal SoC and platforms are not going to be finalized, hence remove stale code. Link: https://lore.kernel.org/lkml/22b92ddf-6321-41b5-8073-f9c7064d3432@infradead.org/ [1] Reviewed-by: Randy Dunlap Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20260225173930.3819351-2-andriy.shevchenko@linux.intel.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 11 -- drivers/memory/Makefile | 1 - drivers/memory/bt1-l2-ctl.c | 323 -------------------------------------------- 3 files changed, 335 deletions(-) delete mode 100644 drivers/memory/bt1-l2-ctl.c diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 79df0d22e218..e5527020ff33 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -64,17 +64,6 @@ config BRCMSTB_MEMC controller and specifically control the Self Refresh Power Down (SRPD) inactivity timeout. -config BT1_L2_CTL - bool "Baikal-T1 CM2 L2-RAM Cache Control Block" - depends on MIPS_BAIKAL_T1 || COMPILE_TEST - select MFD_SYSCON - help - Baikal-T1 CPU is based on the MIPS P5600 Warrior IP-core. The CPU - resides Coherency Manager v2 with embedded 1MB L2-cache. It's - possible to tune the L2 cache performance up by setting the data, - tags and way-select latencies of RAM access. This driver provides a - dt properties-based and sysfs interface for it. - config TI_AEMIF tristate "Texas Instruments AEMIF driver" depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index c1959661bf63..3ee883c8759a 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o -obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_EMIF) += emif.o obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o diff --git a/drivers/memory/bt1-l2-ctl.c b/drivers/memory/bt1-l2-ctl.c deleted file mode 100644 index 0fd96abc172a..000000000000 --- a/drivers/memory/bt1-l2-ctl.c +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC - * - * Authors: - * Serge Semin - * - * Baikal-T1 CM2 L2-cache Control Block driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define L2_CTL_REG 0x028 -#define L2_CTL_DATA_STALL_FLD 0 -#define L2_CTL_DATA_STALL_MASK GENMASK(1, L2_CTL_DATA_STALL_FLD) -#define L2_CTL_TAG_STALL_FLD 2 -#define L2_CTL_TAG_STALL_MASK GENMASK(3, L2_CTL_TAG_STALL_FLD) -#define L2_CTL_WS_STALL_FLD 4 -#define L2_CTL_WS_STALL_MASK GENMASK(5, L2_CTL_WS_STALL_FLD) -#define L2_CTL_SET_CLKRATIO BIT(13) -#define L2_CTL_CLKRATIO_LOCK BIT(31) - -#define L2_CTL_STALL_MIN 0 -#define L2_CTL_STALL_MAX 3 -#define L2_CTL_STALL_SET_DELAY_US 1 -#define L2_CTL_STALL_SET_TOUT_US 1000 - -/* - * struct l2_ctl - Baikal-T1 L2 Control block private data. - * @dev: Pointer to the device structure. - * @sys_regs: Baikal-T1 System Controller registers map. - */ -struct l2_ctl { - struct device *dev; - - struct regmap *sys_regs; -}; - -/* - * enum l2_ctl_stall - Baikal-T1 L2-cache-RAM stall identifier. - * @L2_WSSTALL: Way-select latency. - * @L2_TAGSTALL: Tag latency. - * @L2_DATASTALL: Data latency. - */ -enum l2_ctl_stall { - L2_WS_STALL, - L2_TAG_STALL, - L2_DATA_STALL -}; - -/* - * struct l2_ctl_device_attribute - Baikal-T1 L2-cache device attribute. - * @dev_attr: Actual sysfs device attribute. - * @id: L2-cache stall field identifier. - */ -struct l2_ctl_device_attribute { - struct device_attribute dev_attr; - enum l2_ctl_stall id; -}; - -#define to_l2_ctl_dev_attr(_dev_attr) \ - container_of(_dev_attr, struct l2_ctl_device_attribute, dev_attr) - -#define L2_CTL_ATTR_RW(_name, _prefix, _id) \ - struct l2_ctl_device_attribute l2_ctl_attr_##_name = \ - { __ATTR(_name, 0644, _prefix##_show, _prefix##_store), _id } - -static int l2_ctl_get_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 *val) -{ - u32 data = 0; - int ret; - - ret = regmap_read(l2->sys_regs, L2_CTL_REG, &data); - if (ret) - return ret; - - switch (id) { - case L2_WS_STALL: - *val = FIELD_GET(L2_CTL_WS_STALL_MASK, data); - break; - case L2_TAG_STALL: - *val = FIELD_GET(L2_CTL_TAG_STALL_MASK, data); - break; - case L2_DATA_STALL: - *val = FIELD_GET(L2_CTL_DATA_STALL_MASK, data); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int l2_ctl_set_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 val) -{ - u32 mask = 0, data = 0; - int ret; - - val = clamp_val(val, L2_CTL_STALL_MIN, L2_CTL_STALL_MAX); - - switch (id) { - case L2_WS_STALL: - data = FIELD_PREP(L2_CTL_WS_STALL_MASK, val); - mask = L2_CTL_WS_STALL_MASK; - break; - case L2_TAG_STALL: - data = FIELD_PREP(L2_CTL_TAG_STALL_MASK, val); - mask = L2_CTL_TAG_STALL_MASK; - break; - case L2_DATA_STALL: - data = FIELD_PREP(L2_CTL_DATA_STALL_MASK, val); - mask = L2_CTL_DATA_STALL_MASK; - break; - default: - return -EINVAL; - } - - data |= L2_CTL_SET_CLKRATIO; - mask |= L2_CTL_SET_CLKRATIO; - - ret = regmap_update_bits(l2->sys_regs, L2_CTL_REG, mask, data); - if (ret) - return ret; - - return regmap_read_poll_timeout(l2->sys_regs, L2_CTL_REG, data, - data & L2_CTL_CLKRATIO_LOCK, - L2_CTL_STALL_SET_DELAY_US, - L2_CTL_STALL_SET_TOUT_US); -} - -static void l2_ctl_clear_data(void *data) -{ - struct l2_ctl *l2 = data; - struct platform_device *pdev = to_platform_device(l2->dev); - - platform_set_drvdata(pdev, NULL); -} - -static struct l2_ctl *l2_ctl_create_data(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct l2_ctl *l2; - int ret; - - l2 = devm_kzalloc(dev, sizeof(*l2), GFP_KERNEL); - if (!l2) - return ERR_PTR(-ENOMEM); - - ret = devm_add_action(dev, l2_ctl_clear_data, l2); - if (ret) { - dev_err(dev, "Can't add L2 CTL data clear action\n"); - return ERR_PTR(ret); - } - - l2->dev = dev; - platform_set_drvdata(pdev, l2); - - return l2; -} - -static int l2_ctl_find_sys_regs(struct l2_ctl *l2) -{ - l2->sys_regs = syscon_node_to_regmap(l2->dev->of_node->parent); - if (IS_ERR(l2->sys_regs)) { - dev_err(l2->dev, "Couldn't get L2 CTL register map\n"); - return PTR_ERR(l2->sys_regs); - } - - return 0; -} - -static int l2_ctl_of_parse_property(struct l2_ctl *l2, enum l2_ctl_stall id, - const char *propname) -{ - int ret = 0; - u32 data; - - if (!of_property_read_u32(l2->dev->of_node, propname, &data)) { - ret = l2_ctl_set_latency(l2, id, data); - if (ret) - dev_err(l2->dev, "Invalid value of '%s'\n", propname); - } - - return ret; -} - -static int l2_ctl_of_parse(struct l2_ctl *l2) -{ - int ret; - - ret = l2_ctl_of_parse_property(l2, L2_WS_STALL, "baikal,l2-ws-latency"); - if (ret) - return ret; - - ret = l2_ctl_of_parse_property(l2, L2_TAG_STALL, "baikal,l2-tag-latency"); - if (ret) - return ret; - - return l2_ctl_of_parse_property(l2, L2_DATA_STALL, - "baikal,l2-data-latency"); -} - -static ssize_t l2_ctl_latency_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr); - struct l2_ctl *l2 = dev_get_drvdata(dev); - u32 data; - int ret; - - ret = l2_ctl_get_latency(l2, devattr->id, &data); - if (ret) - return ret; - - return sysfs_emit(buf, "%u\n", data); -} - -static ssize_t l2_ctl_latency_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr); - struct l2_ctl *l2 = dev_get_drvdata(dev); - u32 data; - int ret; - - if (kstrtouint(buf, 0, &data) < 0) - return -EINVAL; - - ret = l2_ctl_set_latency(l2, devattr->id, data); - if (ret) - return ret; - - return count; -} - -static L2_CTL_ATTR_RW(l2_ws_latency, l2_ctl_latency, L2_WS_STALL); -static L2_CTL_ATTR_RW(l2_tag_latency, l2_ctl_latency, L2_TAG_STALL); -static L2_CTL_ATTR_RW(l2_data_latency, l2_ctl_latency, L2_DATA_STALL); - -static struct attribute *l2_ctl_sysfs_attrs[] = { - &l2_ctl_attr_l2_ws_latency.dev_attr.attr, - &l2_ctl_attr_l2_tag_latency.dev_attr.attr, - &l2_ctl_attr_l2_data_latency.dev_attr.attr, - NULL -}; -ATTRIBUTE_GROUPS(l2_ctl_sysfs); - -static void l2_ctl_remove_sysfs(void *data) -{ - struct l2_ctl *l2 = data; - - device_remove_groups(l2->dev, l2_ctl_sysfs_groups); -} - -static int l2_ctl_init_sysfs(struct l2_ctl *l2) -{ - int ret; - - ret = device_add_groups(l2->dev, l2_ctl_sysfs_groups); - if (ret) { - dev_err(l2->dev, "Failed to create L2 CTL sysfs nodes\n"); - return ret; - } - - ret = devm_add_action_or_reset(l2->dev, l2_ctl_remove_sysfs, l2); - if (ret) - dev_err(l2->dev, "Can't add L2 CTL sysfs remove action\n"); - - return ret; -} - -static int l2_ctl_probe(struct platform_device *pdev) -{ - struct l2_ctl *l2; - int ret; - - l2 = l2_ctl_create_data(pdev); - if (IS_ERR(l2)) - return PTR_ERR(l2); - - ret = l2_ctl_find_sys_regs(l2); - if (ret) - return ret; - - ret = l2_ctl_of_parse(l2); - if (ret) - return ret; - - ret = l2_ctl_init_sysfs(l2); - if (ret) - return ret; - - return 0; -} - -static const struct of_device_id l2_ctl_of_match[] = { - { .compatible = "baikal,bt1-l2-ctl" }, - { } -}; -MODULE_DEVICE_TABLE(of, l2_ctl_of_match); - -static struct platform_driver l2_ctl_driver = { - .probe = l2_ctl_probe, - .driver = { - .name = "bt1-l2-ctl", - .of_match_table = l2_ctl_of_match - } -}; -module_platform_driver(l2_ctl_driver); - -MODULE_AUTHOR("Serge Semin "); -MODULE_DESCRIPTION("Baikal-T1 L2-cache driver"); -- cgit v1.2.3 From 9983d51d1a68520ce74663920929e27b191cf43a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 25 Feb 2026 18:37:21 +0100 Subject: dt-bindings: cache: bt1-l2-ctl: Remove unused bindings As stated in [1] the Baikal platforms are not supported and the respective driver code has just been removed. Remove unused bindings. Link: https://lore.kernel.org/lkml/22b92ddf-6321-41b5-8073-f9c7064d3432@infradead.org/ [1] Acked-by: Conor Dooley Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20260225173930.3819351-3-andriy.shevchenko@linux.intel.com Signed-off-by: Krzysztof Kozlowski --- .../bindings/cache/baikal,bt1-l2-ctl.yaml | 63 ---------------------- 1 file changed, 63 deletions(-) delete mode 100644 Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml diff --git a/Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml b/Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml deleted file mode 100644 index ec4f367bc0b4..000000000000 --- a/Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -# Copyright (C) 2020 BAIKAL ELECTRONICS, JSC -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/cache/baikal,bt1-l2-ctl.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Baikal-T1 L2-cache Control Block - -maintainers: - - Serge Semin - -description: | - By means of the System Controller Baikal-T1 SoC exposes a few settings to - tune the MIPS P5600 CM2 L2 cache performance up. In particular it's possible - to change the Tag, Data and Way-select RAM access latencies. Baikal-T1 - L2-cache controller block is responsible for the tuning. Its DT node is - supposed to be a child of the system controller. - -properties: - compatible: - const: baikal,bt1-l2-ctl - - reg: - maxItems: 1 - - baikal,l2-ws-latency: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Cycles of latency for Way-select RAM accesses - default: 0 - minimum: 0 - maximum: 3 - - baikal,l2-tag-latency: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Cycles of latency for Tag RAM accesses - default: 0 - minimum: 0 - maximum: 3 - - baikal,l2-data-latency: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Cycles of latency for Data RAM accesses - default: 1 - minimum: 0 - maximum: 3 - -additionalProperties: false - -required: - - compatible - -examples: - - | - l2@1f04d028 { - compatible = "baikal,bt1-l2-ctl"; - reg = <0x1f04d028 0x004>; - - baikal,l2-ws-latency = <1>; - baikal,l2-tag-latency = <1>; - baikal,l2-data-latency = <2>; - }; -... -- cgit v1.2.3 From a969a0835152984a0f556434eafdee0b84213670 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 21 Jan 2026 16:35:00 -0800 Subject: memory: brcmstb_memc: Expand LPDDR4 check to cover for LPDDR5 The same limitations that apply to LPDDR4 also apply to LPDDR5. Expand the check and rename accordingly. Signed-off-by: Florian Fainelli Link: https://patch.msgid.link/20260122003501.1191059-1-florian.fainelli@broadcom.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_memc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/memory/brcmstb_memc.c b/drivers/memory/brcmstb_memc.c index ba73470b1b13..c28fe9093616 100644 --- a/drivers/memory/brcmstb_memc.c +++ b/drivers/memory/brcmstb_memc.c @@ -14,6 +14,7 @@ #define REG_MEMC_CNTRLR_CONFIG 0x00 #define CNTRLR_CONFIG_LPDDR4_SHIFT 5 +#define CNTRLR_CONFIG_LPDDR5_SHIFT 6 #define CNTRLR_CONFIG_MASK 0xf #define REG_MEMC_SRPD_CFG_21 0x20 #define REG_MEMC_SRPD_CFG_20 0x34 @@ -34,14 +35,15 @@ struct brcmstb_memc { u32 srpd_offset; }; -static int brcmstb_memc_uses_lpddr4(struct brcmstb_memc *memc) +static int brcmstb_memc_uses_lpddr45(struct brcmstb_memc *memc) { void __iomem *config = memc->ddr_ctrl + REG_MEMC_CNTRLR_CONFIG; u32 reg; reg = readl_relaxed(config) & CNTRLR_CONFIG_MASK; - return reg == CNTRLR_CONFIG_LPDDR4_SHIFT; + return reg == CNTRLR_CONFIG_LPDDR4_SHIFT || + reg == CNTRLR_CONFIG_LPDDR5_SHIFT; } static int brcmstb_memc_srpd_config(struct brcmstb_memc *memc, @@ -95,7 +97,7 @@ static ssize_t srpd_store(struct device *dev, struct device_attribute *attr, * dynamic tuning process will also get affected by the inactivity * timeout, thus making it non functional. */ - if (brcmstb_memc_uses_lpddr4(memc)) + if (brcmstb_memc_uses_lpddr45(memc)) return -EOPNOTSUPP; ret = kstrtouint(buf, 10, &val); -- cgit v1.2.3 From 8a39b1d4b358f8ccae29166e239f4dd2594b2e7c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:24 +0100 Subject: memory: renesas-rpc-if: Simplify printing PTR_ERR with dev_err_probe Use dev_err_probe() to simplify the code and fix Coccinelle warning: renesas-rpc-if.c:1010:3-10: WARNING: Consider using %pe to print PTR_ERR() Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260226-memory-simplify-v1-1-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 58ccc1c02e90..0fb568456164 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -1005,11 +1005,9 @@ static int rpcif_probe(struct platform_device *pdev) return PTR_ERR(rpc->base); rpc->info = of_device_get_match_data(dev); rpc->regmap = devm_regmap_init(dev, NULL, rpc, rpc->info->regmap_config); - if (IS_ERR(rpc->regmap)) { - dev_err(dev, "failed to init regmap for rpcif, error %ld\n", - PTR_ERR(rpc->regmap)); - return PTR_ERR(rpc->regmap); - } + if (IS_ERR(rpc->regmap)) + return dev_err_probe(dev, PTR_ERR(rpc->regmap), + "failed to init regmap for rpcif\n"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); rpc->dirmap = devm_ioremap_resource(dev, res); -- cgit v1.2.3 From 2ac5ba4c50be535497dc01089e4113185e4ccad1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:25 +0100 Subject: memory: tegra-mc: Drop tegra_mc_setup_latency_allowance() return value tegra_mc_setup_latency_allowance() only succeeds, thus its return value can be dropped making code a bit simpler. Signed-off-by: Krzysztof Kozlowski Acked-by: Thierry Reding Link: https://patch.msgid.link/20260226-memory-simplify-v1-2-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 6edb210287dc..c33f514fc804 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -386,7 +386,7 @@ EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count); defined(CONFIG_ARCH_TEGRA_124_SOC) || \ defined(CONFIG_ARCH_TEGRA_132_SOC) || \ defined(CONFIG_ARCH_TEGRA_210_SOC) -static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc) +static void tegra_mc_setup_latency_allowance(struct tegra_mc *mc) { unsigned long long tick; unsigned int i; @@ -414,8 +414,6 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc) /* latch new values */ mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL); - - return 0; } static int load_one_timing(struct tegra_mc *mc, @@ -517,11 +515,7 @@ int tegra30_mc_probe(struct tegra_mc *mc) /* ensure that debug features are disabled */ mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG); - err = tegra_mc_setup_latency_allowance(mc); - if (err < 0) { - dev_err(mc->dev, "failed to setup latency allowance: %d\n", err); - return err; - } + tegra_mc_setup_latency_allowance(mc); err = tegra_mc_setup_timings(mc); if (err < 0) { -- cgit v1.2.3 From f7bd985ad907ed85999f4bac4870abe35dcd2745 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:26 +0100 Subject: memory: tegra-mc: Simplify printing PTR_ERR with dev_err_probe Use dev_err_probe() to simplify the code and fix Coccinelle warning: tegra/mc.c:513:52-59: WARNING: Consider using %pe to print PTR_ERR() Signed-off-by: Krzysztof Kozlowski Acked-by: Thierry Reding Link: https://patch.msgid.link/20260226-memory-simplify-v1-3-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index c33f514fc804..1dc516a5be14 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -507,10 +507,9 @@ int tegra30_mc_probe(struct tegra_mc *mc) int err; mc->clk = devm_clk_get_optional(mc->dev, "mc"); - if (IS_ERR(mc->clk)) { - dev_err(mc->dev, "failed to get MC clock: %ld\n", PTR_ERR(mc->clk)); - return PTR_ERR(mc->clk); - } + if (IS_ERR(mc->clk)) + return dev_err_probe(mc->dev, PTR_ERR(mc->clk), + "failed to get MC clock\n"); /* ensure that debug features are disabled */ mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG); @@ -518,10 +517,8 @@ int tegra30_mc_probe(struct tegra_mc *mc) tegra_mc_setup_latency_allowance(mc); err = tegra_mc_setup_timings(mc); - if (err < 0) { - dev_err(mc->dev, "failed to setup timings: %d\n", err); - return err; - } + if (err < 0) + return dev_err_probe(mc->dev, err, "failed to setup timings\n"); return 0; } -- cgit v1.2.3 From 2413283fac5b2975f5ead6a1dcac7d5c6f7366d8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Feb 2026 21:35:27 +0100 Subject: memory: tegra-mc: Use %pe format Make code printing pointer error value a bit simpler and fix coccinelle suggestion: tegra/mc.c:975:4-11: WARNING: Consider using %pe to print PTR_ERR() Signed-off-by: Krzysztof Kozlowski Acked-by: Thierry Reding Link: https://patch.msgid.link/20260226-memory-simplify-v1-4-ccb94f378628@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 1dc516a5be14..67a0b0c07712 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -962,8 +962,7 @@ static int tegra_mc_probe(struct platform_device *pdev) if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU) && mc->soc->smmu) { mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc); if (IS_ERR(mc->smmu)) { - dev_err(&pdev->dev, "failed to probe SMMU: %ld\n", - PTR_ERR(mc->smmu)); + dev_err(&pdev->dev, "failed to probe SMMU: %pe\n", mc->smmu); mc->smmu = NULL; } } -- cgit v1.2.3 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 --- drivers/memory/tegra/mc.c | 47 ++++++++++++++++++++++++++++------------- drivers/memory/tegra/mc.h | 16 +------------- drivers/memory/tegra/tegra114.c | 3 ++- drivers/memory/tegra/tegra124.c | 4 +++- drivers/memory/tegra/tegra186.c | 3 ++- drivers/memory/tegra/tegra194.c | 3 ++- drivers/memory/tegra/tegra20.c | 3 ++- drivers/memory/tegra/tegra210.c | 3 ++- drivers/memory/tegra/tegra234.c | 3 ++- drivers/memory/tegra/tegra30.c | 3 ++- include/soc/tegra/mc.h | 22 ++++++++++++++++++- 11 files changed, 71 insertions(+), 39 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 67a0b0c07712..63f402aa1976 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -56,6 +56,23 @@ static const struct of_device_id tegra_mc_of_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_mc_of_match); +const struct tegra_mc_regs tegra20_mc_regs = { + .cfg_channel_enable = 0xdf8, + .err_status = 0x08, + .err_add = 0x0c, + .err_add_hi = 0x11fc, + .err_vpr_status = 0x654, + .err_vpr_add = 0x658, + .err_sec_status = 0x67c, + .err_sec_add = 0x680, + .err_mts_status = 0x9b0, + .err_mts_add = 0x9b4, + .err_gen_co_status = 0xc00, + .err_gen_co_add = 0xc04, + .err_route_status = 0x9c0, + .err_route_add = 0x9c4, +}; + static void tegra_mc_devm_action_put_device(void *data) { struct tegra_mc *mc = data; @@ -591,37 +608,37 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) switch (intmask) { case MC_INT_DECERR_VPR: - status_reg = MC_ERR_VPR_STATUS; - addr_reg = MC_ERR_VPR_ADR; + status_reg = mc->soc->regs->err_vpr_status; + addr_reg = mc->soc->regs->err_vpr_add; break; case MC_INT_SECERR_SEC: - status_reg = MC_ERR_SEC_STATUS; - addr_reg = MC_ERR_SEC_ADR; + status_reg = mc->soc->regs->err_sec_status; + addr_reg = mc->soc->regs->err_sec_add; break; case MC_INT_DECERR_MTS: - status_reg = MC_ERR_MTS_STATUS; - addr_reg = MC_ERR_MTS_ADR; + status_reg = mc->soc->regs->err_mts_status; + addr_reg = mc->soc->regs->err_mts_add; break; case MC_INT_DECERR_GENERALIZED_CARVEOUT: - status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS; - addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR; + status_reg = mc->soc->regs->err_gen_co_status; + addr_reg = mc->soc->regs->err_gen_co_add; break; case MC_INT_DECERR_ROUTE_SANITY: - status_reg = MC_ERR_ROUTE_SANITY_STATUS; - addr_reg = MC_ERR_ROUTE_SANITY_ADR; + status_reg = mc->soc->regs->err_route_status; + addr_reg = mc->soc->regs->err_route_add; break; default: - status_reg = MC_ERR_STATUS; - addr_reg = MC_ERR_ADR; + status_reg = mc->soc->regs->err_status; + addr_reg = mc->soc->regs->err_add; #ifdef CONFIG_PHYS_ADDR_T_64BIT if (mc->soc->has_addr_hi_reg) - addr_hi_reg = MC_ERR_ADR_HI; + addr_hi_reg = mc->soc->regs->err_add_hi; #endif break; } @@ -874,7 +891,7 @@ static void tegra_mc_num_channel_enabled(struct tegra_mc *mc) unsigned int i; u32 value; - value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE); + value = mc_ch_readl(mc, 0, mc->soc->regs->cfg_channel_enable); if (value <= 0) { mc->num_channels = mc->soc->num_channels; return; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 1d97cf4d3a94..bbe3e2690c64 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2014-2025 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #ifndef MEMORY_TEGRA_MC_H @@ -14,8 +14,6 @@ #define MC_INTSTATUS 0x00 #define MC_INTMASK 0x04 -#define MC_ERR_STATUS 0x08 -#define MC_ERR_ADR 0x0c #define MC_GART_ERROR_REQ 0x30 #define MC_EMEM_ADR_CFG 0x54 #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 @@ -43,19 +41,7 @@ #define MC_EMEM_ARB_OVERRIDE 0xe8 #define MC_TIMING_CONTROL_DBG 0xf8 #define MC_TIMING_CONTROL 0xfc -#define MC_ERR_VPR_STATUS 0x654 -#define MC_ERR_VPR_ADR 0x658 -#define MC_ERR_SEC_STATUS 0x67c -#define MC_ERR_SEC_ADR 0x680 -#define MC_ERR_MTS_STATUS 0x9b0 -#define MC_ERR_MTS_ADR 0x9b4 -#define MC_ERR_ROUTE_SANITY_STATUS 0x9c0 -#define MC_ERR_ROUTE_SANITY_ADR 0x9c4 -#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 -#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 -#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8 #define MC_GLOBAL_INTSTATUS 0xf24 -#define MC_ERR_ADR_HI 0x11fc #define MC_INT_DECERR_ROUTE_SANITY BIT(20) #define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index 41350570c815..ea7e4c7bb5f8 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1114,4 +1114,5 @@ const struct tegra_mc_soc tegra114_mc_soc = { .resets = tegra114_mc_resets, .num_resets = ARRAY_SIZE(tegra114_mc_resets), .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 991d4f7bc070..f0cfe14bb475 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1275,6 +1275,7 @@ const struct tegra_mc_soc tegra124_mc_soc = { .num_resets = ARRAY_SIZE(tegra124_mc_resets), .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ @@ -1307,5 +1308,6 @@ const struct tegra_mc_soc tegra132_mc_soc = { .num_resets = ARRAY_SIZE(tegra124_mc_resets), .icc_ops = &tegra124_mc_icc_ops, .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index aee11457bf8e..51e2dd628fb4 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2017-2025 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -914,5 +914,6 @@ const struct tegra_mc_soc tegra186_mc_soc = { .ops = &tegra186_mc_ops, .ch_intmask = 0x0000000f, .global_intstatus_channel_shift = 0, + .regs = &tegra20_mc_regs, }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index 26035ac3a1eb..5b7ff2dd6812 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2017-2021 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1358,4 +1358,5 @@ const struct tegra_mc_soc tegra194_mc_soc = { .icc_ops = &tegra_mc_icc_ops, .ch_intmask = 0x00000f00, .global_intstatus_channel_shift = 8, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 4748113bfe9d..1b2b598ab564 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2012-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -778,4 +778,5 @@ const struct tegra_mc_soc tegra20_mc_soc = { .num_resets = ARRAY_SIZE(tegra20_mc_resets), .icc_ops = &tegra20_mc_icc_ops, .ops = &tegra20_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index 3c2949c16fde..e166b33848e9 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2015-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1287,4 +1287,5 @@ const struct tegra_mc_soc tegra210_mc_soc = { .resets = tegra210_mc_resets, .num_resets = ARRAY_SIZE(tegra210_mc_resets), .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 5f57cea48b62..512d054d7592 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2022-2026, NVIDIA CORPORATION. All rights reserved. */ #include @@ -1152,4 +1152,5 @@ const struct tegra_mc_soc tegra234_mc_soc = { * supported. */ .num_carveouts = 32, + .regs = &tegra20_mc_regs, }; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index a6bcde4b92c0..337501a30a73 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014-2026 NVIDIA CORPORATION. All rights reserved. */ #include @@ -1400,4 +1400,5 @@ const struct tegra_mc_soc tegra30_mc_soc = { .num_resets = ARRAY_SIZE(tegra30_mc_resets), .icc_ops = &tegra30_mc_icc_ops, .ops = &tegra30_mc_ops, + .regs = &tegra20_mc_regs, }; 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 95b714bd8c39d65b241aa1c346625b9c942af403 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:11 +0000 Subject: memory: tegra: Group register and fields The current register definitions are not in sorted order. Sort these registers according to their address. Put bit fields and masks of the corresponding registers below the register definitions to clearly identify which fields belongs to which registers. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-3-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.h | 62 +++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index bbe3e2690c64..5f816d703d81 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -13,13 +13,35 @@ #include #define MC_INTSTATUS 0x00 +/* Bit field of MC_INTSTATUS register */ +#define MC_INT_DECERR_EMEM BIT(6) +#define MC_INT_INVALID_GART_PAGE BIT(7) +#define MC_INT_SECURITY_VIOLATION BIT(8) +#define MC_INT_ARBITRATION_EMEM BIT(9) +#define MC_INT_INVALID_SMMU_PAGE BIT(10) +#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11) +#define MC_INT_DECERR_VPR BIT(12) +#define MC_INT_SECERR_SEC BIT(13) +#define MC_INT_DECERR_MTS BIT(16) +#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) +#define MC_INT_DECERR_ROUTE_SANITY BIT(20) + #define MC_INTMASK 0x04 #define MC_GART_ERROR_REQ 0x30 #define MC_EMEM_ADR_CFG 0x54 +#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0) + #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 #define MC_SECURITY_VIOLATION_STATUS 0x74 #define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff) +#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff + #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 +#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30) +#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31) +#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff + #define MC_EMEM_ARB_TIMING_RCD 0x98 #define MC_EMEM_ARB_TIMING_RP 0x9c #define MC_EMEM_ARB_TIMING_RC 0xa0 @@ -39,45 +61,27 @@ #define MC_EMEM_ARB_MISC1 0xdc #define MC_EMEM_ARB_RING1_THROTTLE 0xe0 #define MC_EMEM_ARB_OVERRIDE 0xe8 +#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3 + #define MC_TIMING_CONTROL_DBG 0xf8 #define MC_TIMING_CONTROL 0xfc +#define MC_TIMING_UPDATE BIT(0) + #define MC_GLOBAL_INTSTATUS 0xf24 -#define MC_INT_DECERR_ROUTE_SANITY BIT(20) -#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) -#define MC_INT_DECERR_MTS BIT(16) -#define MC_INT_SECERR_SEC BIT(13) -#define MC_INT_DECERR_VPR BIT(12) -#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11) -#define MC_INT_INVALID_SMMU_PAGE BIT(10) -#define MC_INT_ARBITRATION_EMEM BIT(9) -#define MC_INT_SECURITY_VIOLATION BIT(8) -#define MC_INT_INVALID_GART_PAGE BIT(7) -#define MC_INT_DECERR_EMEM BIT(6) +/* Bit field of MC_ERR_STATUS_0 register */ +#define MC_ERR_STATUS_RW BIT(16) +#define MC_ERR_STATUS_SECURITY BIT(17) +#define MC_ERR_STATUS_NONSECURE BIT(25) +#define MC_ERR_STATUS_WRITABLE BIT(26) +#define MC_ERR_STATUS_READABLE BIT(27) #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_READABLE BIT(27) -#define MC_ERR_STATUS_WRITABLE BIT(26) -#define MC_ERR_STATUS_NONSECURE BIT(25) + #define MC_ERR_STATUS_ADR_HI_SHIFT 20 #define MC_ERR_STATUS_ADR_HI_MASK 0x3 -#define MC_ERR_STATUS_SECURITY BIT(17) -#define MC_ERR_STATUS_RW BIT(16) - -#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0) - -#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff) -#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff - -#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff -#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30) -#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31) - -#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3 - -#define MC_TIMING_UPDATE BIT(0) #define MC_BROADCAST_CHANNEL ~0 -- 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(-) 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(-) 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(-) 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 From 82169065ffb07577075a5088b313d78673ded331 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Thu, 26 Feb 2026 16:31:15 +0000 Subject: memory: tegra: Add MC error logging support for Tegra264 In Tegra264, different components from memory subsystems like Memory Controller Fabric (MCF), HUB, HUB Common (HUBC), Side Band Shim (SBS) and channels have different interrupt lines for receiving memory controller error interrupts. Add support for logging memory controller errors reported by these memory subsystems on Tegra264 by: - Renaming tegra_mc_error_names array to tegra20_mc_error_names because it has a different bit index for error names compared to Tegra264. - Defining the intmask registers and mask values supported for Tegra264. - Registering interrupt handlers for interrupts associated with these different MC components which read the interrupt status registers to determine the type of violation that occurred. Signed-off-by: Ketan Patil Reviewed-by: Jon Hunter Tested-by: Jon Hunter Link: https://patch.msgid.link/20260226163115.1152181-7-ketanp@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 5 +- drivers/memory/tegra/mc.h | 72 ++++++- drivers/memory/tegra/tegra20.c | 6 +- drivers/memory/tegra/tegra264.c | 411 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 484 insertions(+), 10 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index dccebbed7833..d620660da331 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -690,7 +690,7 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data) type = (value & mc->soc->mc_err_status_type_mask) >> MC_ERR_STATUS_TYPE_SHIFT; - desc = tegra_mc_error_names[type]; + desc = tegra20_mc_error_names[type]; switch (value & mc->soc->mc_err_status_type_mask) { case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE: @@ -758,9 +758,10 @@ const char *const tegra_mc_status_names[32] = { [16] = "MTS carveout violation", [17] = "Generalized carveout violation", [20] = "Route Sanity error", + [21] = "GIC_MSI error", }; -const char *const tegra_mc_error_names[8] = { +const char *const tegra20_mc_error_names[8] = { [2] = "EMEM decode error", [3] = "TrustZone violation", [4] = "Carveout violation", diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index b286c2558fd5..649b54369263 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -25,6 +25,7 @@ #define MC_INT_DECERR_MTS BIT(16) #define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) #define MC_INT_DECERR_ROUTE_SANITY BIT(20) +#define MC_INT_DECERR_ROUTE_SANITY_GIC_MSI BIT(21) #define MC_INTMASK 0x04 #define MC_GART_ERROR_REQ 0x30 @@ -76,13 +77,82 @@ #define MC_ERR_STATUS_WRITABLE BIT(26) #define MC_ERR_STATUS_READABLE BIT(27) +#define MC_ERR_STATUS_GSC_ADR_HI_MASK 0xffff +#define MC_ERR_STATUS_GSC_ADR_HI_SHIFT 16 +#define MC_ERR_STATUS_RT_ADR_HI_SHIFT 15 + #define MC_ERR_STATUS_TYPE_SHIFT 28 #define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28) +#define MC_ERR_STATUS_RT_TYPE_MASK (0xf << 28) +#define MC_ERR_STATUS_RT_TYPE_SHIFT 28 #define MC_ERR_STATUS_ADR_HI_SHIFT 20 #define MC_BROADCAST_CHANNEL ~0 +/* Tegra264 specific registers */ + +/* Registers for MSS HUB */ +#define MSS_HUB_GLOBAL_INTSTATUS_0 0x6000 +#define MSS_HUBC_INTR BIT(0) +#define MSS_HUB_GLOBAL_MASK 0x7F00 +#define MSS_HUB_GLOBAL_SHIFT 8 + +#define MSS_HUB_HUBC_INTSTATUS_0 0x6008 +#define MSS_HUB_INTRSTATUS_0 0x600c +#define MSS_HUB_HUBC_INTMASK_0 0x6010 +#define MSS_HUB_HUBC_SCRUB_DONE_INTMASK BIT(0) + +#define MSS_HUB_HUBC_INTPRIORITY_0 0x6014 +#define MSS_HUB_INTRMASK_0 0x6018 +#define MSS_HUB_COALESCER_ERR_INTMASK BIT(0) +#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK BIT(1) +#define MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK BIT(2) +#define MSS_HUB_MSI_ERR_INTMASK BIT(3) +#define MSS_HUB_POISON_RSP_INTMASK BIT(4) +#define MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK BIT(5) +#define MSS_HUB_RESERVED_PA_ERR_INTMASK BIT(6) + +#define MSS_HUB_INTRPRIORITY_0 0x601c +#define MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0 0x6020 +#define MSS_HUB_MSI_ERR_STATUS_0 0x6024 +#define MSS_HUB_POISON_RSP_STATUS_0 0x6028 +#define MSS_HUB_COALESCE_ERR_STATUS_0 0x60e0 +#define MSS_HUB_COALESCE_ERR_ADR_HI_0 0x60e4 +#define MSS_HUB_COALESCE_ERR_ADR_0 0x60e8 +#define MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0 0x638c +#define MSS_HUB_RESERVED_PA_ERR_STATUS_0 0x6390 +#define MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0 0x63b0 + +/* Registers for channels */ +#define MC_CH_INTSTATUS_0 0x82d4 +#define MC_CH_INTMASK_0 0x82d8 +#define WCAM_ERR_INTMASK BIT(19) + +#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0 0xbc74 + +/* Registers for MCF */ +#define MCF_COMMON_INTSTATUS0_0_0 0xce04 +#define MCF_INTSTATUS_0 0xce2c +#define MCF_INTMASK_0 0xce30 +#define MCF_INTPRIORITY_0 0xce34 + +/* Registers for SBS */ +#define MSS_SBS_INTSTATUS_0 0xec08 +#define MSS_SBS_INTMASK_0 0xec0c +#define MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK BIT(0) +#define MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK BIT(1) +#define MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK BIT(2) + +/* Bit field of MC_ERR_ROUTE_SANITY_STATUS_0 register */ +#define MC_ERR_ROUTE_SANITY_RW BIT(12) +#define MC_ERR_ROUTE_SANITY_SEC BIT(13) + +#define ERR_GENERALIZED_APERTURE_ID_SHIFT 0 +#define ERR_GENERALIZED_APERTURE_ID_MASK 0x1F +#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT 5 +#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK 0x1F + static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents) { val = val * percents; @@ -193,7 +263,7 @@ extern const struct tegra_mc_ops tegra186_mc_ops; 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]; +extern const char * const tegra20_mc_error_names[8]; /* * These IDs are for internal use of Tegra ICC drivers. The ID numbers are diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index ff9e151b5a4c..27dd6886f86e 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c @@ -713,7 +713,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) value = mc_readl(mc, reg); id = value & mc->soc->client_id_mask; - desc = tegra_mc_error_names[2]; + desc = tegra20_mc_error_names[2]; if (value & BIT(31)) direction = "write"; @@ -724,7 +724,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) value = mc_readl(mc, reg); id = (value >> 1) & mc->soc->client_id_mask; - desc = tegra_mc_error_names[2]; + desc = tegra20_mc_error_names[2]; if (value & BIT(0)) direction = "write"; @@ -736,7 +736,7 @@ static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) id = value & mc->soc->client_id_mask; type = (value & BIT(30)) ? 4 : 3; - desc = tegra_mc_error_names[type]; + desc = tegra20_mc_error_names[type]; secure = "secure "; if (value & BIT(31)) diff --git a/drivers/memory/tegra/tegra264.c b/drivers/memory/tegra/tegra264.c index 172a48b56484..e43ef14da1ee 100644 --- a/drivers/memory/tegra/tegra264.c +++ b/drivers/memory/tegra/tegra264.c @@ -188,6 +188,41 @@ static const struct tegra_mc_client tegra264_mc_clients[] = { }, }; +static const char *const tegra264_hub_error_names[32] = { + [0] = "coalescer error", + [1] = "SMMU BYPASS ALLOW error", + [2] = "Illegal tbugrp_id error", + [3] = "Malformed MSI request error", + [4] = "Read response with poison bit error", + [5] = "Restricted access violation error", + [6] = "Reserved PA error", +}; + +static const char *const tegra264_mc_error_names[4] = { + [1] = "EMEM decode error", + [2] = "TrustZone violation", + [3] = "Carveout violation", +}; + +static const char *const tegra264_rt_error_names[16] = { + [1] = "DECERR_PARTIAL_POPULATED", + [2] = "DECERR_SMMU_BYPASS", + [3] = "DECERR_INVALID_MMIO", + [4] = "DECERR_INVALID_GIC_MSI", + [5] = "DECERR_ATOMIC_SYSRAM", + [9] = "DECERR_REMOTE_REQ_PRE_BOOT", + [10] = "DECERR_ISO_OVER_C2C", + [11] = "DECERR_UNSUPPORTED_SBS_OPCODE", + [12] = "DECERR_SBS_REQ_OVER_SISO_LL", +}; + +/* + * MC instance aperture mapping for hubc registers + */ +static const int mc_hubc_aperture_number[5] = { + 7, 8, 9, 10, 11 +}; + /* * tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW * @src: ICC node for Memory Controller's (MC) Client @@ -283,6 +318,312 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea return 0; } +static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus) +{ + unsigned int bit; + + for_each_set_bit(bit, &mcf_ch_intstatus, 32) { + const char *client = "unknown", *desc = "NA"; + u32 status_reg, status1_reg = 0, addr_reg, addr_hi_reg = 0, err_type_mask = 0; + u32 value, client_id, i, addr_hi_shift = 0, addr_hi_mask = 0, status1; + u32 mc_rw_bit = MC_ERR_STATUS_RW, mc_sec_bit = MC_ERR_STATUS_SECURITY; + phys_addr_t addr = 0; + u8 type; + + switch (BIT(bit)) { + case MC_INT_DECERR_EMEM: + case MC_INT_SECURITY_VIOLATION: + status_reg = mc->soc->regs->err_status; + addr_reg = mc->soc->regs->err_add; + addr_hi_reg = mc->soc->regs->err_add_hi; + err_type_mask = mc->soc->mc_err_status_type_mask; + break; + + case MC_INT_DECERR_VPR: + status_reg = mc->soc->regs->err_vpr_status; + addr_reg = mc->soc->regs->err_vpr_add; + addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; + addr_hi_mask = mc->soc->mc_addr_hi_mask; + break; + + case MC_INT_SECERR_SEC: + status_reg = mc->soc->regs->err_sec_status; + addr_reg = mc->soc->regs->err_sec_add; + addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; + addr_hi_mask = mc->soc->mc_addr_hi_mask; + break; + + case MC_INT_DECERR_MTS: + status_reg = mc->soc->regs->err_mts_status; + addr_reg = mc->soc->regs->err_mts_add; + addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT; + addr_hi_mask = mc->soc->mc_addr_hi_mask; + break; + + case MC_INT_DECERR_GENERALIZED_CARVEOUT: + status_reg = mc->soc->regs->err_gen_co_status; + status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0; + addr_reg = mc->soc->regs->err_gen_co_add; + addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT; + addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK; + break; + + case MC_INT_DECERR_ROUTE_SANITY: + case MC_INT_DECERR_ROUTE_SANITY_GIC_MSI: + status_reg = mc->soc->regs->err_route_status; + addr_reg = mc->soc->regs->err_route_add; + addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT; + addr_hi_mask = mc->soc->mc_addr_hi_mask; + mc_sec_bit = MC_ERR_ROUTE_SANITY_SEC; + mc_rw_bit = MC_ERR_ROUTE_SANITY_RW; + err_type_mask = MC_ERR_STATUS_RT_TYPE_MASK; + break; + + default: + dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n"); + return; + } + + value = mc_ch_readl(mc, channel, status_reg); + if (addr_hi_reg) { + addr = mc_ch_readl(mc, channel, addr_hi_reg); + } else { + if (!status1_reg) { + addr = ((value >> addr_hi_shift) & addr_hi_mask); + } else { + status1 = mc_ch_readl(mc, channel, status1_reg); + addr = ((status1 >> addr_hi_shift) & addr_hi_mask); + } + } + + addr <<= 32; + addr |= mc_ch_readl(mc, channel, addr_reg); + + client_id = value & mc->soc->client_id_mask; + for (i = 0; i < mc->soc->num_clients; i++) { + if (mc->soc->clients[i].id == client_id) { + client = mc->soc->clients[i].name; + break; + } + } + + if (err_type_mask == MC_ERR_STATUS_RT_TYPE_MASK) { + type = (value & err_type_mask) >> + MC_ERR_STATUS_RT_TYPE_SHIFT; + desc = tegra264_rt_error_names[type]; + } else if (err_type_mask) { + type = (value & err_type_mask) >> + MC_ERR_STATUS_TYPE_SHIFT; + desc = tegra264_mc_error_names[type]; + } + + dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n", + client, value & mc_sec_bit ? "secure" : "non-secure", + value & mc_rw_bit ? "write" : "read", &addr, + tegra_mc_status_names[bit] ?: "unknown", desc); + if (status1_reg) + dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n", + ((status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT) + & ERR_GENERALIZED_APERTURE_ID_MASK), + ((status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT) + & ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK)); + } + + /* clear interrupts */ + mc_ch_writel(mc, channel, mcf_ch_intstatus, MCF_INTSTATUS_0); +} + +static irqreturn_t handle_mcf_irq(int irq, void *data) +{ + struct tegra_mc *mc = data; + unsigned long common_intstat, intstatus; + u32 slice; + + /* Read MCF_COMMON_INTSTATUS0_0_0 from MCB block */ + common_intstat = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, MCF_COMMON_INTSTATUS0_0_0); + if (common_intstat == 0) { + dev_warn(mc->dev, "No interrupt in MCF\n"); + return IRQ_NONE; + } + + for_each_set_bit(slice, &common_intstat, 32) { + /* Find out the slice number on which interrupt occurred */ + if (slice > 4) { + dev_err(mc->dev, "Slice index out of bounds: %u\n", slice); + return IRQ_NONE; + } + + intstatus = mc_ch_readl(mc, slice, MCF_INTSTATUS_0); + if (intstatus != 0) + mcf_log_fault(mc, slice, intstatus); + } + + return IRQ_HANDLED; +} + +static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat) +{ + unsigned int bit; + + for_each_set_bit(bit, &hub_intstat, 32) { + const char *client = "unknown"; + u32 client_id, status_reg, value, i; + phys_addr_t addr = 0; + + switch (BIT(bit)) { + case MSS_HUB_COALESCER_ERR_INTMASK: + status_reg = MSS_HUB_COALESCE_ERR_STATUS_0; + addr = mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_HI_0); + addr <<= 32; + addr |= mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_0); + break; + + case MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK: + status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0; + break; + + case MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK: + status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0; + break; + + case MSS_HUB_MSI_ERR_INTMASK: + status_reg = MSS_HUB_MSI_ERR_STATUS_0; + break; + + case MSS_HUB_POISON_RSP_INTMASK: + status_reg = MSS_HUB_POISON_RSP_STATUS_0; + break; + + case MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK: + status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0; + break; + + case MSS_HUB_RESERVED_PA_ERR_INTMASK: + status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0; + break; + + default: + dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n"); + return; + } + + value = mc_ch_readl(mc, hub, status_reg); + + client_id = value & mc->soc->client_id_mask; + for (i = 0; i < mc->soc->num_clients; i++) { + if (mc->soc->clients[i].id == client_id) { + client = mc->soc->clients[i].name; + break; + } + } + + dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n", + client, &addr, tegra264_hub_error_names[bit] ?: "unknown", + value); + } + + /* clear interrupts */ + mc_ch_writel(mc, hub, hub_intstat, MSS_HUB_INTRSTATUS_0); +} + +static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_number) +{ + struct tegra_mc *mc = data; + u32 global_intstat; + unsigned long hub_interrupt, intstat, hub; + + /* Read MSS_HUB_GLOBAL_INTSTATUS_0 from mc_hubc_aperture_number block */ + global_intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_GLOBAL_INTSTATUS_0); + if (global_intstat == 0) { + dev_warn(mc->dev, "No interrupt in HUB/HUBC\n"); + return IRQ_NONE; + } + + /* Handle interrupt from hubc */ + if (global_intstat & MSS_HUBC_INTR) { + /* Read MSS_HUB_HUBC_INTSTATUS_0 from block mc_hubc_aperture_number */ + intstat = mc_ch_readl(mc, mc_hubc_aperture_number, MSS_HUB_HUBC_INTSTATUS_0); + if (intstat != 0) { + dev_err_ratelimited(mc->dev, "Scrubber operation status: 0x%lx\n", + intstat); + /* Clear hubc interrupt */ + mc_ch_writel(mc, mc_hubc_aperture_number, intstat, + MSS_HUB_HUBC_INTSTATUS_0); + } + } + + hub_interrupt = (global_intstat & MSS_HUB_GLOBAL_MASK) >> MSS_HUB_GLOBAL_SHIFT; + /* Handle interrupt from hub */ + for_each_set_bit(hub, &hub_interrupt, 32) { + /* Read MSS_HUB_INTRSTATUS_0 from block MCi */ + intstat = mc_ch_readl(mc, hub, MSS_HUB_INTRSTATUS_0); + if (intstat != 0) + hub_log_fault(mc, hub, intstat); + } + + /* Clear global interrupt status register */ + mc_ch_writel(mc, mc_hubc_aperture_number, global_intstat, MSS_HUB_GLOBAL_INTSTATUS_0); + return IRQ_HANDLED; +} + +static irqreturn_t handle_disp_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]); +} + +static irqreturn_t handle_system_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]); +} + +static irqreturn_t handle_vision_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]); +} + +static irqreturn_t handle_uphy_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]); +} + +static irqreturn_t handle_top_hub_irq(int irq, void *data) +{ + return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]); +} + +static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg) +{ + u32 intstat, i; + + /* Iterate over all MC blocks to read INTSTATUS */ + for (i = 0; i < mc->num_channels; i++) { + intstat = mc_ch_readl(mc, i, intstat_reg); + if (intstat) { + dev_err_ratelimited(mc->dev, "channel: %i status: 0x%x\n", i, intstat); + /* Clear interrupt */ + mc_ch_writel(mc, i, intstat, intstat_reg); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t handle_sbs_irq(int irq, void *data) +{ + return handle_generic_irq((struct tegra_mc *)data, MSS_SBS_INTSTATUS_0); +} + +static irqreturn_t handle_channel_irq(int irq, void *data) +{ + return handle_generic_irq((struct tegra_mc *)data, MC_CH_INTSTATUS_0); +} + +static const irq_handler_t tegra264_mc_irq_handlers[8] = { + handle_mcf_irq, handle_disp_hub_irq, handle_vision_hub_irq, + handle_system_hub_irq, handle_uphy_hub_irq, handle_top_hub_irq, + handle_sbs_irq, handle_channel_irq +}; + static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = { .xlate = tegra_mc_icc_xlate, .aggregate = tegra264_mc_icc_aggregate, @@ -290,13 +631,70 @@ static const struct tegra_mc_icc_ops tegra264_mc_icc_ops = { .set = tegra264_mc_icc_set, }; +static const struct tegra_mc_regs tegra264_mc_regs = { + .cfg_channel_enable = 0x8870, + .err_status = 0xbc00, + .err_add = 0xbc04, + .err_add_hi = 0xbc08, + .err_vpr_status = 0xbc20, + .err_vpr_add = 0xbc24, + .err_sec_status = 0xbc3c, + .err_sec_add = 0xbc40, + .err_mts_status = 0xbc5c, + .err_mts_add = 0xbc60, + .err_gen_co_status = 0xbc78, + .err_gen_co_add = 0xbc7c, + .err_route_status = 0xbc64, + .err_route_add = 0xbc68, +}; + 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, + .reg = MCF_INTMASK_0, + .mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | 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, }, + { + .reg = MCF_INTPRIORITY_0, + .mask = MC_INT_DECERR_ROUTE_SANITY_GIC_MSI | 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, + }, + { + .reg = MSS_HUB_INTRMASK_0, + .mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK | + MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK | + MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK | + MSS_HUB_RESERVED_PA_ERR_INTMASK, + }, + { + .reg = MSS_HUB_INTRPRIORITY_0, + .mask = MSS_HUB_COALESCER_ERR_INTMASK | MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK | + MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK | MSS_HUB_MSI_ERR_INTMASK | + MSS_HUB_POISON_RSP_INTMASK | MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK | + MSS_HUB_RESERVED_PA_ERR_INTMASK, + }, + { + .reg = MSS_HUB_HUBC_INTMASK_0, + .mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK, + }, + { + .reg = MSS_HUB_HUBC_INTPRIORITY_0, + .mask = MSS_HUB_HUBC_SCRUB_DONE_INTMASK, + }, + { + .reg = MSS_SBS_INTMASK_0, + .mask = MSS_SBS_FILL_FIFO_ISO_OVERFLOW_INTMASK | + MSS_SBS_FILL_FIFO_SISO_OVERFLOW_INTMASK | + MSS_SBS_FILL_FIFO_NISO_OVERFLOW_INTMASK, + }, + { + .reg = MC_CH_INTMASK_0, + .mask = WCAM_ERR_INTMASK, + } }; const struct tegra_mc_soc tegra264_mc_soc = { @@ -317,4 +715,9 @@ const struct tegra_mc_soc tegra264_mc_soc = { * supported. */ .num_carveouts = 32, + .mc_addr_hi_mask = 0xff, + .mc_err_status_type_mask = (0x3 << 28), + .regs = &tegra264_mc_regs, + .handle_irq = tegra264_mc_irq_handlers, + .num_interrupts = ARRAY_SIZE(tegra264_mc_irq_handlers), }; -- cgit v1.2.3