Re: [PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver

2015-10-18 Thread chenfeng


On 2015/10/14 20:18, Joerg Roedel wrote:
> On Thu, Oct 08, 2015 at 03:45:47PM +0800, Chen Feng wrote:
>> +static int hi6220_smmu_attach_dev(struct iommu_domain *domain,
>> +  struct device *dev)
>> +{
>> +struct hi6220_domain *m_domain = to_hi6220_domain(domain);
>> +
>> +smmu_domain_prepare(m_domain);
>> +dev->archdata.iommu = _domain->smmu_dev->iova_allocator;
>> +
>> +return 0;
>> +}
> 
> What happens when you attach devices behind different smmus to one
> domain? Will that overwrite the smmu_dev pointer in the domain?
> 

Since the smmu master use the same pagetable, the master can use the 
iova_allocator
in smmu driver to allocate iova address.

In this way, the different master can get the different io address.

>> +static size_t hi6220_smmu_unmap(struct iommu_domain *domain, unsigned long 
>> iova,
>> +size_t size)
>> +{
>> +struct hi6220_domain *m_domain = to_hi6220_domain(domain);
>> +size_t page_size = m_domain->smmu_dev->page_size;
>> +struct hi6220_smmu *smmu_dev = m_domain->smmu_dev;
>> +int *page_table = (unsigned int *)smmu_dev->pgtable_virt;
>> +
>> +if (size != page_size) {
>> +pr_err("unmap size error, only support %zd\n", page_size);
>> +return 0;
>> +}
>> +
>> +__clear_smmu_pte(page_table + IOVA_PFN(iova));
>> +
>> +return page_size;
>> +}
> 
> Don't you need a call to __invalid_smmu_tlb here too?

Thanks, I will fix this next version.
> 
> 
> 
>   Joerg
> 
> 
> .
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver

2015-10-18 Thread chenfeng


On 2015/10/14 20:18, Joerg Roedel wrote:
> On Thu, Oct 08, 2015 at 03:45:47PM +0800, Chen Feng wrote:
>> +static int hi6220_smmu_attach_dev(struct iommu_domain *domain,
>> +  struct device *dev)
>> +{
>> +struct hi6220_domain *m_domain = to_hi6220_domain(domain);
>> +
>> +smmu_domain_prepare(m_domain);
>> +dev->archdata.iommu = _domain->smmu_dev->iova_allocator;
>> +
>> +return 0;
>> +}
> 
> What happens when you attach devices behind different smmus to one
> domain? Will that overwrite the smmu_dev pointer in the domain?
> 

Since the smmu master use the same pagetable, the master can use the 
iova_allocator
in smmu driver to allocate iova address.

In this way, the different master can get the different io address.

>> +static size_t hi6220_smmu_unmap(struct iommu_domain *domain, unsigned long 
>> iova,
>> +size_t size)
>> +{
>> +struct hi6220_domain *m_domain = to_hi6220_domain(domain);
>> +size_t page_size = m_domain->smmu_dev->page_size;
>> +struct hi6220_smmu *smmu_dev = m_domain->smmu_dev;
>> +int *page_table = (unsigned int *)smmu_dev->pgtable_virt;
>> +
>> +if (size != page_size) {
>> +pr_err("unmap size error, only support %zd\n", page_size);
>> +return 0;
>> +}
>> +
>> +__clear_smmu_pte(page_table + IOVA_PFN(iova));
>> +
>> +return page_size;
>> +}
> 
> Don't you need a call to __invalid_smmu_tlb here too?

Thanks, I will fix this next version.
> 
> 
> 
>   Joerg
> 
> 
> .
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver

2015-10-14 Thread Joerg Roedel
On Thu, Oct 08, 2015 at 03:45:47PM +0800, Chen Feng wrote:
> +static int hi6220_smmu_attach_dev(struct iommu_domain *domain,
> +   struct device *dev)
> +{
> + struct hi6220_domain *m_domain = to_hi6220_domain(domain);
> +
> + smmu_domain_prepare(m_domain);
> + dev->archdata.iommu = _domain->smmu_dev->iova_allocator;
> +
> + return 0;
> +}

What happens when you attach devices behind different smmus to one
domain? Will that overwrite the smmu_dev pointer in the domain?

> +static size_t hi6220_smmu_unmap(struct iommu_domain *domain, unsigned long 
> iova,
> + size_t size)
> +{
> + struct hi6220_domain *m_domain = to_hi6220_domain(domain);
> + size_t page_size = m_domain->smmu_dev->page_size;
> + struct hi6220_smmu *smmu_dev = m_domain->smmu_dev;
> + int *page_table = (unsigned int *)smmu_dev->pgtable_virt;
> +
> + if (size != page_size) {
> + pr_err("unmap size error, only support %zd\n", page_size);
> + return 0;
> + }
> +
> + __clear_smmu_pte(page_table + IOVA_PFN(iova));
> +
> + return page_size;
> +}

Don't you need a call to __invalid_smmu_tlb here too?



Joerg

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver

2015-10-14 Thread Joerg Roedel
On Thu, Oct 08, 2015 at 03:45:47PM +0800, Chen Feng wrote:
> +static int hi6220_smmu_attach_dev(struct iommu_domain *domain,
> +   struct device *dev)
> +{
> + struct hi6220_domain *m_domain = to_hi6220_domain(domain);
> +
> + smmu_domain_prepare(m_domain);
> + dev->archdata.iommu = _domain->smmu_dev->iova_allocator;
> +
> + return 0;
> +}

What happens when you attach devices behind different smmus to one
domain? Will that overwrite the smmu_dev pointer in the domain?

> +static size_t hi6220_smmu_unmap(struct iommu_domain *domain, unsigned long 
> iova,
> + size_t size)
> +{
> + struct hi6220_domain *m_domain = to_hi6220_domain(domain);
> + size_t page_size = m_domain->smmu_dev->page_size;
> + struct hi6220_smmu *smmu_dev = m_domain->smmu_dev;
> + int *page_table = (unsigned int *)smmu_dev->pgtable_virt;
> +
> + if (size != page_size) {
> + pr_err("unmap size error, only support %zd\n", page_size);
> + return 0;
> + }
> +
> + __clear_smmu_pte(page_table + IOVA_PFN(iova));
> +
> + return page_size;
> +}

Don't you need a call to __invalid_smmu_tlb here too?



Joerg

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver

2015-10-08 Thread Chen Feng
Enable iommu on hi6220 SoC platform.

Signed-off-by: Chen Feng 
Signed-off-by: Yu Dongbin 
---
 drivers/iommu/Kconfig|   8 +
 drivers/iommu/Makefile   |   1 +
 drivers/iommu/hi6220_iommu.c | 503 +++
 3 files changed, 512 insertions(+)
 create mode 100644 drivers/iommu/hi6220_iommu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 4664c2a..9b41708 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -343,6 +343,14 @@ 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.
+
 # 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..ee4dfef 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
 obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o
 obj-$(CONFIG_SHMOBILE_IPMMU) += shmobile-ipmmu.o
 obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o
+obj-$(CONFIG_HI6220_IOMMU) += hi6220_iommu.o
diff --git a/drivers/iommu/hi6220_iommu.c b/drivers/iommu/hi6220_iommu.c
new file mode 100644
index 000..9e9b19d
--- /dev/null
+++ b/drivers/iommu/hi6220_iommu.c
@@ -0,0 +1,503 @@
+/*
+ * 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 
+#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_REGS_MAX(15)
+#define SMMU_REGS_SGMT_END   (0x60)
+#define SMMU_CHIP_ID_V100(1)
+#define SMMU_CHIP_ID_V200(2)
+
+#define SMMU_REGS_OPS_SEGMT_START(0xf00)
+#define SMMU_REGS_OPS_SEGMT_NUMB (8)
+#define SMMU_REGS_AXI_SEGMT_START(0xf80)
+#define SMMU_REGS_AXI_SEGMT_NUMB (8)
+
+#define SMMU_INIT(0x1)
+#define SMMU_RUNNING (0x2)
+#define SMMU_SUSPEND (0x3)
+#define SMMU_STOP(0x4)
+
+#define PAGE_ENTRY_VALID (0x1)
+
+#define IOVA_START_PFN   (1)
+#define IOPAGE_SHIFT (12)
+#define IOVA_PFN(addr)   ((addr) >> IOPAGE_SHIFT)
+#define IOVA_PAGE_SZ (1UL << IOPAGE_SHIFT)
+#define IOVA_START   (0x2000)
+#define IOVA_END (0x8000)
+
+struct hi6220_smmu {
+   unsigned int irq;
+   irq_handler_t smmu_isr;
+   void __iomem *reg_base;
+   struct clk *smmu_peri_clk;
+   struct clk *smmu_clk;
+   struct clk *media_sc_clk;
+   size_t page_size;
+   struct iova_domain iova_allocator;
+   dma_addr_t pgtable_phy;
+   void *pgtable_virt;
+};
+
+struct hi6220_domain {
+   struct hi6220_smmu *smmu_dev;
+   struct device *dev;
+   spinlock_t spinlock; /*spinlock for device*/
+   struct iommu_domain io_domain;
+   unsigned long iova_start;
+   unsigned long iova_end;
+};
+
+static struct hi6220_smmu *smmu_dev_handle;
+static unsigned int smmu_regs_value[SMMU_REGS_MAX] = {0};
+
+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 

[PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver

2015-10-08 Thread Chen Feng
Enable iommu on hi6220 SoC platform.

Signed-off-by: Chen Feng 
Signed-off-by: Yu Dongbin 
---
 drivers/iommu/Kconfig|   8 +
 drivers/iommu/Makefile   |   1 +
 drivers/iommu/hi6220_iommu.c | 503 +++
 3 files changed, 512 insertions(+)
 create mode 100644 drivers/iommu/hi6220_iommu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 4664c2a..9b41708 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -343,6 +343,14 @@ 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.
+
 # 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..ee4dfef 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
 obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o
 obj-$(CONFIG_SHMOBILE_IPMMU) += shmobile-ipmmu.o
 obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o
+obj-$(CONFIG_HI6220_IOMMU) += hi6220_iommu.o
diff --git a/drivers/iommu/hi6220_iommu.c b/drivers/iommu/hi6220_iommu.c
new file mode 100644
index 000..9e9b19d
--- /dev/null
+++ b/drivers/iommu/hi6220_iommu.c
@@ -0,0 +1,503 @@
+/*
+ * 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 
+#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_REGS_MAX(15)
+#define SMMU_REGS_SGMT_END   (0x60)
+#define SMMU_CHIP_ID_V100(1)
+#define SMMU_CHIP_ID_V200(2)
+
+#define SMMU_REGS_OPS_SEGMT_START(0xf00)
+#define SMMU_REGS_OPS_SEGMT_NUMB (8)
+#define SMMU_REGS_AXI_SEGMT_START(0xf80)
+#define SMMU_REGS_AXI_SEGMT_NUMB (8)
+
+#define SMMU_INIT(0x1)
+#define SMMU_RUNNING (0x2)
+#define SMMU_SUSPEND (0x3)
+#define SMMU_STOP(0x4)
+
+#define PAGE_ENTRY_VALID (0x1)
+
+#define IOVA_START_PFN   (1)
+#define IOPAGE_SHIFT (12)
+#define IOVA_PFN(addr)   ((addr) >> IOPAGE_SHIFT)
+#define IOVA_PAGE_SZ (1UL << IOPAGE_SHIFT)
+#define IOVA_START   (0x2000)
+#define IOVA_END (0x8000)
+
+struct hi6220_smmu {
+   unsigned int irq;
+   irq_handler_t smmu_isr;
+   void __iomem *reg_base;
+   struct clk *smmu_peri_clk;
+   struct clk *smmu_clk;
+   struct clk *media_sc_clk;
+   size_t page_size;
+   struct iova_domain iova_allocator;
+   dma_addr_t pgtable_phy;
+   void *pgtable_virt;
+};
+
+struct hi6220_domain {
+   struct hi6220_smmu *smmu_dev;
+   struct device *dev;
+   spinlock_t spinlock; /*spinlock for device*/
+   struct iommu_domain io_domain;
+   unsigned long iova_start;
+   unsigned long iova_end;
+};
+
+static struct hi6220_smmu *smmu_dev_handle;
+static unsigned int smmu_regs_value[SMMU_REGS_MAX] = {0};
+
+static struct hi6220_domain *to_hi6220_domain(struct iommu_domain *dom)
+{
+   return container_of(dom,