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

Commit 03ccedbc authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu: msm: Calculate context bank base address"

parents 65ee3c33 3f4f0ee3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ Optional properties:
- qcom,iommu-pmu-event-classes: List of event classes supported.
- Bus scaling properties: See msm_bus.txt
- qcom,no-atos-support: boolean indicating that IOMMU doesn't have ATS support
- qcom,cb-base-offset: context bank 0's base address from global base address

- List of sub nodes, one for each of the translation context banks supported.
  Each sub node has the following required properties:
+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct msm_iommu_bfb_settings {
struct msm_iommu_drvdata {
	void __iomem *base;
	void __iomem *glb_base;
	void __iomem *cb_base;
	int ncb;
	int ttbr_split;
	struct clk *clk;
+8 −9
Original line number Diff line number Diff line
@@ -14,14 +14,13 @@
#define __ARCH_ARM_MACH_MSM_IOMMU_HW_V2_H

#define CTX_SHIFT  12
#define CTX_OFFSET 0x8000

#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_GLOBAL_REG_Q(reg, base) (readq_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \
	(readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
	(readl_relaxed((base) + (reg) + ((ctx) << CTX_SHIFT)))
#define GET_CTX_REG_Q(reg, base, ctx) \
	(readq_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
	(readq_relaxed((base) + (reg) + ((ctx) << CTX_SHIFT)))

#define SET_GLOBAL_REG(reg, base, val)	writel_relaxed((val), ((base) + (reg)))
#define SET_GLOBAL_REG_Q(reg, base, val) \
@@ -29,10 +28,10 @@

#define SET_CTX_REG(reg, base, ctx, val) \
	writel_relaxed((val), \
		((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
		((base) + (reg) + ((ctx) << CTX_SHIFT)))
#define SET_CTX_REG_Q(reg, base, ctx, val) \
	writeq_relaxed((val), \
		((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
		((base) + (reg) + ((ctx) << CTX_SHIFT)))

/* Wrappers for numbered registers */
#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG((b), ((r) + (n << 2)), (v))
@@ -42,19 +41,19 @@
#define GET_GLOBAL_FIELD(b, r, F) \
	GET_FIELD(((b) + (r)), r##_##F##_MASK, r##_##F##_SHIFT)
#define GET_CONTEXT_FIELD(b, c, r, F) \
	GET_FIELD(((b) + CTX_OFFSET + (r) + ((c) << CTX_SHIFT)), \
	GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), \
			r##_##F##_MASK, r##_##F##_SHIFT)
#define GET_CONTEXT_FIELD_Q(b, c, r, F) \
	GET_FIELD_Q(((b) + CTX_OFFSET + (r) + ((c) << CTX_SHIFT)), \
	GET_FIELD_Q(((b) + (r) + ((c) << CTX_SHIFT)), \
			r##_##F##_MASK, r##_##F##_SHIFT)

#define SET_GLOBAL_FIELD(b, r, F, v) \
	SET_FIELD(((b) + (r)), r##_##F##_MASK, r##_##F##_SHIFT, (v))
#define SET_CONTEXT_FIELD(b, c, r, F, v) \
	SET_FIELD(((b) + CTX_OFFSET + (r) + ((c) << CTX_SHIFT)), \
	SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), \
			r##_##F##_MASK, r##_##F##_SHIFT, (v))
#define SET_CONTEXT_FIELD_Q(b, c, r, F, v) \
	SET_FIELD_Q(((b) + CTX_OFFSET + (r) + ((c) << CTX_SHIFT)), \
	SET_FIELD_Q(((b) + (r) + ((c) << CTX_SHIFT)), \
			r##_##F##_MASK, r##_##F##_SHIFT, (v))

/* Wrappers for numbered field registers */
+27 −24
Original line number Diff line number Diff line
@@ -239,10 +239,10 @@ static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
		if (ret)
			goto fail;

		SET_TLBIVA(iommu_drvdata->base, ctx_drvdata->num,
		SET_TLBIVA(iommu_drvdata->cb_base, ctx_drvdata->num,
			   ctx_drvdata->asid | (va & CB_TLBIVA_VA));
		mb();
		__sync_tlb(iommu_drvdata->base, ctx_drvdata->num);
		__sync_tlb(iommu_drvdata->cb_base, ctx_drvdata->num);
		__disable_clocks(iommu_drvdata);
	}
fail:
@@ -266,10 +266,10 @@ static int __flush_iotlb(struct iommu_domain *domain)
		if (ret)
			goto fail;

		SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
		SET_TLBIASID(iommu_drvdata->cb_base, ctx_drvdata->num,
			     ctx_drvdata->asid);
		mb();
		__sync_tlb(iommu_drvdata->base, ctx_drvdata->num);
		__sync_tlb(iommu_drvdata->cb_base, ctx_drvdata->num);
		__disable_clocks(iommu_drvdata);
	}

@@ -410,7 +410,7 @@ static void msm_iommu_assign_ASID(const struct msm_iommu_drvdata *iommu_drvdata,
				  struct msm_iommu_priv *priv)
{
	unsigned int found = 0;
	void __iomem *base = iommu_drvdata->base;
	void __iomem *cb_base = iommu_drvdata->cb_base;
	unsigned int i;
	unsigned int ncb = iommu_drvdata->ncb;
	struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -438,7 +438,7 @@ static void msm_iommu_assign_ASID(const struct msm_iommu_drvdata *iommu_drvdata,
		BUG_ON(!found);
	}

	msm_iommu_set_ASID(base, curr_ctx->num, curr_ctx->asid);
	msm_iommu_set_ASID(cb_base, curr_ctx->num, curr_ctx->asid);
}

#ifdef CONFIG_IOMMU_LPAE
@@ -542,30 +542,31 @@ static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
{
	phys_addr_t pn;
	void __iomem *base = iommu_drvdata->base;
	void __iomem *cb_base = iommu_drvdata->cb_base;
	unsigned int ctx = ctx_drvdata->num;
	phys_addr_t pgtable = __pa(priv->pt.fl_table);

	__reset_context(base, ctx);
	msm_iommu_setup_ctx(base, ctx);
	__reset_context(cb_base, ctx);
	msm_iommu_setup_ctx(cb_base, ctx);

	if (priv->pt.redirect)
		msm_iommu_setup_pg_l2_redirect(base, ctx);
		msm_iommu_setup_pg_l2_redirect(cb_base, ctx);

	msm_iommu_setup_memory_remap(base, ctx);
	msm_iommu_setup_memory_remap(cb_base, ctx);

	pn = pgtable >> CB_TTBR0_ADDR_SHIFT;
	SET_CB_TTBR0_ADDR(base, ctx, pn);
	SET_CB_TTBR0_ADDR(cb_base, ctx, pn);

	/* Enable context fault interrupt */
	SET_CB_SCTLR_CFIE(base, ctx, 1);
	SET_CB_SCTLR_CFIE(cb_base, ctx, 1);

	/* Redirect all cacheable requests to L2 slave port. */
	SET_CB_ACTLR_BPRCISH(base, ctx, 1);
	SET_CB_ACTLR_BPRCOSH(base, ctx, 1);
	SET_CB_ACTLR_BPRCNSH(base, ctx, 1);
	SET_CB_ACTLR_BPRCISH(cb_base, ctx, 1);
	SET_CB_ACTLR_BPRCOSH(cb_base, ctx, 1);
	SET_CB_ACTLR_BPRCNSH(cb_base, ctx, 1);

	/* Enable private ASID namespace */
	SET_CB_SCTLR_ASIDPNE(base, ctx, 1);
	SET_CB_SCTLR_ASIDPNE(cb_base, ctx, 1);

	if (!is_secure) {
		if (program_m2v)
@@ -593,7 +594,7 @@ static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
	msm_iommu_assign_ASID(iommu_drvdata, ctx_drvdata, priv);

	/* Enable the MMU */
	SET_CB_SCTLR_M(base, ctx, 1);
	SET_CB_SCTLR_M(cb_base, ctx, 1);
	mb();
}

@@ -768,7 +769,8 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,

	is_secure = iommu_drvdata->sec_id != -1;

	SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, ctx_drvdata->asid);
	SET_TLBIASID(iommu_drvdata->cb_base, ctx_drvdata->num,
					ctx_drvdata->asid);

	BUG_ON(iommu_drvdata->asid[ctx_drvdata->asid - 1] == 0);
	iommu_drvdata->asid[ctx_drvdata->asid - 1]--;
@@ -776,7 +778,7 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,

	iommu_halt(iommu_drvdata);

	__reset_context(iommu_drvdata->base, ctx_drvdata->num);
	__reset_context(iommu_drvdata->cb_base, ctx_drvdata->num);

	/*
	 * Only reset the M2V tables on the very last detach */
@@ -940,7 +942,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
		return ret;
	}

	base = iommu_drvdata->base;
	base = iommu_drvdata->cb_base;
	ctx = ctx_drvdata->num;

	ret = __enable_clocks(iommu_drvdata);
@@ -1180,7 +1182,7 @@ irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
		goto fail;
	}

	fsr = GET_FSR(drvdata->base, ctx_drvdata->num);
	fsr = GET_FSR(drvdata->cb_base, ctx_drvdata->num);
	if (fsr) {
		if (!ctx_drvdata->attached_domain) {
			pr_err("Bad domain in interrupt handler\n");
@@ -1188,7 +1190,7 @@ irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
		} else
			ret = report_iommu_fault(ctx_drvdata->attached_domain,
				&ctx_drvdata->pdev->dev,
				GET_FAR(drvdata->base, ctx_drvdata->num), 0);
				GET_FAR(drvdata->cb_base, ctx_drvdata->num), 0);

		if (ret == -ENOSYS) {
			pr_err("Unexpected IOMMU page fault!\n");
@@ -1196,11 +1198,12 @@ irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
			pr_err("context = %s (%d)\n", ctx_drvdata->name,
							ctx_drvdata->num);
			pr_err("Interesting registers:\n");
			__print_ctx_regs(drvdata->base, ctx_drvdata->num, fsr);
			__print_ctx_regs(drvdata->cb_base,
					ctx_drvdata->num, fsr);
		}

		if (ret != -EBUSY)
			SET_FSR(drvdata->base, ctx_drvdata->num, fsr);
			SET_FSR(drvdata->cb_base, ctx_drvdata->num, fsr);
		ret = IRQ_HANDLED;
	} else
		ret = IRQ_NONE;
+18 −5
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
	struct resource *r;
	int ret, needs_alt_core_clk, needs_alt_iface_clk;
	int global_cfg_irq, global_client_irq;
	u32 temp;

	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
@@ -343,6 +344,13 @@ static int msm_iommu_probe(struct platform_device *pdev)
	drvdata->no_atos_support = of_property_read_bool(pdev->dev.of_node,
						"qcom,no-atos-support");

	if (!of_property_read_u32(pdev->dev.of_node,
				"qcom,cb-base-offset",
				&temp))
		drvdata->cb_base = drvdata->base + temp;
	else
		drvdata->cb_base = drvdata->base + 0x8000;

	if (clk_get_rate(drvdata->clk) == 0) {
		ret = clk_round_rate(drvdata->clk, 1000);
		clk_set_rate(drvdata->clk, ret);
@@ -442,7 +450,9 @@ static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
{
	struct resource *r, rp;
	int irq = 0, ret = 0;
	struct msm_iommu_drvdata *drvdata;
	u32 nsid;
	unsigned long cb_offset;

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

@@ -484,12 +494,15 @@ static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
	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.
	/* 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.
	 */
	ctx_drvdata->num = ((r->start - rp.start) >> CTX_SHIFT) - 8;
	drvdata = dev_get_drvdata(pdev->dev.parent);
	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))