summaryrefslogtreecommitdiffstats
path: root/include/soc/tegra/mc.h
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2026-08-13 18:52:04 +0200
committerDanilo Krummrich <dakr@kernel.org>2026-08-17 01:41:36 +0200
commitf146c7bc85a51f95c05e0f8173d484eb301ece78 (patch)
tree07296ae54ed6551492b0c609dc0f5463f61f89ca /include/soc/tegra/mc.h
downloadlinux-stable-f146c7bc85a51f95c05e0f8173d484eb301ece78.tar.gz
linux-stable-f146c7bc85a51f95c05e0f8173d484eb301ece78.zip
PCI: Add pci_irq_type() to query the allocated interrupt typegrafted
Add a helper that returns PCI_IRQ_MSIX, PCI_IRQ_MSI, or PCI_IRQ_INTX based on the interrupt type the PCI core selected after pci_alloc_irq_vectors(). Several drivers already open-code this check against pdev->msix_enabled and pdev->msi_enabled, or even open code this helper [1]. A common helper avoids the duplication and keeps drivers from accessing the bitfield directly (see also [2]). Acked-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: John Hubbard <jhubbard@nvidia.com> Link: https://elixir.bootlin.com/linux/v7.1/source/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c#L196 [1] Inspired-by: John Hubbard <jhubbard@nvidia.com> Link: https://lore.kernel.org/all/DKKG2QM3YJYB.Z2H2B2UXJ75N@kernel.org/ [2] Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260813165234.620555-5-dakr@kernel.org [ Add missing pci_irq_type() stub for CONFIG_PCI=n. ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'include/soc/tegra/mc.h')
-rw-r--r--include/soc/tegra/mc.h289
1 files changed, 289 insertions, 0 deletions
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
new file mode 100644
index 000000000..25d465d70
--- /dev/null
+++ b/include/soc/tegra/mc.h
@@ -0,0 +1,289 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2014-2026 NVIDIA Corporation
+ */
+
+#ifndef __SOC_TEGRA_MC_H__
+#define __SOC_TEGRA_MC_H__
+
+#include <linux/bits.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/interconnect-provider.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/reset-controller.h>
+#include <linux/tegra-icc.h>
+#include <linux/types.h>
+
+struct clk;
+struct device;
+struct page;
+
+struct tegra_mc_timing {
+ unsigned long rate;
+
+ u32 *emem_data;
+};
+
+struct tegra_mc_client {
+ unsigned int id;
+ unsigned int bpmp_id;
+ enum tegra_icc_client_type type;
+ const char *name;
+ /*
+ * For Tegra210 and earlier, this is the SWGROUP ID used for IOVA translations in the
+ * Tegra SMMU, whereas on Tegra186 and later this is the ID used to override the ARM SMMU
+ * stream ID used for IOVA translations for the given memory client.
+ */
+ union {
+ unsigned int swgroup;
+ unsigned int sid;
+ };
+
+ unsigned int fifo_size;
+
+ struct {
+ /* Tegra SMMU enable (Tegra210 and earlier) */
+ struct {
+ unsigned int reg;
+ unsigned int bit;
+ } smmu;
+
+ /* latency allowance */
+ struct {
+ unsigned int reg;
+ unsigned int shift;
+ unsigned int mask;
+ unsigned int def;
+ } la;
+
+ /* stream ID overrides (Tegra186 and later) */
+ struct {
+ unsigned int override;
+ unsigned int security;
+ } sid;
+ } regs;
+};
+
+struct tegra_smmu_swgroup {
+ const char *name;
+ unsigned int swgroup;
+ unsigned int reg;
+};
+
+struct tegra_smmu_group_soc {
+ const char *name;
+ const unsigned int *swgroups;
+ unsigned int num_swgroups;
+};
+
+struct tegra_smmu_soc {
+ const struct tegra_mc_client *clients;
+ unsigned int num_clients;
+
+ const struct tegra_smmu_swgroup *swgroups;
+ unsigned int num_swgroups;
+
+ const struct tegra_smmu_group_soc *groups;
+ unsigned int num_groups;
+
+ bool supports_round_robin_arbitration;
+ bool supports_request_limit;
+
+ unsigned int num_tlb_lines;
+ unsigned int num_asids;
+};
+
+struct tegra_mc;
+struct tegra_smmu;
+
+#ifdef CONFIG_TEGRA_IOMMU_SMMU
+struct tegra_smmu *tegra_smmu_probe(struct device *dev,
+ const struct tegra_smmu_soc *soc,
+ struct tegra_mc *mc);
+void tegra_smmu_remove(struct tegra_smmu *smmu);
+#else
+static inline struct tegra_smmu *
+tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc,
+ struct tegra_mc *mc)
+{
+ return NULL;
+}
+
+static inline void tegra_smmu_remove(struct tegra_smmu *smmu)
+{
+}
+#endif
+
+struct tegra_mc_reset {
+ const char *name;
+ unsigned long id;
+ unsigned int control;
+ unsigned int status;
+ unsigned int reset;
+ unsigned int bit;
+};
+
+struct tegra_mc_reset_ops {
+ int (*hotreset_assert)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*hotreset_deassert)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*block_dma)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ bool (*dma_idling)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*unblock_dma)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*reset_status)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+};
+
+#define TEGRA_MC_ICC_TAG_DEFAULT 0
+#define TEGRA_MC_ICC_TAG_ISO BIT(0)
+
+struct tegra_mc_icc_ops {
+ int (*set)(struct icc_node *src, struct icc_node *dst);
+ int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
+ u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
+ struct icc_node* (*xlate)(const struct of_phandle_args *spec, void *data);
+ struct icc_node_data *(*xlate_extended)(const struct of_phandle_args *spec,
+ void *data);
+ int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
+};
+
+struct icc_node *tegra_mc_icc_xlate(const struct of_phandle_args *spec,
+ void *data);
+extern const struct tegra_mc_icc_ops tegra_mc_icc_ops;
+
+struct tegra_mc_ops {
+ /*
+ * @probe: Callback to set up SoC-specific bits of the memory controller. This is called
+ * after basic, common set up that is done by the SoC-agnostic bits.
+ */
+ int (*probe)(struct tegra_mc *mc);
+ void (*remove)(struct tegra_mc *mc);
+ void (*resume)(struct tegra_mc *mc);
+ 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_intmask {
+ u32 reg;
+ u32 mask;
+};
+
+struct tegra_mc_soc {
+ const struct tegra_mc_client *clients;
+ unsigned int num_clients;
+
+ const unsigned long *emem_regs;
+ unsigned int num_emem_regs;
+
+ unsigned int num_address_bits;
+ unsigned int atom_size;
+
+ unsigned int num_carveouts;
+
+ u16 client_id_mask;
+ u8 num_channels;
+
+ const struct tegra_smmu_soc *smmu;
+
+ u32 ch_intmask;
+ u32 global_intstatus_channel_shift;
+ bool has_addr_hi_reg;
+
+ const struct tegra_mc_reset_ops *reset_ops;
+ const struct tegra_mc_reset *resets;
+ unsigned int num_resets;
+
+ 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;
+ 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 {
+ struct tegra_bpmp *bpmp;
+ struct device *dev;
+ struct tegra_smmu *smmu;
+ void __iomem *regs;
+ void __iomem *bcast_ch_regs;
+ void __iomem **ch_regs;
+ struct clk *clk;
+
+ const struct tegra_mc_soc *soc;
+ unsigned long tick;
+
+ struct tegra_mc_timing *timings;
+ unsigned int num_timings;
+ unsigned int num_channels;
+
+ bool bwmgr_mrq_supported;
+ struct reset_controller_dev reset;
+
+ struct icc_provider provider;
+
+ spinlock_t lock;
+
+ struct {
+ struct dentry *root;
+ } debugfs;
+};
+
+int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
+unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
+
+#ifdef CONFIG_TEGRA_MC
+struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev);
+int tegra_mc_probe_device(struct tegra_mc *mc, struct device *dev);
+int tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id,
+ phys_addr_t *base, u64 *size);
+#else
+static inline struct tegra_mc *
+devm_tegra_memory_controller_get(struct device *dev)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline int
+tegra_mc_probe_device(struct tegra_mc *mc, struct device *dev)
+{
+ return -ENODEV;
+}
+
+static inline int
+tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id,
+ phys_addr_t *base, u64 *size)
+{
+ return -ENODEV;
+}
+#endif
+
+extern const struct tegra_mc_regs tegra20_mc_regs;
+
+#endif /* __SOC_TEGRA_MC_H__ */