|  | /* 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; | 
|  |  | 
|  | #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); | 
|  | 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; | 
|  | 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__ */ |