drivers/iommu/sprd-iommu.c

Source file repositories/reference/linux-study-clean/drivers/iommu/sprd-iommu.c

File Facts

System
Linux kernel
Corpus path
drivers/iommu/sprd-iommu.c
Extension
.c
Size
13889 bytes
Lines
543
Domain
Driver Families
Bucket
drivers/iommu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sprd_iommu_device {
	struct sprd_iommu_domain	*dom;
	enum sprd_iommu_version	ver;
	u32			*prot_page_va;
	dma_addr_t		prot_page_pa;
	void __iomem		*base;
	struct device		*dev;
	struct iommu_device	iommu;
	struct clk		*eb;
};

struct sprd_iommu_domain {
	spinlock_t		pgtlock; /* lock for page table */
	struct iommu_domain	domain;
	u32			*pgt_va; /* page table virtual address base */
	dma_addr_t		pgt_pa; /* page table physical address base */
	struct sprd_iommu_device	*sdev;
};

static const struct iommu_ops sprd_iommu_ops;

static struct sprd_iommu_domain *to_sprd_domain(struct iommu_domain *dom)
{
	return container_of(dom, struct sprd_iommu_domain, domain);
}

static inline void
sprd_iommu_write(struct sprd_iommu_device *sdev, unsigned int reg, u32 val)
{
	writel_relaxed(val, sdev->base + reg);
}

static inline u32
sprd_iommu_read(struct sprd_iommu_device *sdev, unsigned int reg)
{
	return readl_relaxed(sdev->base + reg);
}

static inline void
sprd_iommu_update_bits(struct sprd_iommu_device *sdev, unsigned int reg,
		  u32 mask, u32 shift, u32 val)
{
	u32 t = sprd_iommu_read(sdev, reg);

	t = (t & (~(mask << shift))) | ((val & mask) << shift);
	sprd_iommu_write(sdev, reg, t);
}

static inline int
sprd_iommu_get_version(struct sprd_iommu_device *sdev)
{
	int ver = (sprd_iommu_read(sdev, SPRD_IOMMU_VERSION) &
		   SPRD_VERSION_MASK) >> SPRD_VERSION_SHIFT;

	switch (ver) {
	case SPRD_IOMMU_EX:
	case SPRD_IOMMU_VAU:
		return ver;
	default:
		return -EINVAL;
	}
}

static size_t
sprd_iommu_pgt_size(struct iommu_domain *domain)
{
	return ((domain->geometry.aperture_end -
		 domain->geometry.aperture_start + 1) >>
		SPRD_IOMMU_PAGE_SHIFT) * sizeof(u32);
}

static struct iommu_domain *sprd_iommu_domain_alloc_paging(struct device *dev)
{
	struct sprd_iommu_domain *dom;

	dom = kzalloc_obj(*dom);
	if (!dom)
		return NULL;

	spin_lock_init(&dom->pgtlock);

	dom->domain.pgsize_bitmap = SPRD_IOMMU_PAGE_SIZE;

	dom->domain.geometry.aperture_start = 0;
	dom->domain.geometry.aperture_end = SZ_256M - 1;
	dom->domain.geometry.force_aperture = true;

	return &dom->domain;
}

Annotation

Implementation Notes