Re: [PATCH 2/3] iommu/hisilicon: Add hi6220 iommu driver
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
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
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
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
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
Enable iommu on hi6220 SoC platform. Signed-off-by: Chen FengSigned-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,