Merge tag 'rproc-v4.18' of git://github.com/andersson/remoteproc
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 11 Jun 2018 19:11:23 +0000 (12:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 11 Jun 2018 19:11:23 +0000 (12:11 -0700)
Pull remoteproc updates from Bjorn Andersson:
 "This brings a few minor fixes to the Davinci driver, drops a orphan
  include file from the StE cleanup done ealier and introduces support
  for booting the modem on Qualcomm's SDM845 platform"

* tag 'rproc-v4.18' of git://github.com/andersson/remoteproc:
  remoteproc: q6v5: Allow defining GLINK edge for mss remoteproc
  remoteproc: q6v5: Add support for mss remoteproc on SDM845
  remoteproc: q6v5: Introduce reset assert/deassert helper functions
  dt-bindings: remoteproc: Add Q6v5 Modem PIL binding for SDM845
  remoteproc: q6v5: Move proxy unvote to handover irq handler
  remoteproc: q6v5: Return irq from q6v5_request_irq()
  remoteproc/ste: remove abandoned include file
  remoteproc/davinci: use octal permissions for module_param()
  remoteproc/davinci: prepare and unprepare the clock where needed
  remoteproc/davinci: add the missing retval check for clk_enable()
  remoteproc: Remove depends on HAS_DMA in case of platform dependency
  remoteproc: Prevent incorrect rproc state on xfer mem ownership failure

Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
drivers/remoteproc/Kconfig
drivers/remoteproc/da8xx_remoteproc.c
drivers/remoteproc/qcom_q6v5_pil.c
include/linux/ste_modem_shm.h [deleted file]

index 00d3d58a102fe6da2ed0b70b7ce2d61772b17822..d9018242545044e6ac0cad6f7bbead4bdbbb87f6 100644 (file)
@@ -11,6 +11,7 @@ on the Qualcomm Hexagon core.
                    "qcom,msm8916-mss-pil",
                    "qcom,msm8974-mss-pil"
                    "qcom,msm8996-mss-pil"
+                   "qcom,sdm845-mss-pil"
 
 - reg:
        Usage: required
index 027274008b086d6f421a3aa0c0ecf5cf2804cb76..cd1c168fd18898dc802e90b5327abc2b9a6fae0d 100644 (file)
@@ -24,7 +24,6 @@ config IMX_REMOTEPROC
 
 config OMAP_REMOTEPROC
        tristate "OMAP remoteproc support"
-       depends on HAS_DMA
        depends on ARCH_OMAP4 || SOC_OMAP5
        depends on OMAP_IOMMU
        select MAILBOX
index bf3b9034c319eed88f86a1ef3fd61792f389466e..b668e32996e215bd474f0e0d2060bdf80c13c573 100644 (file)
@@ -25,7 +25,7 @@
 #include "remoteproc_internal.h"
 
 static char *da8xx_fw_name;
-module_param(da8xx_fw_name, charp, S_IRUGO);
+module_param(da8xx_fw_name, charp, 0444);
 MODULE_PARM_DESC(da8xx_fw_name,
                 "Name of DSP firmware file in /lib/firmware (if not specified defaults to 'rproc-dsp-fw')");
 
@@ -138,6 +138,7 @@ static int da8xx_rproc_start(struct rproc *rproc)
        struct device *dev = rproc->dev.parent;
        struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
        struct clk *dsp_clk = drproc->dsp_clk;
+       int ret;
 
        /* hw requires the start (boot) address be on 1KB boundary */
        if (rproc->bootaddr & 0x3ff) {
@@ -148,7 +149,12 @@ static int da8xx_rproc_start(struct rproc *rproc)
 
        writel(rproc->bootaddr, drproc->bootreg);
 
-       clk_enable(dsp_clk);
+       ret = clk_prepare_enable(dsp_clk);
+       if (ret) {
+               dev_err(dev, "clk_prepare_enable() failed: %d\n", ret);
+               return ret;
+       }
+
        davinci_clk_reset_deassert(dsp_clk);
 
        return 0;
@@ -159,7 +165,7 @@ static int da8xx_rproc_stop(struct rproc *rproc)
        struct da8xx_rproc *drproc = rproc->priv;
 
        davinci_clk_reset_assert(drproc->dsp_clk);
-       clk_disable(drproc->dsp_clk);
+       clk_disable_unprepare(drproc->dsp_clk);
 
        return 0;
 }
index cbbafdcaaecb7576da27039233c72c47a7bcf5ae..2190debf3d35fca5df7a957ef31ab63bc0a47712 100644 (file)
@@ -57,6 +57,8 @@
 #define RMB_PMI_META_DATA_REG          0x10
 #define RMB_PMI_CODE_START_REG         0x14
 #define RMB_PMI_CODE_LENGTH_REG                0x18
+#define RMB_MBA_MSS_STATUS             0x40
+#define RMB_MBA_ALT_RESET              0x44
 
 #define RMB_CMD_META_DATA_READY                0x1
 #define RMB_CMD_LOAD_READY             0x2
 #define QDSP6SS_XO_CBCR                0x0038
 #define QDSP6SS_ACC_OVERRIDE_VAL               0x20
 
+/* QDSP6v65 parameters */
+#define QDSP6SS_SLEEP                   0x3C
+#define QDSP6SS_BOOT_CORE_START         0x400
+#define QDSP6SS_BOOT_CMD                0x404
+#define SLEEP_CHECK_MAX_LOOPS           200
+#define BOOT_FSM_TIMEOUT                10000
+
 struct reg_info {
        struct regulator *reg;
        int uV;
@@ -121,9 +130,11 @@ struct rproc_hexagon_res {
        struct qcom_mss_reg_res *proxy_supply;
        struct qcom_mss_reg_res *active_supply;
        char **proxy_clk_names;
+       char **reset_clk_names;
        char **active_clk_names;
        int version;
        bool need_mem_protection;
+       bool has_alt_reset;
 };
 
 struct q6v5 {
@@ -143,9 +154,15 @@ struct q6v5 {
        struct qcom_smem_state *state;
        unsigned stop_bit;
 
+       int handover_irq;
+
+       bool proxy_unvoted;
+
        struct clk *active_clks[8];
+       struct clk *reset_clks[4];
        struct clk *proxy_clks[4];
        int active_clk_count;
+       int reset_clk_count;
        int proxy_clk_count;
 
        struct reg_info active_regs[1];
@@ -166,10 +183,12 @@ struct q6v5 {
        void *mpss_region;
        size_t mpss_size;
 
+       struct qcom_rproc_glink glink_subdev;
        struct qcom_rproc_subdev smd_subdev;
        struct qcom_rproc_ssr ssr_subdev;
        struct qcom_sysmon *sysmon;
        bool need_mem_protection;
+       bool has_alt_reset;
        int mpss_perm;
        int mba_perm;
        int version;
@@ -179,6 +198,7 @@ enum {
        MSS_MSM8916,
        MSS_MSM8974,
        MSS_MSM8996,
+       MSS_SDM845,
 };
 
 static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
@@ -333,6 +353,29 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
        return 0;
 }
 
+static int q6v5_reset_assert(struct q6v5 *qproc)
+{
+       if (qproc->has_alt_reset)
+               return reset_control_reset(qproc->mss_restart);
+       else
+               return reset_control_assert(qproc->mss_restart);
+}
+
+static int q6v5_reset_deassert(struct q6v5 *qproc)
+{
+       int ret;
+
+       if (qproc->has_alt_reset) {
+               writel(1, qproc->rmb_base + RMB_MBA_ALT_RESET);
+               ret = reset_control_reset(qproc->mss_restart);
+               writel(0, qproc->rmb_base + RMB_MBA_ALT_RESET);
+       } else {
+               ret = reset_control_deassert(qproc->mss_restart);
+       }
+
+       return ret;
+}
+
 static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms)
 {
        unsigned long timeout;
@@ -385,8 +428,35 @@ static int q6v5proc_reset(struct q6v5 *qproc)
        int ret;
        int i;
 
+       if (qproc->version == MSS_SDM845) {
+               val = readl(qproc->reg_base + QDSP6SS_SLEEP);
+               val |= 0x1;
+               writel(val, qproc->reg_base + QDSP6SS_SLEEP);
 
-       if (qproc->version == MSS_MSM8996) {
+               ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_SLEEP,
+                                        val, !(val & BIT(31)), 1,
+                                        SLEEP_CHECK_MAX_LOOPS);
+               if (ret) {
+                       dev_err(qproc->dev, "QDSP6SS Sleep clock timed out\n");
+                       return -ETIMEDOUT;
+               }
+
+               /* De-assert QDSP6 stop core */
+               writel(1, qproc->reg_base + QDSP6SS_BOOT_CORE_START);
+               /* Trigger boot FSM */
+               writel(1, qproc->reg_base + QDSP6SS_BOOT_CMD);
+
+               ret = readl_poll_timeout(qproc->rmb_base + RMB_MBA_MSS_STATUS,
+                               val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
+               if (ret) {
+                       dev_err(qproc->dev, "Boot FSM failed to complete.\n");
+                       /* Reset the modem so that boot FSM is in reset state */
+                       q6v5_reset_deassert(qproc);
+                       return ret;
+               }
+
+               goto pbl_wait;
+       } else if (qproc->version == MSS_MSM8996) {
                /* Override the ACC value if required */
                writel(QDSP6SS_ACC_OVERRIDE_VAL,
                       qproc->reg_base + QDSP6SS_STRAP_ACC);
@@ -494,6 +564,7 @@ static int q6v5proc_reset(struct q6v5 *qproc)
        val &= ~Q6SS_STOP_CORE;
        writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
 
+pbl_wait:
        /* Wait for PBL status */
        ret = q6v5_rmb_pbl_wait(qproc, 1000);
        if (ret == -ETIMEDOUT) {
@@ -727,11 +798,15 @@ static int q6v5_start(struct rproc *rproc)
        int xfermemop_ret;
        int ret;
 
+       qproc->proxy_unvoted = false;
+
+       enable_irq(qproc->handover_irq);
+
        ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
                                    qproc->proxy_reg_count);
        if (ret) {
                dev_err(qproc->dev, "failed to enable proxy supplies\n");
-               return ret;
+               goto disable_irqs;
        }
 
        ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
@@ -747,12 +822,20 @@ static int q6v5_start(struct rproc *rproc)
                dev_err(qproc->dev, "failed to enable supplies\n");
                goto disable_proxy_clk;
        }
-       ret = reset_control_deassert(qproc->mss_restart);
+
+       ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks,
+                             qproc->reset_clk_count);
        if (ret) {
-               dev_err(qproc->dev, "failed to deassert mss restart\n");
+               dev_err(qproc->dev, "failed to enable reset clocks\n");
                goto disable_vdd;
        }
 
+       ret = q6v5_reset_deassert(qproc);
+       if (ret) {
+               dev_err(qproc->dev, "failed to deassert mss restart\n");
+               goto disable_reset_clks;
+       }
+
        ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
                              qproc->active_clk_count);
        if (ret) {
@@ -761,13 +844,11 @@ static int q6v5_start(struct rproc *rproc)
        }
 
        /* Assign MBA image access in DDR to q6 */
-       xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
-                                               qproc->mba_phys,
-                                               qproc->mba_size);
-       if (xfermemop_ret) {
+       ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
+                                     qproc->mba_phys, qproc->mba_size);
+       if (ret) {
                dev_err(qproc->dev,
-                       "assigning Q6 access to mba memory failed: %d\n",
-                       xfermemop_ret);
+                       "assigning Q6 access to mba memory failed: %d\n", ret);
                goto disable_active_clks;
        }
 
@@ -810,11 +891,6 @@ static int q6v5_start(struct rproc *rproc)
                        "Failed to reclaim mba buffer system may become unstable\n");
        qproc->running = true;
 
