Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,19 @@ properties:
# Since PCI provides built-in identification methods, compatible is not
# actually required. For non-PCIe hardware implementations 'riscv,iommu'
# should be specified along with 'reg' property providing MMIO location.
# SpacemiT T100 (distributed IOMMU with split IOATCs placed in adjacent
# to the DMA masters) can be seen in SpacemiT SoCs. It is integerated in
# V100 (server SoC) with coherent page table walk supported and in K3
# (client SoC) without coherent page table walk supported.
compatible:
oneOf:
- description: SpacemiT distributed IOMMUs
items:
- enum:
- spacemit,k3-t100
- spacemit,v100-t100
- const: spacemit,t100
- const: riscv,iommu
- items:
- enum:
- qemu,riscv-iommu
Expand All @@ -57,11 +68,21 @@ properties:

interrupts:
minItems: 1
maxItems: 4
maxItems: 68
description:
Wired interrupt vectors available for RISC-V IOMMU to notify the
RISC-V HARTS. The cause to interrupt vector is software defined
using IVEC IOMMU register.
using ICVEC IOMMU register. For WSI only mode, the number of the
interrupt vectors should be 1 while for MSI possible mode, the
maximum of the interrupt vectors should be 4 with the cause indexed
as "CIV=0, FIV=1, PIV=2, PMIV=3".
SpacemiT distributed IOMMU includes additional interrupts for
IOATCs. Each IOATC exposes PMIV wired vector as standalone
interrupt and the maximum number of IOATCs can be up to 64. Thus for
WSI only mode, the maximum number of the interrupt vectors should be
65 while for MSI possible mode, the maximum number of the interrupt
vectors should be 68 with the cause indexed as "IOATS CIV=0,
IOATS FIV=1, IOATS PIV=2, IOATS PMIV=3, IOATC0..n PMIV=4..4+n".

msi-parent: true

Expand All @@ -75,6 +96,18 @@ required:

additionalProperties: false

allOf:
- if:
properties:
compatible:
not:
contains:
const: spacemit,t100
then:
properties:
interrupts:
maxItems: 4

examples:
- |+
/* Example 1 (IOMMU device with wired interrupts) */
Expand Down Expand Up @@ -145,3 +178,24 @@ examples:
};
};
};

- |+
/* Example 5 (SpacemiT distributed IOMMU) */
#include <dt-bindings/interrupt-controller/irq.h>

iommu4: iommu@1bccd000 {
compatible = "spacemit,k3-t100", "spacemit,t100", "riscv,iommu";
reg = <0x1bccd000 0x1000>;
interrupts = <58 IRQ_TYPE_LEVEL_HIGH>,
<62 IRQ_TYPE_LEVEL_HIGH>, <63 IRQ_TYPE_LEVEL_HIGH>,
<62 IRQ_TYPE_LEVEL_HIGH>, <63 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&saplic>;
#iommu-cells = <0x01>;
};

/* Device with four IOMMU device IDs */
master2 {
#iommu-cells = <1>;
iommus = <&iommu4 0xc0010>, <&iommu4 0xc0011>,
<&iommu4 0xc0012>, <&iommu4 0xc0013>;
};
5 changes: 5 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -22709,12 +22709,17 @@ K: riscv

RISC-V IOMMU
M: Tomasz Jeznach <tjeznach@rivosinc.com>
M: Lv Zheng <lv.zheng@linux.spacemit.com>
M: Jingyu Li <joey.li@spacemit.com>
L: iommu@lists.linux.dev
L: linux-riscv@lists.infradead.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux.git
F: Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
F: drivers/iommu/riscv/
F: drivers/perf/riscv_iommu_hpm.c
F: include/linux/riscv_iommu.h
F: tools/perf/pmu-events/arch/riscv/spacemit/iommu/

RISC-V MICROCHIP SUPPORT
M: Conor Dooley <conor.dooley@microchip.com>
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ config OF_IOMMU

