260 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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__ */
 |