-       q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
-                        qproc->proxy_clk_count);
-       q6v5_regulator_disable(qproc, qproc->proxy_regs,
-                              qproc->proxy_reg_count);
-
        return 0;
 
 reclaim_mpss:
@@ -842,7 +918,10 @@ disable_active_clks:
                         qproc->active_clk_count);
 
 assert_reset:
-       reset_control_assert(qproc->mss_restart);
+       q6v5_reset_assert(qproc);
+disable_reset_clks:
+       q6v5_clk_disable(qproc->dev, qproc->reset_clks,
+                        qproc->reset_clk_count);
 disable_vdd:
        q6v5_regulator_disable(qproc, qproc->active_regs,
                               qproc->active_reg_count);
@@ -853,6 +932,9 @@ disable_proxy_reg:
        q6v5_regulator_disable(qproc, qproc->proxy_regs,
                               qproc->proxy_reg_count);
 
+disable_irqs:
+       disable_irq(qproc->handover_irq);
+
        return ret;
 }
 
@@ -892,7 +974,19 @@ static int q6v5_stop(struct rproc *rproc)
                                      qproc->mpss_phys, qproc->mpss_size);
        WARN_ON(ret);
 
-       reset_control_assert(qproc->mss_restart);
+       q6v5_reset_assert(qproc);
+
+       disable_irq(qproc->handover_irq);
+
+       if (!qproc->proxy_unvoted) {
+               q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
+                                qproc->proxy_clk_count);
+               q6v5_regulator_disable(qproc, qproc->proxy_regs,
+                                      qproc->proxy_reg_count);
+       }
+
+       q6v5_clk_disable(qproc->dev, qproc->reset_clks,
+                        qproc->reset_clk_count);
        q6v5_clk_disable(qproc->dev, qproc->active_clks,
                         qproc->active_clk_count);
        q6v5_regulator_disable(qproc, qproc->active_regs,
@@ -960,7 +1054,7 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
+static irqreturn_t q6v5_ready_interrupt(int irq, void *dev)
 {
        struct q6v5 *qproc = dev;
 
@@ -968,6 +1062,20 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
+{
+       struct q6v5 *qproc = dev;
+
+       q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
+                        qproc->proxy_clk_count);
+       q6v5_regulator_disable(qproc, qproc->proxy_regs,
+                              qproc->proxy_reg_count);
+
+       qproc->proxy_unvoted = true;
+
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t q6v5_stop_ack_interrupt(int irq, void *dev)
 {
        struct q6v5 *qproc = dev;
@@ -1051,22 +1159,23 @@ static int q6v5_request_irq(struct q6v5 *qproc,
                             const char *name,
                             irq_handler_t thread_fn)
 {
+       int irq;
        int ret;
 
-       ret = platform_get_irq_byname(pdev, name);
-       if (ret < 0) {
+       irq = platform_get_irq_byname(pdev, name);
+       if (irq < 0) {
                dev_err(&pdev->dev, "no %s IRQ defined\n", name);
-               return ret;
+               return irq;
        }
 
-       ret = devm_request_threaded_irq(&pdev->dev, ret,
+       ret = devm_request_threaded_irq(&pdev->dev, irq,
                                        NULL, thread_fn,
                                        IRQF_TRIGGER_RISING | IRQF_ONESHOT,
                                        "q6v5", qproc);
        if (ret)
                dev_err(&pdev->dev, "request %s IRQ failed\n", name);
 
-       return ret;
+       return ret ? : irq;
 }
 
 static int q6v5_alloc_memory_region(struct q6v5 *qproc)
@@ -1157,6 +1266,14 @@ static int q6v5_probe(struct platform_device *pdev)
        }
        qproc->proxy_clk_count = ret;
 
+       ret = q6v5_init_clocks(&pdev->dev, qproc->reset_clks,
+                              desc->reset_clk_names);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to get reset clocks.\n");
+               goto free_rproc;
+       }
+       qproc->reset_clk_count = ret;
+
        ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,
                               desc->active_clk_names);
        if (ret < 0) {
@@ -1186,6 +1303,7 @@ static int q6v5_probe(struct platform_device *pdev)
                goto free_rproc;
 
        qproc->version = desc->version;
+       qproc->has_alt_reset = desc->has_alt_reset;
        qproc->need_mem_protection = desc->need_mem_protection;
        ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
        if (ret < 0)
@@ -1195,9 +1313,15 @@ static int q6v5_probe(struct platform_device *pdev)
        if (ret < 0)
                goto free_rproc;
 
+       ret = q6v5_request_irq(qproc, pdev, "ready", q6v5_ready_interrupt);
+       if (ret < 0)
+               goto free_rproc;
+
        ret = q6v5_request_irq(qproc, pdev, "handover", q6v5_handover_interrupt);
        if (ret < 0)
                goto free_rproc;
+       qproc->handover_irq = ret;
+       disable_irq(qproc->handover_irq);
 
        ret = q6v5_request_irq(qproc, pdev, "stop-ack", q6v5_stop_ack_interrupt);
        if (ret < 0)
@@ -1210,6 +1334,7 @@ static int q6v5_probe(struct platform_device *pdev)
        }
        qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
        qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+       qcom_add_glink_subdev(rproc, &qproc->glink_subdev);
        qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
        qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
        qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
@@ -1233,6 +1358,7 @@ static int q6v5_remove(struct platform_device *pdev)
        rproc_del(qproc->rproc);
 
        qcom_remove_sysmon_subdev(qproc->sysmon);
+       qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
        qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
        qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
        rproc_free(qproc->rproc);
@@ -1240,6 +1366,31 @@ static int q6v5_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct rproc_hexagon_res sdm845_mss = {
+       .hexagon_mba_image = "mba.mbn",
+       .proxy_clk_names = (char*[]){
+                       "xo",
+                       "axis2",
+                       "prng",
+                       NULL
+       },
+       .reset_clk_names = (char*[]){
+                       "iface",
+                       "snoc_axi",
+                       NULL
+       },
+       .active_clk_names = (char*[]){
+                       "bus",
+                       "mem",
+                       "gpll0_mss",
+                       "mnoc_axi",
+                       NULL
+       },
+       .need_mem_protection = true,
+       .has_alt_reset = true,
+       .version = MSS_SDM845,
+};
+
 static const struct rproc_hexagon_res msm8996_mss = {
        .hexagon_mba_image = "mba.mbn",
        .proxy_clk_names = (char*[]){
@@ -1255,6 +1406,7 @@ static const struct rproc_hexagon_res msm8996_mss = {
                        NULL
        },
        .need_mem_protection = true,
+       .has_alt_reset = false,
        .version = MSS_MSM8996,
 };
 
@@ -1286,6 +1438,7 @@ static const struct rproc_hexagon_res msm8916_mss = {
                NULL
        },
        .need_mem_protection = false,
+       .has_alt_reset = false,
        .version = MSS_MSM8916,
 };
 
@@ -1325,6 +1478,7 @@ static const struct rproc_hexagon_res msm8974_mss = {
                NULL
        },
        .need_mem_protection = false,
+       .has_alt_reset = false,
        .version = MSS_MSM8974,
 };
 
@@ -1333,6 +1487,7 @@ static const struct of_device_id q6v5_of_match[] = {
        { .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss},
        { .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss},
        { .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss},
+       { .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss},
        { },
 };
 MODULE_DEVICE_TABLE(of, q6v5_of_match);
diff --git a/include/linux/ste_modem_shm.h b/include/linux/ste_modem_shm.h
deleted file mode 100644 (file)
index 8444a4e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2012
- * Author: Sjur Brendeland / sjur.brandeland@stericsson.com
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef __INC_MODEM_DEV_H
-#define __INC_MODEM_DEV_H
-#include <linux/types.h>
-#include <linux/platform_device.h>
-
-struct ste_modem_device;
-
-/**
- * struct ste_modem_dev_cb - Callbacks for modem initiated events.
- * @kick: Called when the modem kicks the host.
- *
- * This structure contains callbacks for actions triggered by the modem.
- */
-struct ste_modem_dev_cb {
-       void (*kick)(struct ste_modem_device *mdev, int notify_id);
-};
-
-/**
- * struct ste_modem_dev_ops - Functions to control modem and modem interface.
- *
- * @power:     Main power switch, used for cold-start or complete power off.
- * @kick:      Kick the modem.
- * @kick_subscribe: Subscribe for notifications from the modem.
- * @setup:     Provide callback functions to modem device.
- *
- * This structure contains functions used by the ste remoteproc driver
- * to manage the modem.
- */
-struct ste_modem_dev_ops {
-       int (*power)(struct ste_modem_device *mdev, bool on);
-       int (*kick)(struct ste_modem_device *mdev, int notify_id);
-       int (*kick_subscribe)(struct ste_modem_device *mdev, int notify_id);
-       int (*setup)(struct ste_modem_device *mdev,
-                    struct ste_modem_dev_cb *cfg);
-};
-
-/**
- * struct ste_modem_device - represent the STE modem device
- * @pdev: Reference to platform device
- * @ops: Operations used to manage the modem.
- * @drv_data: Driver private data.
- */
-struct ste_modem_device {
-       struct platform_device pdev;
-       struct ste_modem_dev_ops ops;
-       void *drv_data;
-};
-
-#endif /*INC_MODEM_DEV_H*/