Skip to contentSkip to conversation

pinctrl: qcom: use scm_call to route GPIO irq to Apps

PATCH Superseded Ansuel Smith 2 participants 4 messages Mar 26, 2020 – Mar 27, 2020

Subsystems (5)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 pinctrl: qcom: use scm_call to route GPIO irq to Apps

From: Ajay Kishore <[email protected]>

For IPQ806x targets, TZ protects the registers that are used to configure the routing of interrupts to a target processor. To resolve this, this patch uses scm call to route GPIO interrupts to application processor. Also the scm call interface is changed.

---
v2:
* Move static varibale in msm_pinctrl struct
* Revert '4b024225c4a8 ("pinctrl: use devm_platform_ioremap_resource() to simplify code")' to get base_reg addr

 drivers/pinctrl/qcom/pinctrl-msm.c | 37 ++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 5 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +32 -5
index 9a8daa256a32..9627ebd41ff9 100644
@@ -22,6 +22,8 @@
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/log2.h>
+#include <linux/qcom_scm.h>
+#include <linux/io.h>
 
 #include <linux/soc/qcom/irq.h>
 
@@ -60,6 +62,9 @@ struct msm_pinctrl {
 	struct irq_chip irq_chip;
 	int irq;
 
+	int route_to_apps;
+	u32 base_reg;
+
 	raw_spinlock_t lock;
 
 	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
@@ -883,10 +888,27 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
 
 	/* Route interrupts to application cpu */
-	val = msm_readl_intr_target(pctrl, g);
-	val &= ~(7 << g->intr_target_bit);
-	val |= g->intr_target_kpss_val << g->intr_target_bit;
-	msm_writel_intr_target(val, pctrl, g);
+	if (pctrl->route_to_apps && pctrl->base_reg) {
+		u32 addr = pctrl->base_reg + g->intr_target_reg;
+		int ret;
+
+		qcom_scm_io_readl(addr, &val);
+
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+
+		ret = qcom_scm_io_writel(addr, val);
+		if (ret)
+			dev_err(pctrl->dev,
+				"Failed routing %lu interrupt to Apps proc",
+				d->hwirq);
+		}
+	} else {
+		val = msm_readl_intr_target(pctrl, g);
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+		msm_writel_intr_target(val, pctrl, g);
+	}
 
 	/* Update configuration for gpio.
 	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
@@ -1241,6 +1263,8 @@ int msm_pinctrl_probe(struct platform_device *pdev,
 	pctrl->dev = &pdev->dev;
 	pctrl->soc = soc_data;
 	pctrl->chip = msm_gpio_template;
+	pctrl->route_to_apps = of_device_is_compatible(pctrl->dev->of_node,
+					"qcom,ipq8064-pinctrl");
 
 	raw_spin_lock_init(&pctrl->lock);
 
@@ -1253,9 +1277,12 @@ int msm_pinctrl_probe(struct platform_device *pdev,
 				return PTR_ERR(pctrl->regs[i]);
 		}
 	} else {
-		pctrl->regs[0] = devm_platform_ioremap_resource(pdev, 0);
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR(pctrl->regs[0]))
 			return PTR_ERR(pctrl->regs[0]);
+		else
+			pctrl->base_reg = res->start;
 	}
 
 	msm_pinctrl_setup_pm_reset(pctrl);
Signature · 1 line
2.25.1
#1 lore raw
Quoted 9 lines · Ansuel Smith

From: Ajay Kishore <[email protected]>

For IPQ806x targets, TZ protects the registers that are used to configure the routing of interrupts to a target processor. To resolve this, this patch uses scm call to route GPIO interrupts to application processor. Also the scm call interface is changed.

Thanks for respinning this Ansuel, just some minor things below.

Quoted 23 lines

---
v2:
* Move static varibale in msm_pinctrl struct
* Revert '4b024225c4a8 ("pinctrl: use devm_platform_ioremap_resource() to simplify code")' to get base_reg addr

 drivers/pinctrl/qcom/pinctrl-msm.c | 37 ++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 5 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +2 -0
index 9a8daa256a32..9627ebd41ff9 100644
@@ -22,6 +22,8 @@
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/log2.h>
+#include <linux/qcom_scm.h>
+#include <linux/io.h>
 
 #include <linux/soc/qcom/irq.h>
 

drivers/pinctrl/qcom/pinctrl-msm.c struct msm_pinctrl { · line 65

Quoted 4 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
@@ -60,6 +62,9 @@ struct msm_pinctrl {
 	struct irq_chip irq_chip;
 	int irq;
 
+	int route_to_apps;

We "always" route our interrupts to apps, so please rename this to intr_target_use_scm. And using "bool" instead would make it clear that this is a binary flag.

drivers/pinctrl/qcom/pinctrl-msm.c struct msm_pinctrl { · line 66

Quoted 1 line
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+	u32 base_reg;

Even though I think it's fine that you only fill in the first entry, please make this phys_base[MAX_NR_GPIO]; next to regs.

drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) · line 891

Quoted 13 lines
drivers/pinctrl/qcom/pinctrl-msm.c +2 -4
+
 	raw_spinlock_t lock;
 
 	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
@@ -883,10 +888,27 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
 
 	/* Route interrupts to application cpu */
