/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright © 2022-2024 Rivos Inc. * Copyright © 2023 FORTH-ICS/CARV * * Authors * Tomasz Jeznach * Nick Kossifidis */ #ifndef _RISCV_IOMMU_H_ #define _RISCV_IOMMU_H_ #include #include #include #include "iommu-bits.h" struct riscv_iommu_device; struct riscv_iommu_queue { atomic_t prod; /* unbounded producer allocation index */ atomic_t head; /* unbounded shadow ring buffer consumer index */ atomic_t tail; /* unbounded shadow ring buffer producer index */ unsigned int mask; /* index mask, queue length - 1 */ unsigned int irq; /* allocated interrupt number */ struct riscv_iommu_device *iommu; /* iommu device handling the queue when active */ void *base; /* ring buffer kernel pointer */ dma_addr_t phys; /* ring buffer physical address */ u16 qbr; /* base register offset, head and tail reference */ u16 qcr; /* control and status register offset */ u8 qid; /* queue identifier, same as RISCV_IOMMU_INTR_XX */ }; struct riscv_iommu_device { /* iommu core interface */ struct iommu_device iommu; /* iommu hardware */ struct device *dev; /* hardware control register space */ void __iomem *reg; /* supported and enabled hardware capabilities */ u64 caps; u32 fctl; /* available interrupt numbers, MSI or WSI */ unsigned int irqs[RISCV_IOMMU_INTR_COUNT]; unsigned int irqs_count; unsigned int icvec; /* hardware queues */ struct riscv_iommu_queue cmdq; struct riscv_iommu_queue fltq; /* device directory */ unsigned int ddt_mode; dma_addr_t ddt_phys; u64 *ddt_root; }; int riscv_iommu_init(struct riscv_iommu_device *iommu); void riscv_iommu_remove(struct riscv_iommu_device *iommu); #define riscv_iommu_readl(iommu, addr) \ readl_relaxed((iommu)->reg + (addr)) #define riscv_iommu_readq(iommu, addr) \ readq_relaxed((iommu)->reg + (addr)) #define riscv_iommu_writel(iommu, addr, val) \ writel_relaxed((val), (iommu)->reg + (addr)) #define riscv_iommu_writeq(iommu, addr, val) \ writeq_relaxed((val), (iommu)->reg + (addr)) #define riscv_iommu_readq_timeout(iommu, addr, val, cond, delay_us, timeout_us) \ readx_poll_timeout(readq_relaxed, (iommu)->reg + (addr), val, cond, \ delay_us, timeout_us) #define riscv_iommu_readl_timeout(iommu, addr, val, cond, delay_us, timeout_us) \ readx_poll_timeout(readl_relaxed, (iommu)->reg + (addr), val, cond, \ delay_us, timeout_us) #endif