[PATCH 2/3] Add iommu driver for hi6220 SoC platform

2015-10-27 Thread Chen Feng
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

2015-10-27 Thread Chen Feng
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