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

Commit da4699fc 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: Handle global fault interrupt"

parents 57e372b0 c72c55c3
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -16,7 +16,13 @@ Optional properties:
- qcom,vdd-supply: Regulator needed to access IOMMU
- qcom,alt-vdd-supply : Alternative regulator needed to access IOMMU
  configuration registers.
- interrupts : should contain the performance monitor overflow interrupt number.
- interrupts : Interrupt numbers for permormance and global fault interrupts
- interrupt-names: Refers to the interrupts number mentioned above.
	"pmon" : the performance monitor overflow interrupt number
	"global_cfg_NS_irq" : the global config non-secure interrupt number
	"global_client_NS_irq" : the global client non-secure interrupt number
	"global_cfg_S_irq" : the global config secure interrupt number
	"global_client_S_irq" : the global client secure interrupt number
- qcom,iommu-enable-halt : Enable halt of the IOMMU before programming certain	19
  registers
- qcom,iommu-pmu-ngroups: Number of Performance Monitor Unit (PMU) groups.
+66 −11
Original line number Diff line number Diff line
@@ -18,7 +18,12 @@
		ranges;
		reg = <0xfda64000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 67 0>;
		interrupts = <0 67 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,needs-alt-core-clk;
		label = "jpeg_iommu";
		status = "disabled";
@@ -113,7 +118,12 @@
		ranges;
		reg = <0xfd928000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 73 0>;
		interrupts = <0 73 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,iommu-secure-id = <1>;
		label = "mdp_iommu";
		qcom,msm-bus,name = "mdp_ebi";
@@ -217,7 +227,12 @@
		reg = <0xfdc84000 0x10000
		       0xfdce0004 0x4>;
		reg-names = "iommu_base", "clk_base";
		interrupts = <0 45 0>;
		interrupts = <0 45 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,iommu-secure-id = <0>;
		qcom,needs-alt-core-clk;
		label = "venus_iommu";
@@ -333,7 +348,12 @@
		ranges;
		reg = <0xfdb10000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 38 0>;
		interrupts = <0 38 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		label = "kgsl_iommu";
		qcom,msm-bus,name = "kgsl_ebi";
		qcom,msm-bus,num-cases = <2>;
@@ -422,7 +442,12 @@
		ranges;
		reg = <0xfda44000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 62 0>;
		interrupts = <0 62 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,needs-alt-core-clk;
		label = "vfe_iommu";
		qcom,msm-bus,name = "vfe_ebi";
@@ -523,7 +548,12 @@
		ranges;
		reg = <0xf9bc4000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 153 0>;
		interrupts = <0 153 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,iommu-secure-id = <8>;
		label = "copss_iommu";
		qcom,msm-bus,name = "copss_ebi";
@@ -682,7 +712,12 @@
		ranges;
		reg = <0xfdee4000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 147 0>;
		interrupts = <0 147 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,iommu-secure-id = <7>;
		label = "vpu_iommu";
		qcom,msm-bus,name = "vpu_ebi";
@@ -815,7 +850,12 @@
		ranges;
		reg = <0xfe054000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 202 0>;
		interrupts = <0 202 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,iommu-secure-id = <2>;
		label = "lpass_qdsp_iommu";
		qcom,msm-bus,name = "lpass_qdsp_ebi";
@@ -943,7 +983,12 @@
		ranges;
		reg = <0xfe064000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 166 0>;
		interrupts = <0 166 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,iommu-secure-id = <6>;
		label = "lpass_core_iommu";
		qcom,msm-bus,name = "lpass_core_ebi";
@@ -1063,7 +1108,12 @@
		ranges;
		reg = <0xfdfb6000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 315 0>;
		interrupts = <0 315 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,needs-alt-core-clk;
		label = "vcap_iommu";
		status = "disabled";
@@ -1156,7 +1206,12 @@
		ranges;
		reg = <0xfc734000 0x10000>;
		reg-names = "iommu_base";
		interrupts = <0 279 0>;
		interrupts = <0 279 0>,
				<0 229 0>, <0 231 0>,
				<0 230 0>, <0 232 0>;
		interrupt-names = "pmon",
				"global_cfg_NS_irq", "global_client_NS_irq",
				"global_cfg_S_irq", "global_client_S_irq";
		qcom,needs-alt-core-clk;
		label = "bcast_iommu";
		status = "disabled";
+1 −0
Original line number Diff line number Diff line
@@ -236,6 +236,7 @@ void print_ctx_regs(struct msm_iommu_context_reg regs[]);
 * interrupt is not supported in the API yet, but this will print an error
 * message and dump useful IOMMU registers.
 */
