[PATCH 2/3] Add iommu driver for hi6220 SoC platform
iommu/hisilicon: Add hi6220-SoC smmu driver The smmu on hi6220 SoC is for media system.And the media IP use the same page-table. It supports only one-to-one mapping from iova to phys address. Signed-off-by: Chen Feng Signed-off-by: Yu Dongbin --- drivers/iommu/Kconfig| 11 + drivers/iommu/Makefile | 1 + drivers/iommu/hi6220_iommu.c | 492 +++ 3 files changed, 504 insertions(+) create mode 100644 drivers/iommu/hi6220_iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index cbe6a89..6ca24db 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -342,6 +342,17 @@ config SPAPR_TCE_IOMMU Enables bits of IOMMU API required by VFIO. The iommu_ops is not implemented as it is not necessary for VFIO. +config HI6220_IOMMU + bool "Hi6220 IOMMU Support" + depends on ARM64 + select IOMMU_API + select IOMMU_IOVA + help + Enable IOMMU Driver for hi6220 SoC. The IOMMU API and IOMMU IOVA + is also selected. + + If unsure, say N. + # ARM IOMMU support config ARM_SMMU bool "ARM Ltd. System MMU (SMMU) Support" diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index c6dcc51..db68fb3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o obj-$(CONFIG_ARM_SMMU) += arm-smmu.o obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o obj-$(CONFIG_DMAR_TABLE) += dmar.o +obj-$(CONFIG_HI6220_IOMMU) += hi6220_iommu.o obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o diff --git a/drivers/iommu/hi6220_iommu.c b/drivers/iommu/hi6220_iommu.c new file mode 100644 index 000..47eb390 --- /dev/null +++ b/drivers/iommu/hi6220_iommu.c @@ -0,0 +1,492 @@ +/* + * Hisilicon Hi6220 IOMMU driver + * + * Copyright (c) 2015 Hisilicon Limited. + * + * Author: Chen Feng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "IOMMU: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMMU_CTRL_OFFSET (0x) +#define SMMU_ENABLE_OFFSET (0x0004) +#define SMMU_PTBR_OFFSET (0x0008) +#define SMMU_START_OFFSET(0x000C) +#define SMMU_END_OFFSET (0x0010) +#define SMMU_INTMASK_OFFSET (0x0014) +#define SMMU_RINTSTS_OFFSET (0x0018) +#define SMMU_MINTSTS_OFFSET (0x001C) +#define SMMU_INTCLR_OFFSET (0x0020) +#define SMMU_STATUS_OFFSET (0x0024) +#define SMMU_AXIID_OFFSET(0x0028) +#define SMMU_CNTCTRL_OFFSET (0x002C) +#define SMMU_TRANSCNT_OFFSET (0x0030) +#define SMMU_L0TLBHITCNT_OFFSET (0x0034) +#define SMMU_L1TLBHITCNT_OFFSET (0x0038) +#define SMMU_WRAPCNT_OFFSET (0x003C) +#define SMMU_SEC_START_OFFSET(0x0040) +#define SMMU_SEC_END_OFFSET (0x0044) +#define SMMU_VERSION_OFFSET (0x0048) +#define SMMU_IPTSRC_OFFSET (0x004C) +#define SMMU_IPTPA_OFFSET(0x0050) +#define SMMU_TRBA_OFFSET (0x0054) +#define SMMU_BYS_START_OFFSET(0x0058) +#define SMMU_BYS_END_OFFSET (0x005C) +#define SMMU_RAM_OFFSET (0x1000) + +#define SMMU_CTRL_INVALID(BIT(10)) +#define SMMU_SR_REGS_NUM (15) +#define SMMU_REGS_SGMT_END (0x60) +#define PAGE_ENTRY_VALID (0x1) +#define IOPAGE_SHIFT (12) +#define IOVA_PFN(addr) ((addr) >> IOPAGE_SHIFT) +#define IOVA_PAGE_SZ (SZ_4K) + +/** + * The iova address from 0 ~ 2G + */ +#define IOVA_START (0x0) +#define IOVA_END (0x8000) + +struct hi6220_smmu { + unsigned int irq; + void __iomem *reg_base; + struct clk *smmu_peri_clk; + struct clk *smmu_clk; + struct clk *media_sc_clk; + spinlock_t spinlock; /*spinlock for tlb invalid*/ + dma_addr_t pgtable_phy; + void *pgtable_virt; + u32 pgtable_size; + u32 *sr_data; +}; + +struct hi6220_domain { + struct hi6220_smmu *smmu_dev; + struct iommu_domain io_domain; +}; + +static struct hi6220_smmu *smmu_dev_handle; +static struct iova_domain iova_allocator; + +static struct hi6220_domain *to_hi6220_domain(struct iommu_domain *dom) +{ + return container_of(dom, struct hi6220_domain, io_domain); +} + +static inline void __smmu_writel(struct hi6220_smmu *smmu_dev, u32 value, +unsigned long offset) +{ + writel(value, smmu_dev->reg_base + offset); +} + +static inline u32 __smmu_readl(struct hi6220_smmu
[PATCH 2/3] Add iommu driver for hi6220 SoC platform
iommu/hisilicon: Add hi6220-SoC smmu driver The smmu on hi6220 SoC is for media system.And the media IP use the same page-table. It supports only one-to-one mapping from iova to phys address. Signed-off-by: Chen FengSigned-off-by: Yu Dongbin --- drivers/iommu/Kconfig| 11 + drivers/iommu/Makefile | 1 + drivers/iommu/hi6220_iommu.c | 492 +++ 3 files changed, 504 insertions(+) create mode 100644 drivers/iommu/hi6220_iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index cbe6a89..6ca24db 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -342,6 +342,17 @@ config SPAPR_TCE_IOMMU Enables bits of IOMMU API required by VFIO. The iommu_ops is not implemented as it is not necessary for VFIO. +config HI6220_IOMMU + bool "Hi6220 IOMMU Support" + depends on ARM64 + select IOMMU_API + select IOMMU_IOVA + help + Enable IOMMU Driver for hi6220 SoC. The IOMMU API and IOMMU IOVA + is also selected. + + If unsure, say N. + # ARM IOMMU support config ARM_SMMU bool "ARM Ltd. System MMU (SMMU) Support" diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index c6dcc51..db68fb3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o obj-$(CONFIG_ARM_SMMU) += arm-smmu.o obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o obj-$(CONFIG_DMAR_TABLE) += dmar.o +obj-$(CONFIG_HI6220_IOMMU) += hi6220_iommu.o obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o diff --git a/drivers/iommu/hi6220_iommu.c b/drivers/iommu/hi6220_iommu.c new file mode 100644 index 000..47eb390 --- /dev/null +++ b/drivers/iommu/hi6220_iommu.c @@ -0,0 +1,492 @@ +/* + * Hisilicon Hi6220 IOMMU driver + * + * Copyright (c) 2015 Hisilicon Limited. + * + * Author: Chen Feng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "IOMMU: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMMU_CTRL_OFFSET (0x) +#define SMMU_ENABLE_OFFSET (0x0004) +#define SMMU_PTBR_OFFSET (0x0008) +#define SMMU_START_OFFSET(0x000C) +#define SMMU_END_OFFSET (0x0010) +#define SMMU_INTMASK_OFFSET (0x0014) +#define SMMU_RINTSTS_OFFSET (0x0018) +#define SMMU_MINTSTS_OFFSET (0x001C) +#define SMMU_INTCLR_OFFSET (0x0020) +#define SMMU_STATUS_OFFSET (0x0024) +#define SMMU_AXIID_OFFSET(0x0028) +#define SMMU_CNTCTRL_OFFSET (0x002C) +#define SMMU_TRANSCNT_OFFSET (0x0030) +#define SMMU_L0TLBHITCNT_OFFSET (0x0034) +#define SMMU_L1TLBHITCNT_OFFSET (0x0038) +#define SMMU_WRAPCNT_OFFSET (0x003C) +#define SMMU_SEC_START_OFFSET(0x0040) +#define SMMU_SEC_END_OFFSET (0x0044) +#define SMMU_VERSION_OFFSET (0x0048) +#define SMMU_IPTSRC_OFFSET (0x004C) +#define SMMU_IPTPA_OFFSET(0x0050) +#define SMMU_TRBA_OFFSET (0x0054) +#define SMMU_BYS_START_OFFSET(0x0058) +#define SMMU_BYS_END_OFFSET (0x005C) +#define SMMU_RAM_OFFSET (0x1000) + +#define SMMU_CTRL_INVALID(BIT(10)) +#define SMMU_SR_REGS_NUM (15) +#define SMMU_REGS_SGMT_END (0x60) +#define PAGE_ENTRY_VALID (0x1) +#define IOPAGE_SHIFT (12) +#define IOVA_PFN(addr) ((addr) >> IOPAGE_SHIFT) +#define IOVA_PAGE_SZ (SZ_4K) + +/** + * The iova address from 0 ~ 2G + */ +#define IOVA_START (0x0) +#define IOVA_END (0x8000) + +struct hi6220_smmu { + unsigned int irq; + void __iomem *reg_base; + struct clk *smmu_peri_clk; + struct clk *smmu_clk; + struct clk *media_sc_clk; + spinlock_t spinlock; /*spinlock for tlb invalid*/ + dma_addr_t pgtable_phy; + void *pgtable_virt; + u32 pgtable_size; + u32 *sr_data; +}; + +struct hi6220_domain { + struct hi6220_smmu *smmu_dev; + struct iommu_domain io_domain; +}; + +static struct hi6220_smmu *smmu_dev_handle; +static struct iova_domain iova_allocator; + +static struct hi6220_domain *to_hi6220_domain(struct iommu_domain *dom) +{ + return container_of(dom, struct hi6220_domain, io_domain); +} + +static inline void __smmu_writel(struct hi6220_smmu *smmu_dev, u32 value, +unsigned long offset) +{ + writel(value, smmu_dev->reg_base