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

Configure Feed

Select the types of activity you want to include in your feed.

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 <ketanp@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Link: https://patch.msgid.link/20260226163115.1152181-4-ketanp@nvidia.com
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

authored by

Ketan Patil and committed by
Krzysztof Kozlowski
4d865a23 95b714bd

+49 -18
+21 -13
drivers/memory/tegra/mc.c
··· 398 398 } 399 399 EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count); 400 400 401 + const irq_handler_t tegra30_mc_irq_handlers[] = { 402 + tegra30_mc_handle_irq 403 + }; 404 + 401 405 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \ 402 406 defined(CONFIG_ARCH_TEGRA_114_SOC) || \ 403 407 defined(CONFIG_ARCH_TEGRA_124_SOC) || \ ··· 546 542 547 543 const struct tegra_mc_ops tegra30_mc_ops = { 548 544 .probe = tegra30_mc_probe, 549 - .handle_irq = tegra30_mc_handle_irq, 550 545 }; 551 546 #endif 552 547 ··· 946 943 947 944 tegra_mc_num_channel_enabled(mc); 948 945 949 - if (mc->soc->ops && mc->soc->ops->handle_irq) { 950 - mc->irq = platform_get_irq(pdev, 0); 951 - if (mc->irq < 0) 952 - return mc->irq; 946 + if (mc->soc->handle_irq) { 947 + unsigned int i; 953 948 954 949 WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n"); 950 + 951 + for (i = 0; i < mc->soc->num_interrupts; i++) { 952 + int irq; 953 + 954 + irq = platform_get_irq(pdev, i); 955 + if (irq < 0) 956 + return irq; 957 + 958 + err = devm_request_irq(&pdev->dev, irq, mc->soc->handle_irq[i], 0, 959 + dev_name(&pdev->dev), mc); 960 + if (err < 0) { 961 + dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err); 962 + return err; 963 + } 964 + } 955 965 956 966 if (mc->soc->num_channels) 957 967 mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask, 958 968 MC_INTMASK); 959 969 else 960 970 mc_writel(mc, mc->soc->intmask, MC_INTMASK); 961 - 962 - err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0, 963 - dev_name(&pdev->dev), mc); 964 - if (err < 0) { 965 - dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq, 966 - err); 967 - return err; 968 - } 969 971 } 970 972 971 973 if (mc->soc->reset_ops) {
+1
drivers/memory/tegra/mc.h
··· 193 193 #endif 194 194 195 195 irqreturn_t tegra30_mc_handle_irq(int irq, void *data); 196 + extern const irq_handler_t tegra30_mc_irq_handlers[1]; 196 197 extern const char * const tegra_mc_status_names[32]; 197 198 extern const char * const tegra_mc_error_names[8]; 198 199
+2
drivers/memory/tegra/tegra114.c
··· 1115 1115 .num_resets = ARRAY_SIZE(tegra114_mc_resets), 1116 1116 .ops = &tegra30_mc_ops, 1117 1117 .regs = &tegra20_mc_regs, 1118 + .handle_irq = tegra30_mc_irq_handlers, 1119 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1118 1120 };
+4
drivers/memory/tegra/tegra124.c
··· 1276 1276 .icc_ops = &tegra124_mc_icc_ops, 1277 1277 .ops = &tegra30_mc_ops, 1278 1278 .regs = &tegra20_mc_regs, 1279 + .handle_irq = tegra30_mc_irq_handlers, 1280 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1279 1281 }; 1280 1282 #endif /* CONFIG_ARCH_TEGRA_124_SOC */ 1281 1283 ··· 1311 1309 .icc_ops = &tegra124_mc_icc_ops, 1312 1310 .ops = &tegra30_mc_ops, 1313 1311 .regs = &tegra20_mc_regs, 1312 + .handle_irq = tegra30_mc_irq_handlers, 1313 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1314 1314 }; 1315 1315 #endif /* CONFIG_ARCH_TEGRA_132_SOC */
+2 -1
drivers/memory/tegra/tegra186.c
··· 174 174 .remove = tegra186_mc_remove, 175 175 .resume = tegra186_mc_resume, 176 176 .probe_device = tegra186_mc_probe_device, 177 - .handle_irq = tegra30_mc_handle_irq, 178 177 }; 179 178 180 179 #if defined(CONFIG_ARCH_TEGRA_186_SOC) ··· 914 915 .ch_intmask = 0x0000000f, 915 916 .global_intstatus_channel_shift = 0, 916 917 .regs = &tegra20_mc_regs, 918 + .handle_irq = tegra30_mc_irq_handlers, 919 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 917 920 }; 918 921 #endif
+2
drivers/memory/tegra/tegra194.c
··· 1359 1359 .ch_intmask = 0x00000f00, 1360 1360 .global_intstatus_channel_shift = 8, 1361 1361 .regs = &tegra20_mc_regs, 1362 + .handle_irq = tegra30_mc_irq_handlers, 1363 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1362 1364 };
+6 -1
drivers/memory/tegra/tegra20.c
··· 761 761 return IRQ_HANDLED; 762 762 } 763 763 764 + static const irq_handler_t tegra20_mc_irq_handlers[] = { 765 + tegra20_mc_handle_irq 766 + }; 767 + 764 768 static const struct tegra_mc_ops tegra20_mc_ops = { 765 769 .probe = tegra20_mc_probe, 766 - .handle_irq = tegra20_mc_handle_irq, 767 770 }; 768 771 769 772 const struct tegra_mc_soc tegra20_mc_soc = { ··· 782 779 .icc_ops = &tegra20_mc_icc_ops, 783 780 .ops = &tegra20_mc_ops, 784 781 .regs = &tegra20_mc_regs, 782 + .handle_irq = tegra20_mc_irq_handlers, 783 + .num_interrupts = ARRAY_SIZE(tegra20_mc_irq_handlers), 785 784 };
+2
drivers/memory/tegra/tegra210.c
··· 1288 1288 .num_resets = ARRAY_SIZE(tegra210_mc_resets), 1289 1289 .ops = &tegra30_mc_ops, 1290 1290 .regs = &tegra20_mc_regs, 1291 + .handle_irq = tegra30_mc_irq_handlers, 1292 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1291 1293 };
+2
drivers/memory/tegra/tegra234.c
··· 1153 1153 */ 1154 1154 .num_carveouts = 32, 1155 1155 .regs = &tegra20_mc_regs, 1156 + .handle_irq = tegra30_mc_irq_handlers, 1157 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1156 1158 };
+2
drivers/memory/tegra/tegra30.c
··· 1401 1401 .icc_ops = &tegra30_mc_icc_ops, 1402 1402 .ops = &tegra30_mc_ops, 1403 1403 .regs = &tegra20_mc_regs, 1404 + .handle_irq = tegra30_mc_irq_handlers, 1405 + .num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers), 1404 1406 };
+5 -3
include/soc/tegra/mc.h
··· 10 10 #include <linux/debugfs.h> 11 11 #include <linux/err.h> 12 12 #include <linux/interconnect-provider.h> 13 + #include <linux/interrupt.h> 13 14 #include <linux/irq.h> 14 15 #include <linux/reset-controller.h> 15 - #include <linux/types.h> 16 16 #include <linux/tegra-icc.h> 17 + #include <linux/types.h> 17 18 18 19 struct clk; 19 20 struct device; ··· 165 164 int (*probe)(struct tegra_mc *mc); 166 165 void (*remove)(struct tegra_mc *mc); 167 166 int (*resume)(struct tegra_mc *mc); 168 - irqreturn_t (*handle_irq)(int irq, void *data); 169 167 int (*probe_device)(struct tegra_mc *mc, struct device *dev); 170 168 }; 171 169 ··· 214 214 const struct tegra_mc_icc_ops *icc_ops; 215 215 const struct tegra_mc_ops *ops; 216 216 const struct tegra_mc_regs *regs; 217 + 218 + const irq_handler_t *handle_irq; 219 + unsigned int num_interrupts; 217 220 }; 218 221 219 222 struct tegra_mc { ··· 227 224 void __iomem *bcast_ch_regs; 228 225 void __iomem **ch_regs; 229 226 struct clk *clk; 230 - int irq; 231 227 232 228 const struct tegra_mc_soc *soc; 233 229 unsigned long tick;