18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2015-2018 Etnaviv Project
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef __ETNAVIV_MMU_H__
78c2ecf20Sopenharmony_ci#define __ETNAVIV_MMU_H__
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define ETNAVIV_PROT_READ	(1 << 0)
108c2ecf20Sopenharmony_ci#define ETNAVIV_PROT_WRITE	(1 << 1)
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cienum etnaviv_iommu_version {
138c2ecf20Sopenharmony_ci	ETNAVIV_IOMMU_V1 = 0,
148c2ecf20Sopenharmony_ci	ETNAVIV_IOMMU_V2,
158c2ecf20Sopenharmony_ci};
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct etnaviv_gpu;
188c2ecf20Sopenharmony_cistruct etnaviv_vram_mapping;
198c2ecf20Sopenharmony_cistruct etnaviv_iommu_global;
208c2ecf20Sopenharmony_cistruct etnaviv_iommu_context;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistruct etnaviv_iommu_ops {
238c2ecf20Sopenharmony_ci	struct etnaviv_iommu_context *(*init)(struct etnaviv_iommu_global *);
248c2ecf20Sopenharmony_ci	void (*free)(struct etnaviv_iommu_context *);
258c2ecf20Sopenharmony_ci	int (*map)(struct etnaviv_iommu_context *context, unsigned long iova,
268c2ecf20Sopenharmony_ci		   phys_addr_t paddr, size_t size, int prot);
278c2ecf20Sopenharmony_ci	size_t (*unmap)(struct etnaviv_iommu_context *context, unsigned long iova,
288c2ecf20Sopenharmony_ci			size_t size);
298c2ecf20Sopenharmony_ci	size_t (*dump_size)(struct etnaviv_iommu_context *);
308c2ecf20Sopenharmony_ci	void (*dump)(struct etnaviv_iommu_context *, void *);
318c2ecf20Sopenharmony_ci	void (*restore)(struct etnaviv_gpu *, struct etnaviv_iommu_context *);
328c2ecf20Sopenharmony_ci};
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciextern const struct etnaviv_iommu_ops etnaviv_iommuv1_ops;
358c2ecf20Sopenharmony_ciextern const struct etnaviv_iommu_ops etnaviv_iommuv2_ops;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define ETNAVIV_PTA_SIZE	SZ_4K
388c2ecf20Sopenharmony_ci#define ETNAVIV_PTA_ENTRIES	(ETNAVIV_PTA_SIZE / sizeof(u64))
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistruct etnaviv_iommu_global {
418c2ecf20Sopenharmony_ci	struct device *dev;
428c2ecf20Sopenharmony_ci	enum etnaviv_iommu_version version;
438c2ecf20Sopenharmony_ci	const struct etnaviv_iommu_ops *ops;
448c2ecf20Sopenharmony_ci	unsigned int use;
458c2ecf20Sopenharmony_ci	struct mutex lock;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	void *bad_page_cpu;
488c2ecf20Sopenharmony_ci	dma_addr_t bad_page_dma;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	u32 memory_base;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/*
538c2ecf20Sopenharmony_ci	 * This union holds members needed by either MMUv1 or MMUv2, which
548c2ecf20Sopenharmony_ci	 * can not exist at the same time.
558c2ecf20Sopenharmony_ci	 */
568c2ecf20Sopenharmony_ci	union {
578c2ecf20Sopenharmony_ci		struct {
588c2ecf20Sopenharmony_ci			struct etnaviv_iommu_context *shared_context;
598c2ecf20Sopenharmony_ci		} v1;
608c2ecf20Sopenharmony_ci		struct {
618c2ecf20Sopenharmony_ci			/* P(age) T(able) A(rray) */
628c2ecf20Sopenharmony_ci			u64 *pta_cpu;
638c2ecf20Sopenharmony_ci			dma_addr_t pta_dma;
648c2ecf20Sopenharmony_ci			struct spinlock pta_lock;
658c2ecf20Sopenharmony_ci			DECLARE_BITMAP(pta_alloc, ETNAVIV_PTA_ENTRIES);
668c2ecf20Sopenharmony_ci		} v2;
678c2ecf20Sopenharmony_ci	};
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistruct etnaviv_iommu_context {
718c2ecf20Sopenharmony_ci	struct kref refcount;
728c2ecf20Sopenharmony_ci	struct etnaviv_iommu_global *global;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* memory manager for GPU address area */
758c2ecf20Sopenharmony_ci	struct mutex lock;
768c2ecf20Sopenharmony_ci	struct list_head mappings;
778c2ecf20Sopenharmony_ci	struct drm_mm mm;
788c2ecf20Sopenharmony_ci	unsigned int flush_seq;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/* Not part of the context, but needs to have the same lifetime */
818c2ecf20Sopenharmony_ci	struct etnaviv_vram_mapping cmdbuf_mapping;
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ciint etnaviv_iommu_global_init(struct etnaviv_gpu *gpu);
858c2ecf20Sopenharmony_civoid etnaviv_iommu_global_fini(struct etnaviv_gpu *gpu);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistruct etnaviv_gem_object;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciint etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
908c2ecf20Sopenharmony_ci	struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,
918c2ecf20Sopenharmony_ci	struct etnaviv_vram_mapping *mapping, u64 va);
928c2ecf20Sopenharmony_civoid etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
938c2ecf20Sopenharmony_ci	struct etnaviv_vram_mapping *mapping);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ciint etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu_context *ctx,
968c2ecf20Sopenharmony_ci				  struct etnaviv_vram_mapping *mapping,
978c2ecf20Sopenharmony_ci				  u32 memory_base, dma_addr_t paddr,
988c2ecf20Sopenharmony_ci				  size_t size);
998c2ecf20Sopenharmony_civoid etnaviv_iommu_put_suballoc_va(struct etnaviv_iommu_context *ctx,
1008c2ecf20Sopenharmony_ci				   struct etnaviv_vram_mapping *mapping);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cisize_t etnaviv_iommu_dump_size(struct etnaviv_iommu_context *ctx);
1038c2ecf20Sopenharmony_civoid etnaviv_iommu_dump(struct etnaviv_iommu_context *ctx, void *buf);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistruct etnaviv_iommu_context *
1068c2ecf20Sopenharmony_cietnaviv_iommu_context_init(struct etnaviv_iommu_global *global,
1078c2ecf20Sopenharmony_ci			   struct etnaviv_cmdbuf_suballoc *suballoc);
1088c2ecf20Sopenharmony_cistatic inline struct etnaviv_iommu_context *
1098c2ecf20Sopenharmony_cietnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	kref_get(&ctx->refcount);
1128c2ecf20Sopenharmony_ci	return ctx;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_civoid etnaviv_iommu_context_put(struct etnaviv_iommu_context *ctx);
1158c2ecf20Sopenharmony_civoid etnaviv_iommu_restore(struct etnaviv_gpu *gpu,
1168c2ecf20Sopenharmony_ci			   struct etnaviv_iommu_context *ctx);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistruct etnaviv_iommu_context *
1198c2ecf20Sopenharmony_cietnaviv_iommuv1_context_alloc(struct etnaviv_iommu_global *global);
1208c2ecf20Sopenharmony_cistruct etnaviv_iommu_context *
1218c2ecf20Sopenharmony_cietnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ciu32 etnaviv_iommuv2_get_mtlb_addr(struct etnaviv_iommu_context *context);
1248c2ecf20Sopenharmony_ciunsigned short etnaviv_iommuv2_get_pta_id(struct etnaviv_iommu_context *context);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#endif /* __ETNAVIV_MMU_H__ */
127