-	val = msm_readl_intr_target(pctrl, g);
-	val &= ~(7 << g->intr_target_bit);
-	val |= g->intr_target_kpss_val << g->intr_target_bit;
-	msm_writel_intr_target(val, pctrl, g);
+	if (pctrl->route_to_apps && pctrl->base_reg) {

I meant that you could fill out "base_reg" only if it's supposed to be used, but looking at your patch I think it's nicer to have a separate flag - so you can omit the check for base_reg != NULL here.

Quoted 33 lines
drivers/pinctrl/qcom/pinctrl-msm.c +22 -0
+		u32 addr = pctrl->base_reg + g->intr_target_reg;
+		int ret;
+
+		qcom_scm_io_readl(addr, &val);
+
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+
+		ret = qcom_scm_io_writel(addr, val);
+		if (ret)
+			dev_err(pctrl->dev,
+				"Failed routing %lu interrupt to Apps proc",
+				d->hwirq);
+		}
+	} else {
+		val = msm_readl_intr_target(pctrl, g);
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+		msm_writel_intr_target(val, pctrl, g);
+	}
 
 	/* Update configuration for gpio.
 	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
@@ -1241,6 +1263,8 @@ int msm_pinctrl_probe(struct platform_device *pdev,
 	pctrl->dev = &pdev->dev;
 	pctrl->soc = soc_data;
 	pctrl->chip = msm_gpio_template;
+	pctrl->route_to_apps = of_device_is_compatible(pctrl->dev->of_node,
+					"qcom,ipq8064-pinctrl");
 
 	raw_spin_lock_init(&pctrl->lock);
 

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct platform_device *pdev, · line 1284

Quoted 9 lines
drivers/pinctrl/qcom/pinctrl-msm.c +3 -1
@@ -1253,9 +1277,12 @@ int msm_pinctrl_probe(struct platform_device *pdev,
 				return PTR_ERR(pctrl->regs[i]);
 		}
 	} else {
-		pctrl->regs[0] = devm_platform_ioremap_resource(pdev, 0);
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR(pctrl->regs[0]))
 			return PTR_ERR(pctrl->regs[0]);
+		else

No need for the else, as the "positive" case is a return.

Thank you,
Bjorn

Quoted 7 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+			pctrl->base_reg = res->start;
 	}
 
 	msm_pinctrl_setup_pm_reset(pctrl);
Signature · 1 line
2.25.1
#2 lore raw

R: [PATCH v2] pinctrl: qcom: use scm_call to route GPIO irq to Apps

Quoted 43 lines · Ansuel Smith
Quoted 10 lines

From: Ajay Kishore <[email protected]>

For IPQ806x targets, TZ protects the registers that are used to configure the routing of interrupts to a target processor. To resolve this, this patch uses scm call to route GPIO interrupts to application processor. Also the scm call interface is changed.

Thanks for respinning this Ansuel, just some minor things below.

Quoted 4 lines

---
v2:
* Move static varibale in msm_pinctrl struct
* Revert '4b024225c4a8 ("pinctrl: use

devm_platform_ioremap_resource() to simplify code")'

Quoted 3 lines

to get base_reg addr

 drivers/pinctrl/qcom/pinctrl-msm.c | 37

++++++++++++++++++++++++++----

Review

Quoted 3 lines
 1 file changed, 32 insertions(+), 5 deletions(-)
(quoted diff) +0 -0

b/drivers/pinctrl/qcom/pinctrl-msm.c

Quoted 16 lines

index 9a8daa256a32..9627ebd41ff9 100644

drivers/pinctrl/qcom/pinctrl-msm.c +2 -0
@@ -22,6 +22,8 @@
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/log2.h>
+#include <linux/qcom_scm.h>
+#include <linux/io.h>
 
 #include <linux/soc/qcom/irq.h>
 
@@ -60,6 +62,9 @@ struct msm_pinctrl {
 	struct irq_chip irq_chip;
 	int irq;
 
Quoted 6 lines

drivers/pinctrl/qcom/pinctrl-msm.c struct msm_pinctrl { · line 65

Quoted 1 line
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+	int route_to_apps;

We "always" route our interrupts to apps, so please rename this to intr_target_use_scm. And using "bool" instead would make it clear that this is a binary flag.

Will fix in v3

Quoted 5 lines

drivers/pinctrl/qcom/pinctrl-msm.c struct msm_pinctrl { · line 66

Quoted 1 line
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+	u32 base_reg;

Even though I think it's fine that you only fill in the first entry, please make this phys_base[MAX_NR_GPIO]; next to regs.

If I understand correctly, I should replace base_reg with phys_base[MAX_NR_GPIO]
I think we should use MAX_NR_TILES instead of MAX_NR_GPIO Wouldn't this be a waste of memory since only the base_reg will be needed? I don't think there will be a soc with multiple tiles and the need to add code
in the loop function. (Also sorry for off-topic... since we have soc_data->ntiles
why don't we use kmem allocation instead of statically use half empty array?)

Quoted 8 lines

drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_irq_set_type(struct

Quoted 5 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+
 	raw_spinlock_t lock;
 
 	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
@@ -883,10 +888,27 @@ static int msm_gpio_irq_set_type(struct

irq_data *d, unsigned int type)

Quoted 2 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0 -0
 		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
 
Quoted 11 lines

drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) · line 891

Quoted 6 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -4
 	/* Route interrupts to application cpu */