irqreturn_t msm_iommu_global_fault_handler(int irq, void *dev_id);
irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id);
irqreturn_t msm_iommu_secure_fault_handler_v2(int irq, void *dev_id);
+69 −0
Original line number Diff line number Diff line
@@ -1026,6 +1026,75 @@ static void __print_ctx_regs(void __iomem *base, int ctx, unsigned int fsr)
	print_ctx_regs(regs);
}

static void print_global_regs(void __iomem *base, unsigned int gfsr)
{
	pr_err("GFAR    = %016llx\n", GET_GFAR(base));

	pr_err("GFSR    = %08x [%s%s%s%s%s%s%s%s%s%s]\n", gfsr,
			(gfsr & 0x01) ? "ICF " : "",
			(gfsr & 0x02) ? "USF " : "",
			(gfsr & 0x04) ? "SMCF " : "",
			(gfsr & 0x08) ? "UCBF " : "",
			(gfsr & 0x10) ? "UCIF " : "",
			(gfsr & 0x20) ? "CAF " : "",
			(gfsr & 0x40) ? "EF " : "",
			(gfsr & 0x80) ? "PF " : "",
			(gfsr & 0x40000000) ? "SS " : "",
			(gfsr & 0x80000000) ? "MULTI " : "");

	pr_err("GFSYNR0	= %08x\n", GET_GFSYNR0(base));
	pr_err("GFSYNR1	= %08x\n", GET_GFSYNR1(base));
	pr_err("GFSYNR2	= %08x\n", GET_GFSYNR2(base));
}

irqreturn_t msm_iommu_global_fault_handler(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct msm_iommu_drvdata *drvdata;
	unsigned int gfsr;
	int ret;

	mutex_lock(&msm_iommu_lock);
	BUG_ON(!pdev);

	drvdata = dev_get_drvdata(&pdev->dev);
	BUG_ON(!drvdata);

	if (!drvdata->ctx_attach_count) {
		pr_err("Unexpected IOMMU global fault !!\n");
		pr_err("name = %s\n", drvdata->name);
		pr_err("Power is OFF. Can't read global fault information\n");
		ret = IRQ_HANDLED;
		goto fail;
	}

	if (drvdata->sec_id != -1) {
		pr_err("NON-secure interrupt from secure %s\n", drvdata->name);
		ret = IRQ_HANDLED;
		goto fail;
	}

	ret = __enable_clocks(drvdata);
	if (ret) {
		ret = IRQ_NONE;
		goto fail;
	}

	gfsr = GET_GFSR(drvdata->base);
	if (gfsr) {
		pr_err("Unexpected %s global fault !!\n", drvdata->name);
		print_global_regs(drvdata->base, gfsr);
		SET_GFSR(drvdata->base, gfsr);
		ret = IRQ_HANDLED;
	} else
		ret = IRQ_NONE;

	__disable_clocks(drvdata);
fail:
	mutex_unlock(&msm_iommu_lock);
	return ret;
}

irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
+30 −0
Original line number Diff line number Diff line
@@ -282,6 +282,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
	struct msm_iommu_drvdata *drvdata;
	struct resource *r;
	int ret, needs_alt_core_clk;
	int global_cfg_irq, global_client_irq;

	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
@@ -368,6 +369,35 @@ static int msm_iommu_probe(struct platform_device *pdev)
			}
		}
	}

	global_cfg_irq =
		platform_get_irq_byname(pdev, "global_cfg_NS_irq");
	if (global_cfg_irq > 0) {
		ret = devm_request_threaded_irq(&pdev->dev, global_cfg_irq,
				NULL,
				msm_iommu_global_fault_handler,
				IRQF_ONESHOT | IRQF_SHARED |
				IRQF_TRIGGER_RISING,
				"msm_iommu_global_cfg_irq", pdev);
		if (ret < 0)
			pr_err("Request Global CFG IRQ %d failed with ret=%d\n",
					global_cfg_irq, ret);
	}

	global_client_irq =
		platform_get_irq_byname(pdev, "global_client_NS_irq");
	if (global_client_irq > 0) {
		ret = devm_request_threaded_irq(&pdev->dev, global_client_irq,
				NULL,
				msm_iommu_global_fault_handler,
				IRQF_ONESHOT | IRQF_SHARED |
				IRQF_TRIGGER_RISING,
				"msm_iommu_global_client_irq", pdev);
		if (ret < 0)
			pr_err("Request Global Client IRQ %d failed with ret=%d\n",
					global_client_irq, ret);
	}

	return 0;
}