/* 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_SMMUstruct 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);#elsestatic 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_MCstruct 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);#elsestatic inline struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev){ return ERR_PTR(-ENODEV);} static inline inttegra_mc_probe_device(struct tegra_mc *mc, struct device *dev){ return -ENODEV;} static inline inttegra_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__ */
/* 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__ */