-	val = msm_readl_intr_target(pctrl, g);
-	val &= ~(7 << g->intr_target_bit);
-	val |= g->intr_target_kpss_val << g->intr_target_bit;
-	msm_writel_intr_target(val, pctrl, g);
+	if (pctrl->route_to_apps && pctrl->base_reg) {

I meant that you could fill out "base_reg" only if it's supposed to be used, but looking at your patch I think it's nicer to have a separate flag - so you can omit the check for base_reg != NULL here.

Since we return error if devm_ioremap_resource fails, it is good to only check
the route_to_apps as base_reg will be set for sure?

Quoted 36 lines

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct platform_device

Quoted 24 lines
drivers/pinctrl/qcom/pinctrl-msm.c +20 -0
+		u32 addr = pctrl->base_reg + g->intr_target_reg;
+		int ret;
+
+		qcom_scm_io_readl(addr, &val);
+
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+
+		ret = qcom_scm_io_writel(addr, val);
+		if (ret)
+			dev_err(pctrl->dev,
+				"Failed routing %lu interrupt to Apps proc",
+				d->hwirq);
+		}
+	} else {
+		val = msm_readl_intr_target(pctrl, g);
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+		msm_writel_intr_target(val, pctrl, g);
+	}
 
 	/* Update configuration for gpio.
 	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
@@ -1241,6 +1263,8 @@ int msm_pinctrl_probe(struct platform_device

*pdev,

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct

Quoted 10 lines
drivers/pinctrl/qcom/pinctrl-msm.c +2 -0
 	pctrl->dev = &pdev->dev;
 	pctrl->soc = soc_data;
 	pctrl->chip = msm_gpio_template;
+	pctrl->route_to_apps = of_device_is_compatible(pctrl->dev-
 of_node,
+					"qcom,ipq8064-pinctrl");
 
 	raw_spin_lock_init(&pctrl->lock);
@@ -1253,9 +1277,12 @@ int msm_pinctrl_probe(struct

platform_device *pdev,

Quoted 12 lines

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct platform_device *pdev, · line 1284

Quoted 9 lines
drivers/pinctrl/qcom/pinctrl-msm.c +3 -1
 				return PTR_ERR(pctrl->regs[i]);
 		}
 	} else {
-		pctrl->regs[0] = devm_platform_ioremap_resource(pdev, 0);
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR(pctrl->regs[0]))
 			return PTR_ERR(pctrl->regs[0]);
+		else

No need for the else, as the "positive" case is a return.

Will fix in v3

Quoted 10 lines

Thank you,
Bjorn

Quoted 7 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -1
+			pctrl->base_reg = res->start;
 	}
 
 	msm_pinctrl_setup_pm_reset(pctrl);
--

2.25.1

#3 lore raw

Re: R: [PATCH v2] pinctrl: qcom: use scm_call to route GPIO irq to Apps

Quoted 58 lines · On Fri 27 Mar 13:58 PDT 2020, [email protected] wrote:
Quoted 43 lines · Ansuel Smith
Quoted 10 lines

From: Ajay Kishore <[email protected]>

For IPQ806x targets, TZ protects the registers that are used to configure the routing of interrupts to a target processor. To resolve this, this patch uses scm call to route GPIO interrupts to application processor. Also the scm call interface is changed.

Thanks for respinning this Ansuel, just some minor things below.

Quoted 4 lines

---
v2:
* Move static varibale in msm_pinctrl struct
* Revert '4b024225c4a8 ("pinctrl: use

devm_platform_ioremap_resource() to simplify code")'

Quoted 3 lines

to get base_reg addr

 drivers/pinctrl/qcom/pinctrl-msm.c | 37

++++++++++++++++++++++++++----

Review

Quoted 3 lines
 1 file changed, 32 insertions(+), 5 deletions(-)
(quoted diff) +0 -0

b/drivers/pinctrl/qcom/pinctrl-msm.c

Quoted 16 lines

index 9a8daa256a32..9627ebd41ff9 100644

drivers/pinctrl/qcom/pinctrl-msm.c +2 -0
@@ -22,6 +22,8 @@
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/log2.h>
+#include <linux/qcom_scm.h>
+#include <linux/io.h>
 
 #include <linux/soc/qcom/irq.h>
 
@@ -60,6 +62,9 @@ struct msm_pinctrl {
 	struct irq_chip irq_chip;
 	int irq;
 
Quoted 6 lines

drivers/pinctrl/qcom/pinctrl-msm.c struct msm_pinctrl { · line 65

Quoted 1 line
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+	int route_to_apps;

We "always" route our interrupts to apps, so please rename this to intr_target_use_scm. And using "bool" instead would make it clear that this is a binary flag.

Will fix in v3

Quoted 5 lines

drivers/pinctrl/qcom/pinctrl-msm.c struct msm_pinctrl { · line 66

Quoted 1 line
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+	u32 base_reg;

Even though I think it's fine that you only fill in the first entry, please make this phys_base[MAX_NR_GPIO]; next to regs.

Quoted 3 lines

If I understand correctly, I should replace base_reg with phys_base[MAX_NR_GPIO]
I think we should use MAX_NR_TILES instead of MAX_NR_GPIO

Yes of course, didn't pay attention to my autocomplete!

Quoted 6 lines

Wouldn't this be a waste of memory since only the base_reg will be needed? I don't think there will be a soc with multiple tiles and the need to add code in the loop function. (Also sorry for off-topic... since we have soc_data->ntiles why don't we use kmem allocation instead of statically use half empty array?)

While I hope you're right, I think it looks better if it mimics the overall design - at the expense of wasting 12 bytes.

Quoted 20 lines
Quoted 8 lines

drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_irq_set_type(struct

Quoted 5 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -0
+
 	raw_spinlock_t lock;
 
 	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
@@ -883,10 +888,27 @@ static int msm_gpio_irq_set_type(struct

irq_data *d, unsigned int type)

Quoted 2 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0 -0
 		clear_bit(d->hwirq, pctrl->dual_edge_irqs);
 
Quoted 11 lines

drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) · line 891

Quoted 6 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -4
 	/* Route interrupts to application cpu */
