Skip to content
Open
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
6 changes: 5 additions & 1 deletion arch/arm64/boot/dts/xilinx/zynqmp.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,10 @@
snps,arcsync-cluster-id = <0x01>;
/* Disable ARC core booting during Linux kernel booting for debugging purposes */
/* snps,auto-boot; */
#stream-id-cells = <1>;
/* VPX@0 CBU master interface stream ID's for the SMMU, connected to TBU3:
TBU3 (0b11 << 10) | S_AXI_HP0_FPD Master ID (0b1010 << 6) | AXI ID (0) */
iommus = <&smmu 0xE80>;
};

app_vpx@0 {
Expand Down Expand Up @@ -970,7 +974,7 @@
/* How many address bits the VPX master can use for DMA to system RAM */
snps,dma-bits = <0x1f>;
#stream-id-cells = <0x01>;
/* Stream ID = TBU4 (0b100 << 10) | S_AXI_HP1_FPD Master ID (0b1001 << 6) | AXI ID (0) */
/* Stream ID = TBU4 (0b100 << 10) | S_AXI_HP1_FPD Master ID (0b1001 << 6) | AXI ID (1) */
iommus = <&smmu 0x12c1>;
};
};
Expand Down
50 changes: 50 additions & 0 deletions drivers/remoteproc/snps_accel/accel_rproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
#include <linux/cache.h>
#endif

#if IS_ENABLED(CONFIG_IOMMU_API)
#include <linux/iommu.h>
/* Enable ARC CBU IOMMU bypass so that IOVA equals physical address */
#define SNPS_ACCEL_RPROC_CBU_IOMMU_BYPASS
#endif

#include "accel_rproc.h"

static int snps_accel_rproc_prepare(struct rproc *rproc)
Expand Down Expand Up @@ -512,11 +518,55 @@ static int snps_accel_rproc_probe(struct platform_device *pdev)
return ret;
}

#if IS_ENABLED(CONFIG_IOMMU_API) && defined(SNPS_ACCEL_RPROC_CBU_IOMMU_BYPASS)
struct iommu_group *group = iommu_group_get(dev);
if (group) {
/* Allocate a new domain */
struct iommu_domain *domain = iommu_domain_alloc(dev->bus);
if (!domain) {
dev_err(dev, "Failed to allocate IOMMU domain\n");
iommu_group_put(group);
return -ENOMEM;
}

/* Configure allocated domain as an identity domain */
domain->type = IOMMU_DOMAIN_IDENTITY;

/* Attach domain to the device */
ret = iommu_attach_device(domain, dev);
if (ret) {
dev_err(dev, "Failed to attach device to identity domain, error %d\n", ret);
iommu_domain_free(domain);
iommu_group_put(group);
return ret;
}
dev_dbg(dev, "Attached to IOMMU identity domain\n");
iommu_group_put(group);
}
else {
dev_dbg(dev, "No IOMMU found for device\n");
}
#endif

return 0;
}

static int snps_accel_rproc_remove(struct platform_device *pdev)
{
#if IS_ENABLED(CONFIG_IOMMU_API) && defined(SNPS_ACCEL_RPROC_CBU_IOMMU_BYPASS)
struct device *dev = &pdev->dev;
struct iommu_group *group = iommu_group_get(dev);
if (group) {
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
/* Ensure that only the allocated domain is freed */
if (domain->type == IOMMU_DOMAIN_IDENTITY) {
iommu_detach_device(domain, dev);
iommu_domain_free(domain);
}
iommu_group_put(group);
}
#endif

return 0;
}

Expand Down