static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
				struct msm_iommu_ctx_drvdata *ctx_drvdata)
{
	struct resource *r, rp;
	int irq = 0, ret = 0;
	u32 nsid;

	get_secure_ctx(pdev->dev.of_node, ctx_drvdata);

	if (ctx_drvdata->secure_context) {
		irq = platform_get_irq(pdev, 1);
		if (irq > 0) {
			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
					msm_iommu_secure_fault_handler_v2,
					IRQF_ONESHOT | IRQF_SHARED,
					"msm_iommu_secure_irq", pdev);
			if (ret) {
				pr_err("Request IRQ %d failed with ret=%d\n",
					irq, ret);
				return ret;
			}
		}
	} else {
		irq = platform_get_irq(pdev, 0);
		if (irq > 0) {
			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
					msm_iommu_fault_handler_v2,
					IRQF_ONESHOT | IRQF_SHARED,
					"msm_iommu_nonsecure_irq", pdev);
			if (ret) {
				pr_err("Request IRQ %d failed with ret=%d\n",
					irq, ret);
				goto out;
			}
		}
	}

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r) {
		ret = -EINVAL;
		goto out;
	}

	ret = of_address_to_resource(pdev->dev.parent->of_node, 0, &rp);
	if (ret)
		goto out;

	/* Calculate the context bank number using the base addresses. The
	 * first 8 pages belong to the global address space which is followed
	 * by the context banks, hence subtract by 8 to get the context bank
	 * number.
	 */
	ctx_drvdata->num = ((r->start - rp.start) >> CTX_SHIFT) - 8;

	if (of_property_read_string(pdev->dev.of_node, "label",
					&ctx_drvdata->name))
		ctx_drvdata->name = dev_name(&pdev->dev);

	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid)) {
		ret = -EINVAL;
		goto out;
	}
	if (nsid >= sizeof(ctx_drvdata->sids)) {
		ret = -EINVAL;
		goto out;
	}

	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
				       ctx_drvdata->sids,
				       nsid / sizeof(*ctx_drvdata->sids))) {
		ret = -EINVAL;
		goto out;
	}
	ctx_drvdata->nsid = nsid;

	ctx_drvdata->asid = -1;
out:
	return ret;
}
Ejemplo n.º 2
0
static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
				struct msm_iommu_ctx_drvdata *ctx_drvdata)
{
	struct resource *r, rp;
	int irq = 0, ret = 0;
	struct msm_iommu_drvdata *drvdata;
	u32 nsid;
	unsigned long cb_offset;

	drvdata = dev_get_drvdata(pdev->dev.parent);

	get_secure_ctx(pdev->dev.of_node, drvdata, ctx_drvdata);

	if (ctx_drvdata->secure_context) {
		irq = platform_get_irq(pdev, 1);
		if (irq > 0) {
			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
					msm_iommu_secure_fault_handler_v2,
					IRQF_ONESHOT | IRQF_SHARED,
					"msm_iommu_secure_irq", pdev);
			if (ret) {
				pr_err("Request IRQ %d failed with ret=%d\n",
					irq, ret);
				return ret;
			}
		}
	} else {
		irq = platform_get_irq(pdev, 0);
		if (irq > 0) {
			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
					msm_iommu_fault_handler_v2,
					IRQF_ONESHOT | IRQF_SHARED,
					"msm_iommu_nonsecure_irq", pdev);
			if (ret) {
				pr_err("Request IRQ %d failed with ret=%d\n",
					irq, ret);
				goto out;
			}
		}
	}

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r) {
		ret = -EINVAL;
		goto out;
	}

	ret = of_address_to_resource(pdev->dev.parent->of_node, 0, &rp);
	if (ret)
		goto out;

	/* Calculate the context bank number using the base addresses.
	 * Typically CB0 base address is 0x8000 pages away if the number
	 * of CBs are <=8. So, assume the offset 0x8000 until mentioned
	 * explicitely.
	 */
	cb_offset = drvdata->cb_base - drvdata->base;
	ctx_drvdata->num = ((r->start - rp.start - cb_offset)
					>> CTX_SHIFT);

	if (of_property_read_string(pdev->dev.of_node, "label",
					&ctx_drvdata->name))
		ctx_drvdata->name = dev_name(&pdev->dev);

	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid)) {
		ret = -EINVAL;
		goto out;
	}
	if (nsid >= sizeof(ctx_drvdata->sids)) {
		ret = -EINVAL;
		goto out;
	}

	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
				       ctx_drvdata->sids,
				       nsid / sizeof(*ctx_drvdata->sids))) {
		ret = -EINVAL;
		goto out;
	}
	ctx_drvdata->nsid = nsid;

	ctx_drvdata->asid = -1;
