Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'memory-controller-drv-tegra-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into arm/drivers

Memory controller drivers for v5.19 - Tegra SoC

Add support for Tegra234 memory controller and for logging memory
controller errors on Tegra186, Tegra194 and Tegra234.

* tag 'memory-controller-drv-tegra-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
memory: tegra: Add MC error logging on Tegra186 onward
memory: tegra: Add memory controller channels support
memory: tegra: Add APE memory clients for Tegra234
memory: tegra: Add Tegra234 support

Link: https://lore.kernel.org/r/20220509160807.154187-1-krzysztof.kozlowski@linaro.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+338 -18
+2
drivers/memory/tegra/Makefile
··· 9 9 tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o 10 10 tegra-mc-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o 11 11 tegra-mc-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186.o tegra194.o 12 + tegra-mc-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186.o tegra234.o 12 13 13 14 obj-$(CONFIG_TEGRA_MC) += tegra-mc.o 14 15 ··· 20 19 obj-$(CONFIG_TEGRA210_EMC) += tegra210-emc.o 21 20 obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-emc.o 22 21 obj-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186-emc.o 22 + obj-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186-emc.o 23 23 24 24 tegra210-emc-y := tegra210-emc-core.o tegra210-emc-cc-r21021.o
+121 -16
drivers/memory/tegra/mc.c
··· 45 45 #ifdef CONFIG_ARCH_TEGRA_194_SOC 46 46 { .compatible = "nvidia,tegra194-mc", .data = &tegra194_mc_soc }, 47 47 #endif 48 + #ifdef CONFIG_ARCH_TEGRA_234_SOC 49 + { .compatible = "nvidia,tegra234-mc", .data = &tegra234_mc_soc }, 50 + #endif 48 51 { /* sentinel */ } 49 52 }; 50 53 MODULE_DEVICE_TABLE(of, tegra_mc_of_match); ··· 508 505 return 0; 509 506 } 510 507 511 - static irqreturn_t tegra30_mc_handle_irq(int irq, void *data) 508 + const struct tegra_mc_ops tegra30_mc_ops = { 509 + .probe = tegra30_mc_probe, 510 + .handle_irq = tegra30_mc_handle_irq, 511 + }; 512 + #endif 513 + 514 + static int mc_global_intstatus_to_channel(const struct tegra_mc *mc, u32 status, 515 + unsigned int *mc_channel) 516 + { 517 + if ((status & mc->soc->ch_intmask) == 0) 518 + return -EINVAL; 519 + 520 + *mc_channel = __ffs((status & mc->soc->ch_intmask) >> 521 + mc->soc->global_intstatus_channel_shift); 522 + 523 + return 0; 524 + } 525 + 526 + static u32 mc_channel_to_global_intstatus(const struct tegra_mc *mc, 527 + unsigned int channel) 528 + { 529 + return BIT(channel) << mc->soc->global_intstatus_channel_shift; 530 + } 531 + 532 + irqreturn_t tegra30_mc_handle_irq(int irq, void *data) 512 533 { 513 534 struct tegra_mc *mc = data; 535 + unsigned int bit, channel; 514 536 unsigned long status; 515 - unsigned int bit; 516 537 517 - /* mask all interrupts to avoid flooding */ 518 - status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; 538 + if (mc->soc->num_channels) { 539 + u32 global_status; 540 + int err; 541 + 542 + global_status = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, MC_GLOBAL_INTSTATUS); 543 + err = mc_global_intstatus_to_channel(mc, global_status, &channel); 544 + if (err < 0) { 545 + dev_err_ratelimited(mc->dev, "unknown interrupt channel 0x%08x\n", 546 + global_status); 547 + return IRQ_NONE; 548 + } 549 + 550 + /* mask all interrupts to avoid flooding */ 551 + status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask; 552 + } else { 553 + status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; 554 + } 555 + 519 556 if (!status) 520 557 return IRQ_NONE; 521 558 ··· 563 520 const char *error = tegra_mc_status_names[bit] ?: "unknown"; 564 521 const char *client = "unknown", *desc; 565 522 const char *direction, *secure; 523 + u32 status_reg, addr_reg; 524 + u32 intmask = BIT(bit); 566 525 phys_addr_t addr = 0; 526 + #ifdef CONFIG_PHYS_ADDR_T_64BIT 527 + u32 addr_hi_reg = 0; 528 + #endif 567 529 unsigned int i; 568 530 char perm[7]; 569 531 u8 id, type; 570 532 u32 value; 571 533 572 - value = mc_readl(mc, MC_ERR_STATUS); 534 + switch (intmask) { 535 + case MC_INT_DECERR_VPR: 536 + status_reg = MC_ERR_VPR_STATUS; 537 + addr_reg = MC_ERR_VPR_ADR; 538 + break; 539 + 540 + case MC_INT_SECERR_SEC: 541 + status_reg = MC_ERR_SEC_STATUS; 542 + addr_reg = MC_ERR_SEC_ADR; 543 + break; 544 + 545 + case MC_INT_DECERR_MTS: 546 + status_reg = MC_ERR_MTS_STATUS; 547 + addr_reg = MC_ERR_MTS_ADR; 548 + break; 549 + 550 + case MC_INT_DECERR_GENERALIZED_CARVEOUT: 551 + status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS; 552 + addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR; 553 + break; 554 + 555 + case MC_INT_DECERR_ROUTE_SANITY: 556 + status_reg = MC_ERR_ROUTE_SANITY_STATUS; 557 + addr_reg = MC_ERR_ROUTE_SANITY_ADR; 558 + break; 559 + 560 + default: 561 + status_reg = MC_ERR_STATUS; 562 + addr_reg = MC_ERR_ADR; 563 + 564 + #ifdef CONFIG_PHYS_ADDR_T_64BIT 565 + if (mc->soc->has_addr_hi_reg) 566 + addr_hi_reg = MC_ERR_ADR_HI; 567 + #endif 568 + break; 569 + } 570 + 571 + if (mc->soc->num_channels) 572 + value = mc_ch_readl(mc, channel, status_reg); 573 + else 574 + value = mc_readl(mc, status_reg); 573 575 574 576 #ifdef CONFIG_PHYS_ADDR_T_64BIT 575 577 if (mc->soc->num_address_bits > 32) { 576 - addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) & 577 - MC_ERR_STATUS_ADR_HI_MASK); 578 + if (addr_hi_reg) { 579 + if (mc->soc->num_channels) 580 + addr = mc_ch_readl(mc, channel, addr_hi_reg); 581 + else 582 + addr = mc_readl(mc, addr_hi_reg); 583 + } else { 584 + addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) & 585 + MC_ERR_STATUS_ADR_HI_MASK); 586 + } 578 587 addr <<= 32; 579 588 } 580 589 #endif ··· 683 588 break; 684 589 } 685 590 686 - value = mc_readl(mc, MC_ERR_ADR); 591 + if (mc->soc->num_channels) 592 + value = mc_ch_readl(mc, channel, addr_reg); 593 + else 594 + value = mc_readl(mc, addr_reg); 687 595 addr |= value; 688 596 689 597 dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s%s)\n", ··· 695 597 } 696 598 697 599 /* clear interrupts */ 698 - mc_writel(mc, status, MC_INTSTATUS); 600 + if (mc->soc->num_channels) { 601 + mc_ch_writel(mc, channel, status, MC_INTSTATUS); 602 + mc_ch_writel(mc, MC_BROADCAST_CHANNEL, 603 + mc_channel_to_global_intstatus(mc, channel), 604 + MC_GLOBAL_INTSTATUS); 605 + } else { 606 + mc_writel(mc, status, MC_INTSTATUS); 607 + } 699 608 700 609 return IRQ_HANDLED; 701 610 } 702 - 703 - const struct tegra_mc_ops tegra30_mc_ops = { 704 - .probe = tegra30_mc_probe, 705 - .handle_irq = tegra30_mc_handle_irq, 706 - }; 707 - #endif 708 611 709 612 const char *const tegra_mc_status_names[32] = { 710 613 [ 1] = "External interrupt", ··· 718 619 [12] = "VPR violation", 719 620 [13] = "Secure carveout violation", 720 621 [16] = "MTS carveout violation", 622 + [17] = "Generalized carveout violation", 623 + [20] = "Route Sanity error", 721 624 }; 722 625 723 626 const char *const tegra_mc_error_names[8] = { ··· 860 759 861 760 WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n"); 862 761 863 - mc_writel(mc, mc->soc->intmask, MC_INTMASK); 762 + if (mc->soc->num_channels) 763 + mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask, 764 + MC_INTMASK); 765 + else 766 + mc_writel(mc, mc->soc->intmask, MC_INTMASK); 864 767 865 768 err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0, 866 769 dev_name(&pdev->dev), mc);
+47 -1
drivers/memory/tegra/mc.h
··· 43 43 #define MC_EMEM_ARB_OVERRIDE 0xe8 44 44 #define MC_TIMING_CONTROL_DBG 0xf8 45 45 #define MC_TIMING_CONTROL 0xfc 46 + #define MC_ERR_VPR_STATUS 0x654 47 + #define MC_ERR_VPR_ADR 0x658 48 + #define MC_ERR_SEC_STATUS 0x67c 49 + #define MC_ERR_SEC_ADR 0x680 50 + #define MC_ERR_MTS_STATUS 0x9b0 51 + #define MC_ERR_MTS_ADR 0x9b4 52 + #define MC_ERR_ROUTE_SANITY_STATUS 0x9c0 53 + #define MC_ERR_ROUTE_SANITY_ADR 0x9c4 54 + #define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 55 + #define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 56 + #define MC_GLOBAL_INTSTATUS 0xf24 57 + #define MC_ERR_ADR_HI 0x11fc 46 58 59 + #define MC_INT_DECERR_ROUTE_SANITY BIT(20) 60 + #define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17) 47 61 #define MC_INT_DECERR_MTS BIT(16) 48 62 #define MC_INT_SECERR_SEC BIT(13) 49 63 #define MC_INT_DECERR_VPR BIT(12) ··· 92 78 93 79 #define MC_TIMING_UPDATE BIT(0) 94 80 81 + #define MC_BROADCAST_CHANNEL ~0 82 + 95 83 static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents) 96 84 { 97 85 val = val * percents; ··· 106 90 icc_provider_to_tegra_mc(struct icc_provider *provider) 107 91 { 108 92 return container_of(provider, struct tegra_mc, provider); 93 + } 94 + 95 + static inline u32 mc_ch_readl(const struct tegra_mc *mc, int ch, 96 + unsigned long offset) 97 + { 98 + if (!mc->bcast_ch_regs) 99 + return 0; 100 + 101 + if (ch == MC_BROADCAST_CHANNEL) 102 + return readl_relaxed(mc->bcast_ch_regs + offset); 103 + 104 + return readl_relaxed(mc->ch_regs[ch] + offset); 105 + } 106 + 107 + static inline void mc_ch_writel(const struct tegra_mc *mc, int ch, 108 + u32 value, unsigned long offset) 109 + { 110 + if (!mc->bcast_ch_regs) 111 + return; 112 + 113 + if (ch == MC_BROADCAST_CHANNEL) 114 + writel_relaxed(value, mc->bcast_ch_regs + offset); 115 + else 116 + writel_relaxed(value, mc->ch_regs[ch] + offset); 109 117 } 110 118 111 119 static inline u32 mc_readl(const struct tegra_mc *mc, unsigned long offset) ··· 177 137 extern const struct tegra_mc_soc tegra194_mc_soc; 178 138 #endif 179 139 140 + #ifdef CONFIG_ARCH_TEGRA_234_SOC 141 + extern const struct tegra_mc_soc tegra234_mc_soc; 142 + #endif 143 + 180 144 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \ 181 145 defined(CONFIG_ARCH_TEGRA_114_SOC) || \ 182 146 defined(CONFIG_ARCH_TEGRA_124_SOC) || \ ··· 191 147 #endif 192 148 193 149 #if defined(CONFIG_ARCH_TEGRA_186_SOC) || \ 194 - defined(CONFIG_ARCH_TEGRA_194_SOC) 150 + defined(CONFIG_ARCH_TEGRA_194_SOC) || \ 151 + defined(CONFIG_ARCH_TEGRA_234_SOC) 195 152 extern const struct tegra_mc_ops tegra186_mc_ops; 196 153 #endif 197 154 155 + irqreturn_t tegra30_mc_handle_irq(int irq, void *data); 198 156 extern const char * const tegra_mc_status_names[32]; 199 157 extern const char * const tegra_mc_error_names[8]; 200 158
+3
drivers/memory/tegra/tegra186-emc.c
··· 273 273 #if defined(CONFIG_ARCH_TEGRA_194_SOC) 274 274 { .compatible = "nvidia,tegra194-emc" }, 275 275 #endif 276 + #if defined(CONFIG_ARCH_TEGRA_234_SOC) 277 + { .compatible = "nvidia,tegra234-emc" }, 278 + #endif 276 279 { /* sentinel */ } 277 280 }; 278 281 MODULE_DEVICE_TABLE(of, tegra186_emc_of_match);
+39
drivers/memory/tegra/tegra186.c
··· 16 16 #include <dt-bindings/memory/tegra186-mc.h> 17 17 #endif 18 18 19 + #include "mc.h" 20 + 19 21 #define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0) 20 22 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16) 21 23 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8) ··· 50 48 51 49 static int tegra186_mc_probe(struct tegra_mc *mc) 52 50 { 51 + struct platform_device *pdev = to_platform_device(mc->dev); 52 + unsigned int i; 53 + char name[8]; 53 54 int err; 54 55 56 + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast"); 57 + if (IS_ERR(mc->bcast_ch_regs)) { 58 + if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) { 59 + dev_warn(&pdev->dev, 60 + "Broadcast channel is missing, please update your device-tree\n"); 61 + mc->bcast_ch_regs = NULL; 62 + goto populate; 63 + } 64 + 65 + return PTR_ERR(mc->bcast_ch_regs); 66 + } 67 + 68 + mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs), 69 + GFP_KERNEL); 70 + if (!mc->ch_regs) 71 + return -ENOMEM; 72 + 73 + for (i = 0; i < mc->soc->num_channels; i++) { 74 + snprintf(name, sizeof(name), "ch%u", i); 75 + 76 + mc->ch_regs[i] = devm_platform_ioremap_resource_byname(pdev, name); 77 + if (IS_ERR(mc->ch_regs[i])) 78 + return PTR_ERR(mc->ch_regs[i]); 79 + } 80 + 81 + populate: 55 82 err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev); 56 83 if (err < 0) 57 84 return err; ··· 175 144 .remove = tegra186_mc_remove, 176 145 .resume = tegra186_mc_resume, 177 146 .probe_device = tegra186_mc_probe_device, 147 + .handle_irq = tegra30_mc_handle_irq, 178 148 }; 179 149 180 150 #if defined(CONFIG_ARCH_TEGRA_186_SOC) ··· 907 875 .num_clients = ARRAY_SIZE(tegra186_mc_clients), 908 876 .clients = tegra186_mc_clients, 909 877 .num_address_bits = 40, 878 + .num_channels = 4, 879 + .client_id_mask = 0xff, 880 + .intmask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | 881 + MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | 882 + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, 910 883 .ops = &tegra186_mc_ops, 884 + .ch_intmask = 0x0000000f, 885 + .global_intstatus_channel_shift = 0, 911 886 }; 912 887 #endif
+9
drivers/memory/tegra/tegra194.c
··· 1347 1347 .num_clients = ARRAY_SIZE(tegra194_mc_clients), 1348 1348 .clients = tegra194_mc_clients, 1349 1349 .num_address_bits = 40, 1350 + .num_channels = 16, 1351 + .client_id_mask = 0xff, 1352 + .intmask = MC_INT_DECERR_ROUTE_SANITY | 1353 + MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | 1354 + MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | 1355 + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, 1356 + .has_addr_hi_reg = true, 1350 1357 .ops = &tegra186_mc_ops, 1358 + .ch_intmask = 0x00000f00, 1359 + .global_intstatus_channel_shift = 8, 1351 1360 };
+110
drivers/memory/tegra/tegra234.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved. 4 + */ 5 + 6 + #include <soc/tegra/mc.h> 7 + 8 + #include <dt-bindings/memory/tegra234-mc.h> 9 + 10 + #include "mc.h" 11 + 12 + static const struct tegra_mc_client tegra234_mc_clients[] = { 13 + { 14 + .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB, 15 + .name = "sdmmcrab", 16 + .sid = TEGRA234_SID_SDMMC4, 17 + .regs = { 18 + .sid = { 19 + .override = 0x318, 20 + .security = 0x31c, 21 + }, 22 + }, 23 + }, { 24 + .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB, 25 + .name = "sdmmcwab", 26 + .sid = TEGRA234_SID_SDMMC4, 27 + .regs = { 28 + .sid = { 29 + .override = 0x338, 30 + .security = 0x33c, 31 + }, 32 + }, 33 + }, { 34 + .id = TEGRA234_MEMORY_CLIENT_BPMPR, 35 + .name = "bpmpr", 36 + .sid = TEGRA234_SID_BPMP, 37 + .regs = { 38 + .sid = { 39 + .override = 0x498, 40 + .security = 0x49c, 41 + }, 42 + }, 43 + }, { 44 + .id = TEGRA234_MEMORY_CLIENT_BPMPW, 45 + .name = "bpmpw", 46 + .sid = TEGRA234_SID_BPMP, 47 + .regs = { 48 + .sid = { 49 + .override = 0x4a0, 50 + .security = 0x4a4, 51 + }, 52 + }, 53 + }, { 54 + .id = TEGRA234_MEMORY_CLIENT_BPMPDMAR, 55 + .name = "bpmpdmar", 56 + .sid = TEGRA234_SID_BPMP, 57 + .regs = { 58 + .sid = { 59 + .override = 0x4a8, 60 + .security = 0x4ac, 61 + }, 62 + }, 63 + }, { 64 + .id = TEGRA234_MEMORY_CLIENT_BPMPDMAW, 65 + .name = "bpmpdmaw", 66 + .sid = TEGRA234_SID_BPMP, 67 + .regs = { 68 + .sid = { 69 + .override = 0x4b0, 70 + .security = 0x4b4, 71 + }, 72 + }, 73 + }, { 74 + .id = TEGRA234_MEMORY_CLIENT_APEDMAR, 75 + .name = "apedmar", 76 + .sid = TEGRA234_SID_APE, 77 + .regs = { 78 + .sid = { 79 + .override = 0x4f8, 80 + .security = 0x4fc, 81 + }, 82 + }, 83 + }, { 84 + .id = TEGRA234_MEMORY_CLIENT_APEDMAW, 85 + .name = "apedmaw", 86 + .sid = TEGRA234_SID_APE, 87 + .regs = { 88 + .sid = { 89 + .override = 0x500, 90 + .security = 0x504, 91 + }, 92 + }, 93 + }, 94 + }; 95 + 96 + const struct tegra_mc_soc tegra234_mc_soc = { 97 + .num_clients = ARRAY_SIZE(tegra234_mc_clients), 98 + .clients = tegra234_mc_clients, 99 + .num_address_bits = 40, 100 + .num_channels = 16, 101 + .client_id_mask = 0x1ff, 102 + .intmask = MC_INT_DECERR_ROUTE_SANITY | 103 + MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS | 104 + MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | 105 + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, 106 + .has_addr_hi_reg = true, 107 + .ops = &tegra186_mc_ops, 108 + .ch_intmask = 0x0000ff00, 109 + .global_intstatus_channel_shift = 8, 110 + };
+7 -1
include/soc/tegra/mc.h
··· 193 193 unsigned int num_address_bits; 194 194 unsigned int atom_size; 195 195 196 - u8 client_id_mask; 196 + u16 client_id_mask; 197 + u8 num_channels; 197 198 198 199 const struct tegra_smmu_soc *smmu; 199 200 200 201 u32 intmask; 202 + u32 ch_intmask; 203 + u32 global_intstatus_channel_shift; 204 + bool has_addr_hi_reg; 201 205 202 206 const struct tegra_mc_reset_ops *reset_ops; 203 207 const struct tegra_mc_reset *resets; ··· 216 212 struct tegra_smmu *smmu; 217 213 struct gart_device *gart; 218 214 void __iomem *regs; 215 + void __iomem *bcast_ch_regs; 216 + void __iomem **ch_regs; 219 217 struct clk *clk; 220 218 int irq; 221 219