提交 8a68ee87 编写于 作者: Z Zhou Guanghui 提交者: Yang Yingliang

iommu: support message based spi for smmu

ascend inclusion
category: feature
bugzilla: NA
CVE: NA

------------------------------------------------------------------

The current SMMU driver supports SPI WireInterrupt and Message Based
SPI. However, some hisilicon chips use the Messaged Based SPI. Therefore,
a special attribute is added to indentify this situation. Add an option
"hisicion,message-based-spi" and addr of GICD_SETSPI to dts node of SMMU,
like this:
    hisicion,message-based-spi
    iommu-spi-base=<0x10 0x9000040> //Addr of GICD_SETSPI: 0x1009000040
Signed-off-by: NZhou Guanghui <zhouguanghui1@huawei.com>
Reviewed-by: NDing Tianhong <dingtianhong@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 63149a11
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/irq.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include "io-pgtable.h" #include "io-pgtable.h"
...@@ -609,8 +610,11 @@ struct arm_smmu_device { ...@@ -609,8 +610,11 @@ struct arm_smmu_device {
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
#define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1) #define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1)
#define ARM_SMMU_OPT_MESSAGE_BASED_SPI (1 << 2)
u32 options; u32 options;
u64 spi_base;
struct arm_smmu_cmdq cmdq; struct arm_smmu_cmdq cmdq;
struct arm_smmu_evtq evtq; struct arm_smmu_evtq evtq;
struct arm_smmu_priq priq; struct arm_smmu_priq priq;
...@@ -722,6 +726,7 @@ struct arm_smmu_option_prop { ...@@ -722,6 +726,7 @@ struct arm_smmu_option_prop {
static struct arm_smmu_option_prop arm_smmu_options[] = { static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
{ ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"}, { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"},
{ ARM_SMMU_OPT_MESSAGE_BASED_SPI, "hisilicon,message-based-spi"},
{ 0, NULL}, { 0, NULL},
}; };
...@@ -1126,7 +1131,8 @@ static int __arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) ...@@ -1126,7 +1131,8 @@ static int __arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
static void arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) static void arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
{ {
int ret; int ret;
bool msi = (smmu->features & ARM_SMMU_FEAT_MSI) && bool msi = !(smmu->options & ARM_SMMU_OPT_MESSAGE_BASED_SPI) &&
(smmu->features & ARM_SMMU_FEAT_MSI) &&
(smmu->features & ARM_SMMU_FEAT_COHERENCY); (smmu->features & ARM_SMMU_FEAT_COHERENCY);
ret = msi ? __arm_smmu_cmdq_issue_sync_msi(smmu) ret = msi ? __arm_smmu_cmdq_issue_sync_msi(smmu)
...@@ -3070,6 +3076,37 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu) ...@@ -3070,6 +3076,37 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
devm_add_action(dev, arm_smmu_free_msis, dev); devm_add_action(dev, arm_smmu_free_msis, dev);
} }
static void arm_smmu_setup_message_based_spi(struct arm_smmu_device *smmu)
{
struct irq_desc *desc;
u32 event_hwirq, gerror_hwirq, pri_hwirq;
desc = irq_to_desc(smmu->gerr_irq);
gerror_hwirq = desc->irq_data.hwirq;
writeq_relaxed(smmu->spi_base, smmu->base + ARM_SMMU_GERROR_IRQ_CFG0);
writel_relaxed(gerror_hwirq, smmu->base + ARM_SMMU_GERROR_IRQ_CFG1);
writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE,
smmu->base + ARM_SMMU_GERROR_IRQ_CFG2);
desc = irq_to_desc(smmu->evtq.q.irq);
event_hwirq = desc->irq_data.hwirq;
writeq_relaxed(smmu->spi_base, smmu->base + ARM_SMMU_EVTQ_IRQ_CFG0);
writel_relaxed(event_hwirq, smmu->base + ARM_SMMU_EVTQ_IRQ_CFG1);
writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE,
smmu->base + ARM_SMMU_EVTQ_IRQ_CFG2);
if (smmu->features & ARM_SMMU_FEAT_PRI) {
desc = irq_to_desc(smmu->priq.q.irq);
pri_hwirq = desc->irq_data.hwirq;
writeq_relaxed(smmu->spi_base,
smmu->base + ARM_SMMU_PRIQ_IRQ_CFG0);
writel_relaxed(pri_hwirq, smmu->base + ARM_SMMU_PRIQ_IRQ_CFG1);
writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE,
smmu->base + ARM_SMMU_PRIQ_IRQ_CFG2);
}
}
static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
{ {
int irq, ret; int irq, ret;
...@@ -3148,6 +3185,9 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu) ...@@ -3148,6 +3185,9 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
if (smmu->features & ARM_SMMU_FEAT_PRI) if (smmu->features & ARM_SMMU_FEAT_PRI)
irqen_flags |= IRQ_CTRL_PRIQ_IRQEN; irqen_flags |= IRQ_CTRL_PRIQ_IRQEN;
if (smmu->options & ARM_SMMU_OPT_MESSAGE_BASED_SPI)
arm_smmu_setup_message_based_spi(smmu);
/* Enable interrupt generation on the SMMU */ /* Enable interrupt generation on the SMMU */
ret = arm_smmu_write_reg_sync(smmu, irqen_flags, ret = arm_smmu_write_reg_sync(smmu, irqen_flags,
ARM_SMMU_IRQ_CTRL, ARM_SMMU_IRQ_CTRLACK); ARM_SMMU_IRQ_CTRL, ARM_SMMU_IRQ_CTRLACK);
...@@ -3643,6 +3683,14 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, ...@@ -3643,6 +3683,14 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev,
parse_driver_options(smmu); parse_driver_options(smmu);
if (smmu->options & ARM_SMMU_OPT_MESSAGE_BASED_SPI) {
if (of_property_read_u64(dev->of_node, "iommu-spi-base",
&smmu->spi_base)) {
dev_err(dev, "missing irq base address\n");
ret = -EINVAL;
}
}
if (of_dma_is_coherent(dev->of_node)) if (of_dma_is_coherent(dev->of_node))
smmu->features |= ARM_SMMU_FEAT_COHERENCY; smmu->features |= ARM_SMMU_FEAT_COHERENCY;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册