out:
	return ret;
}
static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
				struct msm_iommu_ctx_drvdata *ctx_drvdata)
{
	struct resource *r, rp;
	int irq = 0, ret = 0;
	struct msm_iommu_drvdata *drvdata;
	u32 nsid;
	u32 n_sid_mask;
	unsigned long cb_offset;

	drvdata = dev_get_drvdata(pdev->dev.parent);

	get_secure_ctx(pdev->dev.of_node, drvdata, ctx_drvdata);

	if (drvdata->sec_id != -1) {
		irq = platform_get_irq(pdev, 1);

		/*
		 * This is for supporting old DTs where it was assumed
		 * that interrupt 0 is only required as their CB is
		 * non-secure.
		 */
		if (irq < 0)
			irq = platform_get_irq(pdev, 0);

		if (irq > 0) {
			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
					msm_iommu_secure_fault_handler_v2,
					IRQF_ONESHOT | IRQF_SHARED,
					"msm_iommu_secure_irq", pdev);
			if (ret) {
				pr_err("Request IRQ %d failed with ret=%d\n",
					irq, ret);
				return ret;
			}
		}
	} else {
		irq = platform_get_irq(pdev, 0);
		if (irq > 0) {
			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
					msm_iommu_fault_handler_v2,
					IRQF_ONESHOT | IRQF_SHARED,
					"msm_iommu_nonsecure_irq", pdev);
			if (ret) {
				pr_err("Request IRQ %d failed with ret=%d\n",
					irq, ret);
				goto out;
			}
		}
	}

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r) {
		ret = -EINVAL;
		goto out;
	}

	ret = of_address_to_resource(pdev->dev.parent->of_node, 0, &rp);
	if (ret)
		goto out;

	/* Calculate the context bank number using the base addresses.
	 * Typically CB0 base address is 0x8000 pages away if the number
	 * of CBs are <=8. So, assume the offset 0x8000 until mentioned
	 * explicitely.
	 */
	cb_offset = drvdata->cb_base - drvdata->base;
	ctx_drvdata->num = ((r->start - rp.start - cb_offset)
					>> CTX_SHIFT);

	if (of_property_read_string(pdev->dev.of_node, "label",
					&ctx_drvdata->name))
		ctx_drvdata->name = dev_name(&pdev->dev);

	ctx_drvdata->report_error_on_fault =
		of_property_read_bool(pdev->dev.of_node,
				"qcom,report-error-on-fault");

	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid)) {
		ret = -EINVAL;
		goto out;
	}
	if (nsid >= sizeof(ctx_drvdata->sids)) {
		ret = -EINVAL;
		goto out;
	}

	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
				       ctx_drvdata->sids,
				       nsid / sizeof(*ctx_drvdata->sids))) {
		ret = -EINVAL;
		goto out;
	}
	ctx_drvdata->nsid = nsid;

	ctx_drvdata->asid = -1;

	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-sid-mask",
						&n_sid_mask)) {
		memset(ctx_drvdata->sid_mask, 0, MAX_NUM_SMR);
		goto out;
	}

	if (n_sid_mask != nsid) {
		ret = -EINVAL;
		goto out;
	}

	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-sid-mask",
				ctx_drvdata->sid_mask,
				n_sid_mask / sizeof(*ctx_drvdata->sid_mask))) {
		ret = -EINVAL;
		goto out;
	}
	ctx_drvdata->n_sid_mask = n_sid_mask;

out:
	return ret;
}