Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34c251e4 authored by Maya Erez's avatar Maya Erez
Browse files

msm_11ad: 11AD SMMU changes to allow enabling of SMMU stage1



Add the following changes to support enabling of SMMU stage1:
- Enable DMA coherency and PAGE_TABLE_FORCE_COHERENT attr
to allow cache coherency when SMMU stage1 is enabled
- Add the option to define SMMU base address and size in DT
- Add DT node flag to determine if stage1 is enabled

Change-Id: I38b0ee3d5c4bf533f91077ee69bd464dfdd358c8
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
parent 704099f3
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -10,6 +10,10 @@ Required properties:

- compatible: "qcom,wil6210"
- qcom,smmu-support: Boolean flag indicating whether PCIe has SMMU support
- qcom,smmu-s1-en: Boolean flag indicating whether SMMU stage1 should be enabled
- qcom,smmu-fast-map: Boolean flag indicating whether SMMU fast mapping should be enabled
- qcom,smmu-coherent: Boolean flag indicating SMMU dma and page table coherency
- qcom,smmu-mapping: specifies the base address and size of SMMU space
- qcom,pcie-parent: phandle for the PCIe root complex to which 11ad card is connected
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
  the below optional properties:
@@ -33,6 +37,10 @@ Example:
	wil6210: qcom,wil6210 {
		compatible = "qcom,wil6210";
		qcom,smmu-support;
		qcom,smmu-s1-en;
		qcom,smmu-fast-map;
		qcom,smmu-coherent;
		qcom,smmu-mapping = <0x20000000 0xe0000000>;
		qcom,pcie-parent = <&pcie1>;
		qcom,wigig-en = <&tlmm 94 0>;
		qcom,msm-bus,name = "wil6210";
+58 −17
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@
#define WIGIG_VENDOR (0x1ae9)
#define WIGIG_DEVICE (0x0310)

#define SMMU_BASE	0x10000000 /* Device address range base */
#define SMMU_BASE	0x20000000 /* Device address range base */
#define SMMU_SIZE	((SZ_1G * 4ULL) - SMMU_BASE)

#define WIGIG_ENABLE_DELAY	50
@@ -93,9 +93,12 @@ struct msm11ad_ctx {

	/* SMMU */
	bool use_smmu; /* have SMMU enabled? */
	int smmu_bypass;
	int smmu_s1_en;
	int smmu_fast_map;
	int smmu_coherent;
	struct dma_iommu_mapping *mapping;
	u32 smmu_base;
	u32 smmu_size;

	/* bus frequency scaling */
	struct msm_bus_scale_pdata *bus_scale;
@@ -638,15 +641,17 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
{
	int atomic_ctx = 1;
	int rc;
	int force_pt_coherent = 1;
	int smmu_bypass = !ctx->smmu_s1_en;

	if (!ctx->use_smmu)
		return 0;

	dev_info(ctx->dev, "Initialize SMMU, bypass = %d, fastmap = %d\n",
		 ctx->smmu_bypass, ctx->smmu_fast_map);
	dev_info(ctx->dev, "Initialize SMMU, bypass=%d, fastmap=%d, coherent=%d\n",
		 smmu_bypass, ctx->smmu_fast_map, ctx->smmu_coherent);

	ctx->mapping = arm_iommu_create_mapping(&platform_bus_type,
						SMMU_BASE, SMMU_SIZE);
						ctx->smmu_base, ctx->smmu_size);
	if (IS_ERR_OR_NULL(ctx->mapping)) {
		rc = PTR_ERR(ctx->mapping) ?: -ENODEV;
		dev_err(ctx->dev, "Failed to create IOMMU mapping (%d)\n", rc);
@@ -662,16 +667,31 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
		goto release_mapping;
	}

	if (ctx->smmu_bypass) {
	if (smmu_bypass) {
		rc = iommu_domain_set_attr(ctx->mapping->domain,
					   DOMAIN_ATTR_S1_BYPASS,
					   &ctx->smmu_bypass);
					   &smmu_bypass);
		if (rc) {
			dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n",
				rc);
			goto release_mapping;
		}
	} else if (ctx->smmu_fast_map) {
	} else {
		/* Set dma-coherent and page table coherency */
		if (ctx->smmu_coherent) {
			arch_setup_dma_ops(&ctx->pcidev->dev, 0, 0, NULL, true);
			rc = iommu_domain_set_attr(ctx->mapping->domain,
				   DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT,
				   &force_pt_coherent);
			if (rc) {
				dev_err(ctx->dev,
					"Set SMMU PAGE_TABLE_FORCE_COHERENT attr failed (%d)\n",
					rc);
				goto release_mapping;
			}
		}

		if (ctx->smmu_fast_map) {
			rc = iommu_domain_set_attr(ctx->mapping->domain,
						   DOMAIN_ATTR_FAST,
						   &ctx->smmu_fast_map);
@@ -681,6 +701,7 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
				goto release_mapping;
			}
		}
	}

	rc = arm_iommu_attach_device(&ctx->pcidev->dev, ctx->mapping);
	if (rc) {
@@ -900,6 +921,7 @@ static int msm_11ad_probe(struct platform_device *pdev)
	struct device_node *of_node = dev->of_node;
	struct device_node *rc_node;
	struct pci_dev *pcidev = NULL;
	u32 smmu_mapping[2];
	int rc;
	u32 val;

@@ -954,8 +976,27 @@ static int msm_11ad_probe(struct platform_device *pdev)
	ctx->use_smmu = of_property_read_bool(of_node, "qcom,smmu-support");
	ctx->bus_scale = msm_bus_cl_get_pdata(pdev);

	ctx->smmu_bypass = 1;
	ctx->smmu_fast_map = 0;
	ctx->smmu_s1_en = of_property_read_bool(of_node, "qcom,smmu-s1-en");
	if (ctx->smmu_s1_en) {
		ctx->smmu_fast_map = of_property_read_bool(
						of_node, "qcom,smmu-fast-map");
		ctx->smmu_coherent = of_property_read_bool(
						of_node, "qcom,smmu-coherent");
	}
	rc = of_property_read_u32_array(dev->of_node, "qcom,smmu-mapping",
			smmu_mapping, 2);
	if (rc) {
		dev_err(ctx->dev,
			"Failed to read base/size smmu addresses %d, fallback to default\n",
			rc);
		ctx->smmu_base = SMMU_BASE;
		ctx->smmu_size = SMMU_SIZE;
	} else {
		ctx->smmu_base = smmu_mapping[0];
		ctx->smmu_size = smmu_mapping[1];
	}
	dev_dbg(ctx->dev, "smmu_base=0x%x smmu_sise=0x%x\n",
		ctx->smmu_base, ctx->smmu_size);

	/*== execute ==*/
	/* turn device on */