# IOMMU-agnostic DMA-mapping layer
config IOMMU_DMA
def_bool ARM64 || X86 || S390
def_bool ARM64 || X86 || S390 || RISCV
select DMA_OPS_HELPERS
select IOMMU_API
select IOMMU_IOVA
Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ config RISCV_IOMMU
depends on RISCV && 64BIT
default y
select IOMMU_API
select AUXILIARY_BUS
help
Support for implementations of the RISC-V IOMMU architecture that
complements the RISC-V MMU capabilities, providing similar address
Expand Down
12 changes: 12 additions & 0 deletions drivers/iommu/riscv/iommu-bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ enum riscv_iommu_hpmevent_id {
#define RISCV_IOMMU_ICVEC_PMIV GENMASK_ULL(11, 8)
#define RISCV_IOMMU_ICVEC_PIV GENMASK_ULL(15, 12)

/* 5.28 Distributed translation interface status register (dtisr0-3) (4 * 32-bits) */
#define RISCV_IOMMU_REG_DTISR_BASE 0x02B0
#define RISCV_IOMMU_REG_DTISR(_n) (RISCV_IOMMU_REG_DTISR_BASE + ((_n) * 0x04))
#define RISCV_IOMMU_DTI_STS_SHIFT(_n) (((_n) % 16) * 2)
#define RISCV_IOMMU_DTI_STS_MASK(_n) (0x3 << RISCV_IOMMU_DTI_STS_SHIFT(_n))
#define RISCV_IOMMU_DTI_STS_NONE 0x0
#define RISCV_IOMMU_DTI_STS_IOATC 0x1

/* 5.28 MSI Configuration table (32 * 64bits) */
#define RISCV_IOMMU_REG_MSI_CFG_TBL 0x0300
#define RISCV_IOMMU_REG_MSI_CFG_TBL_ADDR(_n) \
Expand All @@ -292,6 +300,10 @@ enum riscv_iommu_hpmevent_id {

#define RISCV_IOMMU_REG_SIZE 0x1000

/* SpacemiT IOMMU IOATC registers */
#define MAX_RISCV_IOMMU_IOATC 64
#define RISCV_IOMMU_IOATC_BASE(_idx) (((_idx) + 1) * RISCV_IOMMU_REG_SIZE)

/*
* Chapter 2: Data structures
*/
Expand Down
8 changes: 7 additions & 1 deletion drivers/iommu/riscv/iommu-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static int riscv_iommu_pci_probe(struct pci_dev *pdev, const struct pci_device_i
{
struct device *dev = &pdev->dev;
struct riscv_iommu_device *iommu;
phys_addr_t reg_phys;
resource_size_t reg_size;
int rc, vec;

rc = pcim_enable_device(pdev);
Expand All @@ -43,7 +45,9 @@ static int riscv_iommu_pci_probe(struct pci_dev *pdev, const struct pci_device_i
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM))
return -ENODEV;

if (pci_resource_len(pdev, 0) < RISCV_IOMMU_REG_SIZE)
reg_phys = pci_resource_start(pdev, 0);
reg_size = pci_resource_len(pdev, 0);
if (reg_size < RISCV_IOMMU_REG_SIZE)
return -ENODEV;

rc = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
Expand All @@ -56,6 +60,8 @@ static int riscv_iommu_pci_probe(struct pci_dev *pdev, const struct pci_device_i

iommu->dev = dev;
iommu->reg = pcim_iomap_table(pdev)[0];
iommu->reg_phys = reg_phys;
iommu->reg_size = reg_size;

pci_set_master(pdev);
dev_set_drvdata(dev, iommu);
Expand Down
7 changes: 5 additions & 2 deletions drivers/iommu/riscv/iommu-platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ static int riscv_iommu_platform_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(iommu->reg),
"could not map register region\n");

iommu->reg_phys = res->start;
iommu->reg_size = resource_size(res);

dev_set_drvdata(dev, iommu);

/* Check device reported capabilities / features. */
Expand All @@ -72,8 +75,8 @@ static int riscv_iommu_platform_probe(struct platform_device *pdev)
if (iommu->irqs_count <= 0)
return dev_err_probe(dev, -ENODEV,
"no IRQ resources provided\n");
if (iommu->irqs_count > RISCV_IOMMU_INTR_COUNT)
iommu->irqs_count = RISCV_IOMMU_INTR_COUNT;
if (iommu->irqs_count > RISCV_IOMMU_INTR_COUNT + MAX_RISCV_IOMMU_IOATC)
iommu->irqs_count = RISCV_IOMMU_INTR_COUNT + MAX_RISCV_IOMMU_IOATC;

igs = FIELD_GET(RISCV_IOMMU_CAPABILITIES_IGS, iommu->caps);
switch (igs) {
Expand Down
Loading
Loading