-	val = msm_readl_intr_target(pctrl, g);
-	val &= ~(7 << g->intr_target_bit);
-	val |= g->intr_target_kpss_val << g->intr_target_bit;
-	msm_writel_intr_target(val, pctrl, g);
+	if (pctrl->route_to_apps && pctrl->base_reg) {

I meant that you could fill out "base_reg" only if it's supposed to be used, but looking at your patch I think it's nicer to have a separate flag - so you can omit the check for base_reg != NULL here.

Quoted 4 lines

Since we return error if devm_ioremap_resource fails, it is good to only check
the route_to_apps as base_reg will be set for sure?

Right.

My initial suggestion was that base != NULL would have the meaning of intr_target_use_scm. But what I meant here is that after looking at your patch I think one flag and a separate base is better.

Thanks,
Bjorn

Quoted 62 lines
Quoted 36 lines

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct platform_device

Quoted 24 lines
drivers/pinctrl/qcom/pinctrl-msm.c +20 -0
+		u32 addr = pctrl->base_reg + g->intr_target_reg;
+		int ret;
+
+		qcom_scm_io_readl(addr, &val);
+
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+
+		ret = qcom_scm_io_writel(addr, val);
+		if (ret)
+			dev_err(pctrl->dev,
+				"Failed routing %lu interrupt to Apps proc",
+				d->hwirq);
+		}
+	} else {
+		val = msm_readl_intr_target(pctrl, g);
+		val &= ~(7 << g->intr_target_bit);
+		val |= g->intr_target_kpss_val << g->intr_target_bit;
+		msm_writel_intr_target(val, pctrl, g);
+	}
 
 	/* Update configuration for gpio.
 	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
@@ -1241,6 +1263,8 @@ int msm_pinctrl_probe(struct platform_device

*pdev,

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct

Quoted 10 lines
drivers/pinctrl/qcom/pinctrl-msm.c +2 -0
 	pctrl->dev = &pdev->dev;
 	pctrl->soc = soc_data;
 	pctrl->chip = msm_gpio_template;
+	pctrl->route_to_apps = of_device_is_compatible(pctrl->dev-
 of_node,
+					"qcom,ipq8064-pinctrl");
 
 	raw_spin_lock_init(&pctrl->lock);
@@ -1253,9 +1277,12 @@ int msm_pinctrl_probe(struct

platform_device *pdev,

Quoted 12 lines

drivers/pinctrl/qcom/pinctrl-msm.c int msm_pinctrl_probe(struct platform_device *pdev, · line 1284

Quoted 9 lines
drivers/pinctrl/qcom/pinctrl-msm.c +3 -1
 				return PTR_ERR(pctrl->regs[i]);
 		}
 	} else {
-		pctrl->regs[0] = devm_platform_ioremap_resource(pdev, 0);
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR(pctrl->regs[0]))
 			return PTR_ERR(pctrl->regs[0]);
+		else

No need for the else, as the "positive" case is a return.

Will fix in v3

Quoted 10 lines

Thank you,
Bjorn

Quoted 7 lines
drivers/pinctrl/qcom/pinctrl-msm.c +1 -1
+			pctrl->base_reg = res->start;
 	}
 
 	msm_pinctrl_setup_pm_reset(pctrl);
--

2.25.1