pinctrl: qcom: use scm_call to route GPIO irq to Apps
[sfrench/cifs-2.6.git] / drivers / pinctrl / qcom / pinctrl-msm.c
index 173be7d4f00c685f15e2e2e8278cc8e1eebb6c55..75fee04dac5335ad551a9272cd485e0735af1b8e 100644 (file)
@@ -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,8 @@ struct msm_pinctrl {
        struct irq_chip irq_chip;
        int irq;
 
+       bool intr_target_use_scm;
+
        raw_spinlock_t lock;
 
        DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
@@ -68,6 +72,7 @@ struct msm_pinctrl {
 
        const struct msm_pinctrl_soc_data *soc;
        void __iomem *regs[MAX_NR_TILES];
+       u32 phys_base[MAX_NR_TILES];
 };
 
 #define MSM_ACCESSOR(name) \
@@ -882,11 +887,31 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        else
                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);
+       /* Route interrupts to application cpu.
+        * With intr_target_use_scm interrupts are routed to
+        * application cpu using scm calls.
+        */
+       if (pctrl->intr_target_use_scm) {
+               u32 addr = pctrl->phys_base[0] + 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 +1266,9 @@ int msm_pinctrl_probe(struct platform_device *pdev,
        pctrl->dev = &pdev->dev;
        pctrl->soc = soc_data;
        pctrl->chip = msm_gpio_template;
+       pctrl->intr_target_use_scm = of_device_is_compatible(
+                                       pctrl->dev->of_node,
+                                       "qcom,ipq8064-pinctrl");
 
        raw_spin_lock_init(&pctrl->lock);
 
@@ -1253,9 +1281,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]);
+
+               pctrl->phys_base[0] = res->start;
        }
 
        msm_pinctrl_setup_pm_reset(pctrl);