diff options
Diffstat (limited to 'include/soc/tegra/mc.h')
-rw-r--r-- | include/soc/tegra/mc.h | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h new file mode 100644 index 0000000000..a5ef84944a --- /dev/null +++ b/include/soc/tegra/mc.h @@ -0,0 +1,283 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2014 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/irq.h> +#include <linux/reset-controller.h> +#include <linux/types.h> +#include <linux/tegra-icc.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; +struct gart_device; + +#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 + +#ifdef CONFIG_TEGRA_IOMMU_GART +struct gart_device *tegra_gart_probe(struct device *dev, struct tegra_mc *mc); +int tegra_gart_suspend(struct gart_device *gart); +int tegra_gart_resume(struct gart_device *gart); +#else +static inline struct gart_device * +tegra_gart_probe(struct device *dev, struct tegra_mc *mc) +{ + return ERR_PTR(-ENODEV); +} + +static inline int tegra_gart_suspend(struct gart_device *gart) +{ + return -ENODEV; +} + +static inline int tegra_gart_resume(struct gart_device *gart) +{ + return -ENODEV; +} +#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)(struct of_phandle_args *spec, void *data); + struct icc_node_data *(*xlate_extended)(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(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); + int (*suspend)(struct tegra_mc *mc); + int (*resume)(struct tegra_mc *mc); + irqreturn_t (*handle_irq)(int irq, void *data); + int (*probe_device)(struct tegra_mc *mc, struct device *dev); +}; + +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 intmask; + 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; +}; + +struct tegra_mc { + struct tegra_bpmp *bpmp; + struct device *dev; + struct tegra_smmu *smmu; + struct gart_device *gart; + void __iomem *regs; + void __iomem *bcast_ch_regs; + void __iomem **ch_regs; + struct clk *clk; + int irq; + + 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 + +#endif /* __SOC_TEGRA_MC_H__ */ |