ipq806x: route gpio interrupts to APPS processor through scm firmware
authorPavel Kubelun <be.dissent@gmail.com>
Sun, 19 Mar 2017 11:59:26 +0000 (07:59 -0400)
committerJohn Crispin <john@phrozen.org>
Mon, 20 Mar 2017 07:11:29 +0000 (08:11 +0100)
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.

Signed-off-by: Pavel Kubelun <be.dissent@gmail.com>
target/linux/ipq806x/patches-4.9/0073-pinctrl-qom-use-scm_call-to-route-GPIO-irq-to-Apps.patch [new file with mode: 0644]

diff --git a/target/linux/ipq806x/patches-4.9/0073-pinctrl-qom-use-scm_call-to-route-GPIO-irq-to-Apps.patch b/target/linux/ipq806x/patches-4.9/0073-pinctrl-qom-use-scm_call-to-route-GPIO-irq-to-Apps.patch
new file mode 100644 (file)
index 0000000..2eac44d
--- /dev/null
@@ -0,0 +1,166 @@
+From 2034addc7e193dc81d7ca60d8884832751b76758 Mon Sep 17 00:00:00 2001
+From: Ajay Kishore <akisho@codeaurora.org>
+Date: Tue, 24 Jan 2017 14:14:16 +0530
+Subject: pinctrl: qcom: use scm_call to route GPIO irq to Apps
+
+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.
+
+Change-Id: Ib6c06829d04bc8c20483c36e63da92e26cdef9ce
+Signed-off-by: Ajay Kishore <akisho@codeaurora.org>
+---
+ drivers/firmware/qcom_scm-32.c     | 17 +++++++++++++++++
+ drivers/firmware/qcom_scm-64.c     |  9 +++++++++
+ drivers/firmware/qcom_scm.c        | 13 +++++++++++++
+ drivers/firmware/qcom_scm.h        |  8 ++++++++
+ drivers/pinctrl/qcom/pinctrl-msm.c | 34 ++++++++++++++++++++++++++++------
+ include/linux/qcom_scm.h           |  3 ++-
+ 6 files changed, 77 insertions(+), 7 deletions(-)
+
+--- a/drivers/firmware/qcom_scm-32.c
++++ b/drivers/firmware/qcom_scm-32.c
+@@ -560,3 +560,21 @@ int __qcom_scm_pas_mss_reset(struct devi
+       return ret ? : le32_to_cpu(out);
+ }
++
++int __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1)
++{
++      s32 ret;
++
++      ret = qcom_scm_call_atomic1(svc_id, cmd_id, arg1);
++
++      return ret;
++}
++
++int __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2)
++{
++      s32 ret;
++
++      ret = qcom_scm_call_atomic2(svc_id, cmd_id, arg1, arg2);
++ 
++ return ret;
++ }
+--- a/drivers/firmware/qcom_scm-64.c
++++ b/drivers/firmware/qcom_scm-64.c
+@@ -358,3 +358,12 @@ int __qcom_scm_pas_mss_reset(struct devi
+       return ret ? : res.a1;
+ }
++int __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1)
++{
++      return -ENOTSUPP;
++}
++
++int __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2)
++{
++      return -ENOTSUPP;
++}
+--- a/drivers/firmware/qcom_scm.c
++++ b/drivers/firmware/qcom_scm.c
+@@ -443,3 +443,16 @@ static int __init qcom_scm_init(void)
+       return platform_driver_register(&qcom_scm_driver);
+ }
+ subsys_initcall(qcom_scm_init);
++
++int qcom_scm_pinmux_read(u32 arg1)
++{
++      return __qcom_scm_pinmux_read(SCM_SVC_IO_ACCESS, SCM_IO_READ, arg1);
++}
++EXPORT_SYMBOL(qcom_scm_pinmux_read);
++
++int qcom_scm_pinmux_write(u32 arg1, u32 arg2)
++{
++      return __qcom_scm_pinmux_write(SCM_SVC_IO_ACCESS, SCM_IO_WRITE,
++                                      arg1, arg2);
++}
++EXPORT_SYMBOL(qcom_scm_pinmux_write);
+--- a/drivers/firmware/qcom_scm.h
++++ b/drivers/firmware/qcom_scm.h
+@@ -56,6 +56,13 @@ extern int  __qcom_scm_pas_auth_and_rese
+ extern int  __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral);
+ extern int  __qcom_scm_pas_mss_reset(struct device *dev, bool reset);
++#define SCM_IO_READ   1
++#define SCM_IO_WRITE  2
++#define SCM_SVC_IO_ACCESS     0x5
++
++s32 __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1);
++s32 __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2);
++
+ /* common error codes */
+ #define QCOM_SCM_V2_EBUSY     -12
+ #define QCOM_SCM_ENOMEM               -5
+--- a/drivers/pinctrl/qcom/pinctrl-msm.c
++++ b/drivers/pinctrl/qcom/pinctrl-msm.c
+@@ -30,7 +30,8 @@
+ #include <linux/reboot.h>
+ #include <linux/pm.h>
+ #include <linux/log2.h>
+-
++#include <linux/qcom_scm.h>
++#include <linux/io.h>
+ #include "../core.h"
+ #include "../pinconf.h"
+ #include "pinctrl-msm.h"
+@@ -639,6 +640,9 @@ static int msm_gpio_irq_set_type(struct
+       const struct msm_pingroup *g;
+       unsigned long flags;
+       u32 val;
++      u32 addr;
++      int ret;
++      const __be32 *reg;
+       g = &pctrl->soc->groups[d->hwirq];
+@@ -652,11 +656,30 @@ static int msm_gpio_irq_set_type(struct
+       else
+               clear_bit(d->hwirq, pctrl->dual_edge_irqs);
++      ret = of_device_is_compatible(pctrl->dev->of_node,
++                                      "qcom,ipq8064-pinctrl");
+       /* Route interrupts to application cpu */
+-      val = readl(pctrl->regs + g->intr_target_reg);
+-      val &= ~(7 << g->intr_target_bit);
+-      val |= g->intr_target_kpss_val << g->intr_target_bit;
+-      writel(val, pctrl->regs + g->intr_target_reg);
++      if (!ret) {
++              val = readl(pctrl->regs + g->intr_target_reg);
++              val &= ~(7 << g->intr_target_bit);
++              val |= g->intr_target_kpss_val << g->intr_target_bit;
++              writel(val, pctrl->regs + g->intr_target_reg);
++      } else {
++              reg = of_get_property(pctrl->dev->of_node, "reg", NULL);
++              if (reg) {
++                      addr = be32_to_cpup(reg) + g->intr_target_reg;
++                      val = qcom_scm_pinmux_read(addr);
++                      __iormb();
++
++                      val &= ~(7 << g->intr_target_bit);
++                      val |= g->intr_target_kpss_val << g->intr_target_bit;
++
++                      __iowmb();
++                      ret = qcom_scm_pinmux_write(addr, val);
++                      if (ret)
++                              pr_err("\n Routing interrupts to Apps proc failed");
++              }
++      }
+       /* Update configuration for gpio.
+        * RAW_STATUS_EN is left on for all gpio irqs. Due to the
+@@ -930,4 +953,3 @@ int msm_pinctrl_remove(struct platform_d
+       return 0;
+ }
+ EXPORT_SYMBOL(msm_pinctrl_remove);
+-
+--- a/include/linux/qcom_scm.h
++++ b/include/linux/qcom_scm.h
+@@ -46,4 +46,6 @@ extern void qcom_scm_cpu_power_down(u32
+ extern u32 qcom_scm_get_version(void);
++extern s32 qcom_scm_pinmux_read(u32 arg1);
++extern s32 qcom_scm_pinmux_write(u32 arg1, u32 arg2);
+ #endif