Loading Documentation/devicetree/bindings/arm/tegra.yaml +5 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,11 @@ properties: - const: nvidia,p3737-0000+p3701-0000 - const: nvidia,p3701-0000 - const: nvidia,tegra234 - description: NVIDIA IGX Orin Development Kit items: - const: nvidia,p3740-0002+p3701-0008 - const: nvidia,p3701-0008 - const: nvidia,tegra234 - description: Jetson Orin NX items: - const: nvidia,p3767-0000 Loading drivers/memory/tegra/mc.c +24 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/sort.h> #include <linux/tegra-icc.h> #include <soc/tegra/fuse.h> Loading Loading @@ -792,6 +793,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) mc->provider.data = &mc->provider; mc->provider.set = mc->soc->icc_ops->set; mc->provider.aggregate = mc->soc->icc_ops->aggregate; mc->provider.get_bw = mc->soc->icc_ops->get_bw; mc->provider.xlate = mc->soc->icc_ops->xlate; mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended; icc_provider_init(&mc->provider); Loading Loading @@ -824,6 +827,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) err = icc_link_create(node, TEGRA_ICC_MC); if (err) goto remove_nodes; node->data = (struct tegra_mc_client *)&(mc->soc->clients[i]); } err = icc_provider_register(&mc->provider); Loading @@ -838,6 +843,23 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) return err; } 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); if (value <= 0) { mc->num_channels = mc->soc->num_channels; return; } for (i = 0; i < 32; i++) { if (value & BIT(i)) mc->num_channels++; } } static int tegra_mc_probe(struct platform_device *pdev) { struct tegra_mc *mc; Loading Loading @@ -876,6 +898,8 @@ static int tegra_mc_probe(struct platform_device *pdev) return err; } 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) Loading drivers/memory/tegra/mc.h +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ #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 Loading drivers/memory/tegra/tegra186-emc.c +133 −0 Original line number Diff line number Diff line Loading @@ -7,9 +7,11 @@ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <soc/tegra/bpmp.h> #include "mc.h" struct tegra186_emc_dvfs { unsigned long latency; Loading @@ -29,8 +31,15 @@ struct tegra186_emc { unsigned long min_rate; unsigned long max_rate; } debugfs; struct icc_provider provider; }; static inline struct tegra186_emc *to_tegra186_emc(struct icc_provider *provider) { return container_of(provider, struct tegra186_emc, provider); } /* * debugfs interface * Loading Loading @@ -146,8 +155,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, tegra186_emc_debug_max_rate_get, tegra186_emc_debug_max_rate_set, "%llu\n"); /* * tegra_emc_icc_set_bw() - Set BW api for EMC provider * @src: ICC node for External Memory Controller (EMC) * @dst: ICC node for External Memory (DRAM) * * Do nothing here as info to BPMP-FW is now passed in the BW set function * of the MC driver. BPMP-FW sets the final Freq based on the passed values. */ static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst) { return 0; } static struct icc_node * tegra_emc_of_icc_xlate(struct of_phandle_args *spec, void *data) { struct icc_provider *provider = data; struct icc_node *node; /* External Memory is the only possible ICC route */ list_for_each_entry(node, &provider->nodes, node_list) { if (node->id != TEGRA_ICC_EMEM) continue; return node; } return ERR_PTR(-EPROBE_DEFER); } static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) { *avg = 0; *peak = 0; return 0; } static int tegra_emc_interconnect_init(struct tegra186_emc *emc) { struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent); const struct tegra_mc_soc *soc = mc->soc; struct icc_node *node; int err; emc->provider.dev = emc->dev; emc->provider.set = tegra_emc_icc_set_bw; emc->provider.data = &emc->provider; emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.xlate = tegra_emc_of_icc_xlate; emc->provider.get_bw = tegra_emc_icc_get_init_bw; icc_provider_init(&emc->provider); /* create External Memory Controller node */ node = icc_node_create(TEGRA_ICC_EMC); if (IS_ERR(node)) { err = PTR_ERR(node); goto err_msg; } node->name = "External Memory Controller"; icc_node_add(node, &emc->provider); /* link External Memory Controller to External Memory (DRAM) */ err = icc_link_create(node, TEGRA_ICC_EMEM); if (err) goto remove_nodes; /* create External Memory node */ node = icc_node_create(TEGRA_ICC_EMEM); if (IS_ERR(node)) { err = PTR_ERR(node); goto remove_nodes; } node->name = "External Memory (DRAM)"; icc_node_add(node, &emc->provider); err = icc_provider_register(&emc->provider); if (err) goto remove_nodes; return 0; remove_nodes: icc_nodes_remove(&emc->provider); err_msg: dev_err(emc->dev, "failed to initialize ICC: %d\n", err); return err; } static int tegra186_emc_probe(struct platform_device *pdev) { struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct mrq_emc_dvfs_latency_response response; struct tegra_bpmp_message msg; struct tegra186_emc *emc; Loading Loading @@ -236,6 +339,32 @@ static int tegra186_emc_probe(struct platform_device *pdev) debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root, emc, &tegra186_emc_debug_max_rate_fops); if (mc && mc->soc->icc_ops) { if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) { mc->bwmgr_mrq_supported = true; /* * MC driver probe can't get BPMP reference as it gets probed * earlier than BPMP. So, save the BPMP ref got from the EMC * DT node in the mc->bpmp and use it in MC's icc_set hook. */ mc->bpmp = emc->bpmp; barrier(); } /* * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'. * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return * EINVAL instead of passing the request to BPMP-FW later when the BW * request is made by client with 'icc_set_bw()' call. */ err = tegra_emc_interconnect_init(emc); if (err) { mc->bpmp = NULL; goto put_bpmp; } } return 0; put_bpmp: Loading @@ -245,9 +374,12 @@ static int tegra186_emc_probe(struct platform_device *pdev) static int tegra186_emc_remove(struct platform_device *pdev) { struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct tegra186_emc *emc = platform_get_drvdata(pdev); debugfs_remove_recursive(emc->debugfs.root); mc->bpmp = NULL; tegra_bpmp_put(emc->bpmp); return 0; Loading @@ -272,6 +404,7 @@ static struct platform_driver tegra186_emc_driver = { .name = "tegra186-emc", .of_match_table = tegra186_emc_of_match, .suppress_bind_attrs = true, .sync_state = icc_sync_state, }, .probe = tegra186_emc_probe, .remove = tegra186_emc_remove, Loading drivers/memory/tegra/tegra234.c +594 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved. * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved. */ #include <soc/tegra/mc.h> #include <dt-bindings/memory/tegra234-mc.h> #include <linux/interconnect.h> #include <linux/tegra-icc.h> #include <soc/tegra/bpmp.h> #include "mc.h" static const struct tegra_mc_client tegra234_mc_clients[] = { { .id = TEGRA234_MEMORY_CLIENT_HDAR, .name = "hdar", .bpmp_id = TEGRA_ICC_BPMP_HDA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_HDA, .regs = { .sid = { .override = 0xa8, .security = 0xac, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_HDAW, .name = "hdaw", .bpmp_id = TEGRA_ICC_BPMP_HDA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_HDA, .regs = { .sid = { .override = 0x1a8, .security = 0x1ac, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_MGBEARD, .name = "mgbeard", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE, .regs = { .sid = { Loading @@ -23,6 +52,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBRD, .name = "mgbebrd", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { Loading @@ -33,6 +64,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECRD, .name = "mgbecrd", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { Loading @@ -43,6 +76,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDRD, .name = "mgbedrd", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { Loading @@ -52,6 +87,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, }, { .id = TEGRA234_MEMORY_CLIENT_MGBEAWR, .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .name = "mgbeawr", .sid = TEGRA234_SID_MGBE, .regs = { Loading @@ -63,6 +100,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBWR, .name = "mgbebwr", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { Loading @@ -73,6 +112,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECWR, .name = "mgbecwr", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { Loading @@ -83,6 +124,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB, .name = "sdmmcrab", .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { Loading @@ -93,6 +136,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDWR, .name = "mgbedwr", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { Loading @@ -103,6 +148,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB, .name = "sdmmcwab", .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { Loading @@ -110,6 +157,90 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { .security = 0x33c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_VI2W, .name = "vi2w", .bpmp_id = TEGRA_ICC_BPMP_VI2, .type = TEGRA_ICC_ISO_VI, .sid = TEGRA234_SID_ISO_VI2, .regs = { .sid = { .override = 0x380, .security = 0x384, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_VI2FALR, .name = "vi2falr", .bpmp_id = TEGRA_ICC_BPMP_VI2FAL, .type = TEGRA_ICC_ISO_VIFAL, .sid = TEGRA234_SID_ISO_VI2FALC, .regs = { .sid = { .override = 0x388, .security = 0x38c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_VI2FALW, .name = "vi2falw", .bpmp_id = TEGRA_ICC_BPMP_VI2FAL, .type = TEGRA_ICC_ISO_VIFAL, .sid = TEGRA234_SID_ISO_VI2FALC, .regs = { .sid = { .override = 0x3e0, .security = 0x3e4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_APER, .name = "aper", .bpmp_id = TEGRA_ICC_BPMP_APE, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { .override = 0x3d0, .security = 0x3d4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_APEW, .name = "apew", .bpmp_id = TEGRA_ICC_BPMP_APE, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { .override = 0x3d8, .security = 0x3dc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR, .name = "nvdisplayr", .bpmp_id = TEGRA_ICC_BPMP_DISPLAY, .type = TEGRA_ICC_ISO_DISPLAY, .sid = TEGRA234_SID_ISO_NVDISPLAY, .regs = { .sid = { .override = 0x490, .security = 0x494, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR1, .name = "nvdisplayr1", .bpmp_id = TEGRA_ICC_BPMP_DISPLAY, .type = TEGRA_ICC_ISO_DISPLAY, .sid = TEGRA234_SID_ISO_NVDISPLAY, .regs = { .sid = { .override = 0x508, .security = 0x50c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_BPMPR, .name = "bpmpr", Loading Loading @@ -153,6 +284,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAR, .name = "apedmar", .bpmp_id = TEGRA_ICC_BPMP_APEDMA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { Loading @@ -163,6 +296,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAW, .name = "apedmaw", .bpmp_id = TEGRA_ICC_BPMP_APEDMA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { Loading Loading @@ -330,7 +465,464 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { .security = 0x37c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE0R, .name = "pcie0r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_0, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE0, .regs = { .sid = { .override = 0x6c0, .security = 0x6c4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE0W, .name = "pcie0w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_0, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE0, .regs = { .sid = { .override = 0x6c8, .security = 0x6cc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE1R, .name = "pcie1r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_1, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE1, .regs = { .sid = { .override = 0x6d0, .security = 0x6d4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE1W, .name = "pcie1w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_1, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE1, .regs = { .sid = { .override = 0x6d8, .security = 0x6dc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE2AR, .name = "pcie2ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_2, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE2, .regs = { .sid = { .override = 0x6e0, .security = 0x6e4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE2AW, .name = "pcie2aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_2, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE2, .regs = { .sid = { .override = 0x6e8, .security = 0x6ec, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE3R, .name = "pcie3r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_3, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE3, .regs = { .sid = { .override = 0x6f0, .security = 0x6f4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE3W, .name = "pcie3w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_3, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE3, .regs = { .sid = { .override = 0x6f8, .security = 0x6fc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE4R, .name = "pcie4r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE4, .regs = { .sid = { .override = 0x700, .security = 0x704, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE4W, .name = "pcie4w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE4, .regs = { .sid = { .override = 0x708, .security = 0x70c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE5R, .name = "pcie5r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE5, .regs = { .sid = { .override = 0x710, .security = 0x714, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE5W, .name = "pcie5w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE5, .regs = { .sid = { .override = 0x718, .security = 0x71c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE5R1, .name = "pcie5r1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE5, .regs = { .sid = { .override = 0x778, .security = 0x77c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE6AR, .name = "pcie6ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE6, .regs = { .sid = { .override = 0x140, .security = 0x144, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE6AW, .name = "pcie6aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE6, .regs = { .sid = { .override = 0x148, .security = 0x14c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE6AR1, .name = "pcie6ar1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE6, .regs = { .sid = { .override = 0x1e8, .security = 0x1ec, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE7AR, .name = "pcie7ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE7, .regs = { .sid = { .override = 0x150, .security = 0x154, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE7AW, .name = "pcie7aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE7, .regs = { .sid = { .override = 0x180, .security = 0x184, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE7AR1, .name = "pcie7ar1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE7, .regs = { .sid = { .override = 0x248, .security = 0x24c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE8AR, .name = "pcie8ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_8, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE8, .regs = { .sid = { .override = 0x190, .security = 0x194, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE8AW, .name = "pcie8aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_8, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE8, .regs = { .sid = { .override = 0x1d8, .security = 0x1dc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE9AR, .name = "pcie9ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_9, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE9, .regs = { .sid = { .override = 0x1e0, .security = 0x1e4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE9AW, .name = "pcie9aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_9, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE9, .regs = { .sid = { .override = 0x1f0, .security = 0x1f4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE10AR, .name = "pcie10ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE10, .regs = { .sid = { .override = 0x1f8, .security = 0x1fc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE10AW, .name = "pcie10aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE10, .regs = { .sid = { .override = 0x200, .security = 0x204, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE10AR1, .name = "pcie10ar1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE10, .regs = { .sid = { .override = 0x240, .security = 0x244, }, }, }, { .id = TEGRA_ICC_MC_CPU_CLUSTER0, .name = "sw_cluster0", .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER0, .type = TEGRA_ICC_NISO, }, { .id = TEGRA_ICC_MC_CPU_CLUSTER1, .name = "sw_cluster1", .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER1, .type = TEGRA_ICC_NISO, }, { .id = TEGRA_ICC_MC_CPU_CLUSTER2, .name = "sw_cluster2", .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER2, .type = TEGRA_ICC_NISO, }, }; /* * tegra234_mc_icc_set() - Pass MC client info to the BPMP-FW * @src: ICC node for Memory Controller's (MC) Client * @dst: ICC node for Memory Controller (MC) * * Passing the current request info from the MC to the BPMP-FW where * LA and PTSA registers are accessed and the final EMC freq is set * based on client_id, type, latency and bandwidth. * icc_set_bw() makes set_bw calls for both MC and EMC providers in * sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'. * So, the data passed won't be updated by concurrent set calls from * other clients. */ static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst) { struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider); struct mrq_bwmgr_int_request bwmgr_req = { 0 }; struct mrq_bwmgr_int_response bwmgr_resp = { 0 }; const struct tegra_mc_client *pclient = src->data; struct tegra_bpmp_message msg; int ret; /* * Same Src and Dst node will happen during boot from icc_node_add(). * This can be used to pre-initialize and set bandwidth for all clients * before their drivers are loaded. We are skipping this case as for us, * the pre-initialization already happened in Bootloader(MB2) and BPMP-FW. */ if (src->id == dst->id) return 0; if (!mc->bwmgr_mrq_supported) return -EINVAL; if (!mc->bpmp) { dev_err(mc->dev, "BPMP reference NULL\n"); return -ENOENT; } if (pclient->type == TEGRA_ICC_NISO) bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw; else bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw; bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id; bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET; bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw; bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS; memset(&msg, 0, sizeof(msg)); msg.mrq = MRQ_BWMGR_INT; msg.tx.data = &bwmgr_req; msg.tx.size = sizeof(bwmgr_req); msg.rx.data = &bwmgr_resp; msg.rx.size = sizeof(bwmgr_resp); ret = tegra_bpmp_transfer(mc->bpmp, &msg); if (ret < 0) { dev_err(mc->dev, "BPMP transfer failed: %d\n", ret); goto error; } if (msg.rx.ret < 0) { pr_err("failed to set bandwidth for %u: %d\n", bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret); ret = -EINVAL; } error: return ret; } static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, u32 peak_bw, u32 *agg_avg, u32 *agg_peak) { struct icc_provider *p = node->provider; struct tegra_mc *mc = icc_provider_to_tegra_mc(p); if (!mc->bwmgr_mrq_supported) return -EINVAL; if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || node->id == TEGRA_ICC_MC_CPU_CLUSTER1 || node->id == TEGRA_ICC_MC_CPU_CLUSTER2) { if (mc) peak_bw = peak_bw * mc->num_channels; } *agg_avg += avg_bw; *agg_peak = max(*agg_peak, peak_bw); return 0; } static struct icc_node* tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data) { struct tegra_mc *mc = icc_provider_to_tegra_mc(data); unsigned int cl_id = spec->args[0]; struct icc_node *node; list_for_each_entry(node, &mc->provider.nodes, node_list) { if (node->id != cl_id) continue; return node; } /* * If a client driver calls devm_of_icc_get() before the MC driver * is probed, then return EPROBE_DEFER to the client driver. */ return ERR_PTR(-EPROBE_DEFER); } static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) { *avg = 0; *peak = 0; return 0; } static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { .xlate = tegra234_mc_of_icc_xlate, .aggregate = tegra234_mc_icc_aggregate, .get_bw = tegra234_mc_icc_get_init_bw, .set = tegra234_mc_icc_set, }; const struct tegra_mc_soc tegra234_mc_soc = { Loading @@ -345,6 +937,7 @@ const struct tegra_mc_soc tegra234_mc_soc = { MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra234_mc_icc_ops, .ch_intmask = 0x0000ff00, .global_intstatus_channel_shift = 8, /* Loading Loading
Documentation/devicetree/bindings/arm/tegra.yaml +5 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,11 @@ properties: - const: nvidia,p3737-0000+p3701-0000 - const: nvidia,p3701-0000 - const: nvidia,tegra234 - description: NVIDIA IGX Orin Development Kit items: - const: nvidia,p3740-0002+p3701-0008 - const: nvidia,p3701-0008 - const: nvidia,tegra234 - description: Jetson Orin NX items: - const: nvidia,p3767-0000 Loading
drivers/memory/tegra/mc.c +24 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/sort.h> #include <linux/tegra-icc.h> #include <soc/tegra/fuse.h> Loading Loading @@ -792,6 +793,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) mc->provider.data = &mc->provider; mc->provider.set = mc->soc->icc_ops->set; mc->provider.aggregate = mc->soc->icc_ops->aggregate; mc->provider.get_bw = mc->soc->icc_ops->get_bw; mc->provider.xlate = mc->soc->icc_ops->xlate; mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended; icc_provider_init(&mc->provider); Loading Loading @@ -824,6 +827,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) err = icc_link_create(node, TEGRA_ICC_MC); if (err) goto remove_nodes; node->data = (struct tegra_mc_client *)&(mc->soc->clients[i]); } err = icc_provider_register(&mc->provider); Loading @@ -838,6 +843,23 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) return err; } 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); if (value <= 0) { mc->num_channels = mc->soc->num_channels; return; } for (i = 0; i < 32; i++) { if (value & BIT(i)) mc->num_channels++; } } static int tegra_mc_probe(struct platform_device *pdev) { struct tegra_mc *mc; Loading Loading @@ -876,6 +898,8 @@ static int tegra_mc_probe(struct platform_device *pdev) return err; } 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) Loading
drivers/memory/tegra/mc.h +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ #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 Loading
drivers/memory/tegra/tegra186-emc.c +133 −0 Original line number Diff line number Diff line Loading @@ -7,9 +7,11 @@ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <soc/tegra/bpmp.h> #include "mc.h" struct tegra186_emc_dvfs { unsigned long latency; Loading @@ -29,8 +31,15 @@ struct tegra186_emc { unsigned long min_rate; unsigned long max_rate; } debugfs; struct icc_provider provider; }; static inline struct tegra186_emc *to_tegra186_emc(struct icc_provider *provider) { return container_of(provider, struct tegra186_emc, provider); } /* * debugfs interface * Loading Loading @@ -146,8 +155,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, tegra186_emc_debug_max_rate_get, tegra186_emc_debug_max_rate_set, "%llu\n"); /* * tegra_emc_icc_set_bw() - Set BW api for EMC provider * @src: ICC node for External Memory Controller (EMC) * @dst: ICC node for External Memory (DRAM) * * Do nothing here as info to BPMP-FW is now passed in the BW set function * of the MC driver. BPMP-FW sets the final Freq based on the passed values. */ static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst) { return 0; } static struct icc_node * tegra_emc_of_icc_xlate(struct of_phandle_args *spec, void *data) { struct icc_provider *provider = data; struct icc_node *node; /* External Memory is the only possible ICC route */ list_for_each_entry(node, &provider->nodes, node_list) { if (node->id != TEGRA_ICC_EMEM) continue; return node; } return ERR_PTR(-EPROBE_DEFER); } static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) { *avg = 0; *peak = 0; return 0; } static int tegra_emc_interconnect_init(struct tegra186_emc *emc) { struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent); const struct tegra_mc_soc *soc = mc->soc; struct icc_node *node; int err; emc->provider.dev = emc->dev; emc->provider.set = tegra_emc_icc_set_bw; emc->provider.data = &emc->provider; emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.xlate = tegra_emc_of_icc_xlate; emc->provider.get_bw = tegra_emc_icc_get_init_bw; icc_provider_init(&emc->provider); /* create External Memory Controller node */ node = icc_node_create(TEGRA_ICC_EMC); if (IS_ERR(node)) { err = PTR_ERR(node); goto err_msg; } node->name = "External Memory Controller"; icc_node_add(node, &emc->provider); /* link External Memory Controller to External Memory (DRAM) */ err = icc_link_create(node, TEGRA_ICC_EMEM); if (err) goto remove_nodes; /* create External Memory node */ node = icc_node_create(TEGRA_ICC_EMEM); if (IS_ERR(node)) { err = PTR_ERR(node); goto remove_nodes; } node->name = "External Memory (DRAM)"; icc_node_add(node, &emc->provider); err = icc_provider_register(&emc->provider); if (err) goto remove_nodes; return 0; remove_nodes: icc_nodes_remove(&emc->provider); err_msg: dev_err(emc->dev, "failed to initialize ICC: %d\n", err); return err; } static int tegra186_emc_probe(struct platform_device *pdev) { struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct mrq_emc_dvfs_latency_response response; struct tegra_bpmp_message msg; struct tegra186_emc *emc; Loading Loading @@ -236,6 +339,32 @@ static int tegra186_emc_probe(struct platform_device *pdev) debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root, emc, &tegra186_emc_debug_max_rate_fops); if (mc && mc->soc->icc_ops) { if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) { mc->bwmgr_mrq_supported = true; /* * MC driver probe can't get BPMP reference as it gets probed * earlier than BPMP. So, save the BPMP ref got from the EMC * DT node in the mc->bpmp and use it in MC's icc_set hook. */ mc->bpmp = emc->bpmp; barrier(); } /* * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'. * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return * EINVAL instead of passing the request to BPMP-FW later when the BW * request is made by client with 'icc_set_bw()' call. */ err = tegra_emc_interconnect_init(emc); if (err) { mc->bpmp = NULL; goto put_bpmp; } } return 0; put_bpmp: Loading @@ -245,9 +374,12 @@ static int tegra186_emc_probe(struct platform_device *pdev) static int tegra186_emc_remove(struct platform_device *pdev) { struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct tegra186_emc *emc = platform_get_drvdata(pdev); debugfs_remove_recursive(emc->debugfs.root); mc->bpmp = NULL; tegra_bpmp_put(emc->bpmp); return 0; Loading @@ -272,6 +404,7 @@ static struct platform_driver tegra186_emc_driver = { .name = "tegra186-emc", .of_match_table = tegra186_emc_of_match, .suppress_bind_attrs = true, .sync_state = icc_sync_state, }, .probe = tegra186_emc_probe, .remove = tegra186_emc_remove, Loading
drivers/memory/tegra/tegra234.c +594 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved. * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved. */ #include <soc/tegra/mc.h> #include <dt-bindings/memory/tegra234-mc.h> #include <linux/interconnect.h> #include <linux/tegra-icc.h> #include <soc/tegra/bpmp.h> #include "mc.h" static const struct tegra_mc_client tegra234_mc_clients[] = { { .id = TEGRA234_MEMORY_CLIENT_HDAR, .name = "hdar", .bpmp_id = TEGRA_ICC_BPMP_HDA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_HDA, .regs = { .sid = { .override = 0xa8, .security = 0xac, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_HDAW, .name = "hdaw", .bpmp_id = TEGRA_ICC_BPMP_HDA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_HDA, .regs = { .sid = { .override = 0x1a8, .security = 0x1ac, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_MGBEARD, .name = "mgbeard", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE, .regs = { .sid = { Loading @@ -23,6 +52,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBRD, .name = "mgbebrd", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { Loading @@ -33,6 +64,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECRD, .name = "mgbecrd", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { Loading @@ -43,6 +76,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDRD, .name = "mgbedrd", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { Loading @@ -52,6 +87,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, }, { .id = TEGRA234_MEMORY_CLIENT_MGBEAWR, .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .name = "mgbeawr", .sid = TEGRA234_SID_MGBE, .regs = { Loading @@ -63,6 +100,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBWR, .name = "mgbebwr", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { Loading @@ -73,6 +112,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECWR, .name = "mgbecwr", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { Loading @@ -83,6 +124,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB, .name = "sdmmcrab", .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { Loading @@ -93,6 +136,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDWR, .name = "mgbedwr", .bpmp_id = TEGRA_ICC_BPMP_EQOS, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { Loading @@ -103,6 +148,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB, .name = "sdmmcwab", .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { Loading @@ -110,6 +157,90 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { .security = 0x33c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_VI2W, .name = "vi2w", .bpmp_id = TEGRA_ICC_BPMP_VI2, .type = TEGRA_ICC_ISO_VI, .sid = TEGRA234_SID_ISO_VI2, .regs = { .sid = { .override = 0x380, .security = 0x384, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_VI2FALR, .name = "vi2falr", .bpmp_id = TEGRA_ICC_BPMP_VI2FAL, .type = TEGRA_ICC_ISO_VIFAL, .sid = TEGRA234_SID_ISO_VI2FALC, .regs = { .sid = { .override = 0x388, .security = 0x38c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_VI2FALW, .name = "vi2falw", .bpmp_id = TEGRA_ICC_BPMP_VI2FAL, .type = TEGRA_ICC_ISO_VIFAL, .sid = TEGRA234_SID_ISO_VI2FALC, .regs = { .sid = { .override = 0x3e0, .security = 0x3e4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_APER, .name = "aper", .bpmp_id = TEGRA_ICC_BPMP_APE, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { .override = 0x3d0, .security = 0x3d4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_APEW, .name = "apew", .bpmp_id = TEGRA_ICC_BPMP_APE, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { .override = 0x3d8, .security = 0x3dc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR, .name = "nvdisplayr", .bpmp_id = TEGRA_ICC_BPMP_DISPLAY, .type = TEGRA_ICC_ISO_DISPLAY, .sid = TEGRA234_SID_ISO_NVDISPLAY, .regs = { .sid = { .override = 0x490, .security = 0x494, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR1, .name = "nvdisplayr1", .bpmp_id = TEGRA_ICC_BPMP_DISPLAY, .type = TEGRA_ICC_ISO_DISPLAY, .sid = TEGRA234_SID_ISO_NVDISPLAY, .regs = { .sid = { .override = 0x508, .security = 0x50c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_BPMPR, .name = "bpmpr", Loading Loading @@ -153,6 +284,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAR, .name = "apedmar", .bpmp_id = TEGRA_ICC_BPMP_APEDMA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { Loading @@ -163,6 +296,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAW, .name = "apedmaw", .bpmp_id = TEGRA_ICC_BPMP_APEDMA, .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { Loading Loading @@ -330,7 +465,464 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { .security = 0x37c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE0R, .name = "pcie0r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_0, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE0, .regs = { .sid = { .override = 0x6c0, .security = 0x6c4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE0W, .name = "pcie0w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_0, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE0, .regs = { .sid = { .override = 0x6c8, .security = 0x6cc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE1R, .name = "pcie1r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_1, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE1, .regs = { .sid = { .override = 0x6d0, .security = 0x6d4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE1W, .name = "pcie1w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_1, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE1, .regs = { .sid = { .override = 0x6d8, .security = 0x6dc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE2AR, .name = "pcie2ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_2, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE2, .regs = { .sid = { .override = 0x6e0, .security = 0x6e4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE2AW, .name = "pcie2aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_2, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE2, .regs = { .sid = { .override = 0x6e8, .security = 0x6ec, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE3R, .name = "pcie3r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_3, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE3, .regs = { .sid = { .override = 0x6f0, .security = 0x6f4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE3W, .name = "pcie3w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_3, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE3, .regs = { .sid = { .override = 0x6f8, .security = 0x6fc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE4R, .name = "pcie4r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE4, .regs = { .sid = { .override = 0x700, .security = 0x704, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE4W, .name = "pcie4w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_4, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE4, .regs = { .sid = { .override = 0x708, .security = 0x70c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE5R, .name = "pcie5r", .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE5, .regs = { .sid = { .override = 0x710, .security = 0x714, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE5W, .name = "pcie5w", .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE5, .regs = { .sid = { .override = 0x718, .security = 0x71c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE5R1, .name = "pcie5r1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE5, .regs = { .sid = { .override = 0x778, .security = 0x77c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE6AR, .name = "pcie6ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE6, .regs = { .sid = { .override = 0x140, .security = 0x144, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE6AW, .name = "pcie6aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE6, .regs = { .sid = { .override = 0x148, .security = 0x14c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE6AR1, .name = "pcie6ar1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE6, .regs = { .sid = { .override = 0x1e8, .security = 0x1ec, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE7AR, .name = "pcie7ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE7, .regs = { .sid = { .override = 0x150, .security = 0x154, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE7AW, .name = "pcie7aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE7, .regs = { .sid = { .override = 0x180, .security = 0x184, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE7AR1, .name = "pcie7ar1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE7, .regs = { .sid = { .override = 0x248, .security = 0x24c, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE8AR, .name = "pcie8ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_8, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE8, .regs = { .sid = { .override = 0x190, .security = 0x194, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE8AW, .name = "pcie8aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_8, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE8, .regs = { .sid = { .override = 0x1d8, .security = 0x1dc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE9AR, .name = "pcie9ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_9, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE9, .regs = { .sid = { .override = 0x1e0, .security = 0x1e4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE9AW, .name = "pcie9aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_9, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE9, .regs = { .sid = { .override = 0x1f0, .security = 0x1f4, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE10AR, .name = "pcie10ar", .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE10, .regs = { .sid = { .override = 0x1f8, .security = 0x1fc, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE10AW, .name = "pcie10aw", .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE10, .regs = { .sid = { .override = 0x200, .security = 0x204, }, }, }, { .id = TEGRA234_MEMORY_CLIENT_PCIE10AR1, .name = "pcie10ar1", .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_PCIE10, .regs = { .sid = { .override = 0x240, .security = 0x244, }, }, }, { .id = TEGRA_ICC_MC_CPU_CLUSTER0, .name = "sw_cluster0", .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER0, .type = TEGRA_ICC_NISO, }, { .id = TEGRA_ICC_MC_CPU_CLUSTER1, .name = "sw_cluster1", .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER1, .type = TEGRA_ICC_NISO, }, { .id = TEGRA_ICC_MC_CPU_CLUSTER2, .name = "sw_cluster2", .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER2, .type = TEGRA_ICC_NISO, }, }; /* * tegra234_mc_icc_set() - Pass MC client info to the BPMP-FW * @src: ICC node for Memory Controller's (MC) Client * @dst: ICC node for Memory Controller (MC) * * Passing the current request info from the MC to the BPMP-FW where * LA and PTSA registers are accessed and the final EMC freq is set * based on client_id, type, latency and bandwidth. * icc_set_bw() makes set_bw calls for both MC and EMC providers in * sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'. * So, the data passed won't be updated by concurrent set calls from * other clients. */ static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst) { struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider); struct mrq_bwmgr_int_request bwmgr_req = { 0 }; struct mrq_bwmgr_int_response bwmgr_resp = { 0 }; const struct tegra_mc_client *pclient = src->data; struct tegra_bpmp_message msg; int ret; /* * Same Src and Dst node will happen during boot from icc_node_add(). * This can be used to pre-initialize and set bandwidth for all clients * before their drivers are loaded. We are skipping this case as for us, * the pre-initialization already happened in Bootloader(MB2) and BPMP-FW. */ if (src->id == dst->id) return 0; if (!mc->bwmgr_mrq_supported) return -EINVAL; if (!mc->bpmp) { dev_err(mc->dev, "BPMP reference NULL\n"); return -ENOENT; } if (pclient->type == TEGRA_ICC_NISO) bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw; else bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw; bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id; bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET; bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw; bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS; memset(&msg, 0, sizeof(msg)); msg.mrq = MRQ_BWMGR_INT; msg.tx.data = &bwmgr_req; msg.tx.size = sizeof(bwmgr_req); msg.rx.data = &bwmgr_resp; msg.rx.size = sizeof(bwmgr_resp); ret = tegra_bpmp_transfer(mc->bpmp, &msg); if (ret < 0) { dev_err(mc->dev, "BPMP transfer failed: %d\n", ret); goto error; } if (msg.rx.ret < 0) { pr_err("failed to set bandwidth for %u: %d\n", bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret); ret = -EINVAL; } error: return ret; } static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, u32 peak_bw, u32 *agg_avg, u32 *agg_peak) { struct icc_provider *p = node->provider; struct tegra_mc *mc = icc_provider_to_tegra_mc(p); if (!mc->bwmgr_mrq_supported) return -EINVAL; if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || node->id == TEGRA_ICC_MC_CPU_CLUSTER1 || node->id == TEGRA_ICC_MC_CPU_CLUSTER2) { if (mc) peak_bw = peak_bw * mc->num_channels; } *agg_avg += avg_bw; *agg_peak = max(*agg_peak, peak_bw); return 0; } static struct icc_node* tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data) { struct tegra_mc *mc = icc_provider_to_tegra_mc(data); unsigned int cl_id = spec->args[0]; struct icc_node *node; list_for_each_entry(node, &mc->provider.nodes, node_list) { if (node->id != cl_id) continue; return node; } /* * If a client driver calls devm_of_icc_get() before the MC driver * is probed, then return EPROBE_DEFER to the client driver. */ return ERR_PTR(-EPROBE_DEFER); } static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) { *avg = 0; *peak = 0; return 0; } static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { .xlate = tegra234_mc_of_icc_xlate, .aggregate = tegra234_mc_icc_aggregate, .get_bw = tegra234_mc_icc_get_init_bw, .set = tegra234_mc_icc_set, }; const struct tegra_mc_soc tegra234_mc_soc = { Loading @@ -345,6 +937,7 @@ const struct tegra_mc_soc tegra234_mc_soc = { MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, .icc_ops = &tegra234_mc_icc_ops, .ch_intmask = 0x0000ff00, .global_intstatus_channel_shift = 8, /* Loading