From 2724807f7f70a6a3e67b3f6bf921cc77ed39c8a1 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 18 Apr 2018 01:14:15 +0530 Subject: [PATCH 01/12] remoteproc: Prevent incorrect rproc state on xfer mem ownership failure Any failure in the secure call for transferring mem ownership of mba region to Q6 would result in reporting that the remoteproc device is running. This is because the previous q6v5_clk_enable would have been a success. Prevent this by updating variable 'ret' accordingly. Cc: stable@vger.kernel.org Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 8e70a627e0bb..8d4a2eb3736e 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -761,13 +761,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; } From 41a5985f173bf1f93d2634fc93d8aa53683067f9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 17 Apr 2018 19:49:16 +0200 Subject: [PATCH 02/12] remoteproc: Remove depends on HAS_DMA in case of platform dependency Remove dependencies on HAS_DMA where a Kconfig symbol depends on another symbol that implies HAS_DMA, and, optionally, on "|| COMPILE_TEST". In most cases this other symbol is an architecture or platform specific symbol, or PCI. Generic symbols and drivers without platform dependencies keep their dependencies on HAS_DMA, to prevent compiling subsystems or drivers that cannot work anyway. This simplifies the dependencies, and allows to improve compile-testing. Signed-off-by: Geert Uytterhoeven Reviewed-by: Mark Brown Acked-by: Robin Murphy Acked-by: Bjorn Andersson Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 027274008b08..cd1c168fd188 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -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 From 2310eae90f26f1cb8039bdfbfe6fe981e9838e80 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 2 May 2018 11:56:57 +0200 Subject: [PATCH 03/12] remoteproc/davinci: add the missing retval check for clk_enable() The davinci platform is being switched to using the common clock framework, where clk_enable() can fail. Add the return value check. Signed-off-by: Bartosz Golaszewski Acked-by: Suman Anna Reviewed-by: David Lechner Reviewed-by: Sekhar Nori Signed-off-by: Bjorn Andersson --- drivers/remoteproc/da8xx_remoteproc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index bf3b9034c319..2b24291337b7 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -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_enable(dsp_clk); + if (ret) { + dev_err(dev, "clk_enable() failed: %d\n", ret); + return ret; + } + davinci_clk_reset_deassert(dsp_clk); return 0; From 5d26f068a59415664ddf79f42dac78777ff0dcf8 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 2 May 2018 11:56:58 +0200 Subject: [PATCH 04/12] remoteproc/davinci: prepare and unprepare the clock where needed We're currently switching the platform to using the common clock framework. We need to explicitly prepare and unprepare the rproc clock. Signed-off-by: Bartosz Golaszewski Acked-by: Suman Anna Reviewed-by: David Lechner Reviewed-by: Sekhar Nori Signed-off-by: Bjorn Andersson --- drivers/remoteproc/da8xx_remoteproc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index 2b24291337b7..f134192922e0 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -149,9 +149,9 @@ static int da8xx_rproc_start(struct rproc *rproc) writel(rproc->bootaddr, drproc->bootreg); - ret = clk_enable(dsp_clk); + ret = clk_prepare_enable(dsp_clk); if (ret) { - dev_err(dev, "clk_enable() failed: %d\n", ret); + dev_err(dev, "clk_prepare_enable() failed: %d\n", ret); return ret; } @@ -165,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; } From 24ff14172fc3fe6aba4c2d329fa093fe92818373 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 2 May 2018 11:56:59 +0200 Subject: [PATCH 05/12] remoteproc/davinci: use octal permissions for module_param() Checkpatch recommends to use octal perms instead of S_IRUGO. Signed-off-by: Bartosz Golaszewski Reviewed-by: Sekhar Nori Acked-by: Suman Anna Signed-off-by: Bjorn Andersson --- drivers/remoteproc/da8xx_remoteproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index f134192922e0..b668e32996e2 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -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')"); From 826950868cd81268913a91b69f00fb6c3f0b6f5b Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 27 Apr 2018 14:16:38 +0200 Subject: [PATCH 06/12] remoteproc/ste: remove abandoned include file STE modem driver has been removed in 2016. This include has no users since then. Signed-off-by: Andrzej Hajda Cc: Jean Delvare Cc: Linus Walleij Cc: Ohad Ben-Cohen Cc: Bjorn Andersson Cc: Suman Anna Acked-by: Jean Delvare Acked-by: Linus Walleij Signed-off-by: Bjorn Andersson --- include/linux/ste_modem_shm.h | 56 ----------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 include/linux/ste_modem_shm.h diff --git a/include/linux/ste_modem_shm.h b/include/linux/ste_modem_shm.h deleted file mode 100644 index 8444a4eff1bb..000000000000 --- a/include/linux/ste_modem_shm.h +++ /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 -#include - -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*/ From f4c428cfe427e4c5ea6dc47c6fbbfee2b13b31e0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 21 May 2018 16:39:15 -0700 Subject: [PATCH 07/12] remoteproc: q6v5: Return irq from q6v5_request_irq() q6v5_request_irq() was supposed to return the irq number, but ret is overwritten by the request_irq(), fix this and return the IRQ on success. Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 56b14c27e275..3736e8608c69 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -1049,22 +1049,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) From 663e98453a6e449655b07e004ce01e28af09dd07 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 21 May 2018 22:57:09 +0530 Subject: [PATCH 08/12] remoteproc: q6v5: Move proxy unvote to handover irq handler Introduce interrupt handler for smp2p ready interrupt to handle start completion. Move the proxy votes for clocks and regulators to the handover interrupt context. Signed-off-by: Sibi Sankar [bjorn: Only proxy unvote if handover irq has not fired] Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 50 +++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 3736e8608c69..a7c325ef78a1 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -143,6 +143,10 @@ struct q6v5 { struct qcom_smem_state *state; unsigned stop_bit; + int handover_irq; + + bool proxy_unvoted; + struct clk *active_clks[8]; struct clk *proxy_clks[4]; int active_clk_count; @@ -727,11 +731,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, @@ -808,11 +816,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: @@ -851,6 +854,9 @@ static int q6v5_start(struct rproc *rproc) q6v5_regulator_disable(qproc, qproc->proxy_regs, qproc->proxy_reg_count); +disable_irqs: + disable_irq(qproc->handover_irq); + return ret; } @@ -891,6 +897,16 @@ static int q6v5_stop(struct rproc *rproc) WARN_ON(ret); reset_control_assert(qproc->mss_restart); + + 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->active_clks, qproc->active_clk_count); q6v5_regulator_disable(qproc, qproc->active_regs, @@ -958,7 +974,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; @@ -966,6 +982,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; @@ -1194,9 +1224,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) From fb22022ff63ddbc51face6fb2f06496ae90d3293 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 21 May 2018 22:57:11 +0530 Subject: [PATCH 09/12] dt-bindings: remoteproc: Add Q6v5 Modem PIL binding for SDM845 Add new compatible string for Qualcomm SDM845 SoCs Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt index 00d3d58a102f..d90182425450 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt @@ -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 From 9f135fa1ffea3005f0d8021e55463134a2175928 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 21 May 2018 22:57:12 +0530 Subject: [PATCH 10/12] remoteproc: q6v5: Introduce reset assert/deassert helper functions Adding reset assert/deassert helper functions to handle SoC specific reset sequences. This wil be used by SDM845 to assert and deassert ALT_RESET and MSS_RESET signals. Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index a7c325ef78a1..7e2691c9c034 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -337,6 +337,16 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw) return 0; } +static int q6v5_reset_assert(struct q6v5 *qproc) +{ + return reset_control_assert(qproc->mss_restart); +} + +static int q6v5_reset_deassert(struct q6v5 *qproc) +{ + return reset_control_deassert(qproc->mss_restart); +} + static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms) { unsigned long timeout; @@ -755,7 +765,7 @@ 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_reset_deassert(qproc); if (ret) { dev_err(qproc->dev, "failed to deassert mss restart\n"); goto disable_vdd; @@ -843,7 +853,7 @@ static int q6v5_start(struct rproc *rproc) qproc->active_clk_count); assert_reset: - reset_control_assert(qproc->mss_restart); + q6v5_reset_assert(qproc); disable_vdd: q6v5_regulator_disable(qproc, qproc->active_regs, qproc->active_reg_count); @@ -896,7 +906,7 @@ 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); From 231f67d1fb2fe80a523a5d68690f1da9593781c8 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 21 May 2018 22:57:13 +0530 Subject: [PATCH 11/12] remoteproc: q6v5: Add support for mss remoteproc on SDM845 From SDM845, the Q6SS reset sequence on software side has been simplified with the introduction of boot FSM which assists in bringing the Q6 out of reset. SDM845 brings a new reset signal ALT_RESET which is a part of the MSS subsystem hence requires reset clks to be enabled before assert/deassert. Use the SoC specific reset helper function to add support for ALT_RESET in SDM845. Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 115 ++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 4 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 7e2691c9c034..b48e5f36dd71 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -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 @@ -104,6 +106,13 @@ #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 { @@ -148,8 +159,10 @@ struct q6v5 { 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]; @@ -174,6 +187,7 @@ struct q6v5 { 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; @@ -183,6 +197,7 @@ enum { MSS_MSM8916, MSS_MSM8974, MSS_MSM8996, + MSS_SDM845, }; static int q6v5_regulator_init(struct device *dev, struct reg_info *regs, @@ -339,12 +354,25 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw) static int q6v5_reset_assert(struct q6v5 *qproc) { - return reset_control_assert(qproc->mss_restart); + 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) { - return reset_control_deassert(qproc->mss_restart); + 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) @@ -399,8 +427,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); @@ -508,6 +563,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) { @@ -765,10 +821,18 @@ static int q6v5_start(struct rproc *rproc) dev_err(qproc->dev, "failed to enable supplies\n"); goto disable_proxy_clk; } + + ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks, + qproc->reset_clk_count); + if (ret) { + 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_vdd; + goto disable_reset_clks; } ret = q6v5_clk_enable(qproc->dev, qproc->active_clks, @@ -854,6 +918,9 @@ static int q6v5_start(struct rproc *rproc) assert_reset: 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); @@ -917,6 +984,8 @@ static int q6v5_stop(struct rproc *rproc) 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, @@ -1196,6 +1265,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) { @@ -1225,6 +1302,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) @@ -1285,6 +1363,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*[]){ @@ -1300,6 +1403,7 @@ static const struct rproc_hexagon_res msm8996_mss = { NULL }, .need_mem_protection = true, + .has_alt_reset = false, .version = MSS_MSM8996, }; @@ -1331,6 +1435,7 @@ static const struct rproc_hexagon_res msm8916_mss = { NULL }, .need_mem_protection = false, + .has_alt_reset = false, .version = MSS_MSM8916, }; @@ -1370,6 +1475,7 @@ static const struct rproc_hexagon_res msm8974_mss = { NULL }, .need_mem_protection = false, + .has_alt_reset = false, .version = MSS_MSM8974, }; @@ -1378,6 +1484,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); From 4725496e4872824fa6182d412c66c00cae978a62 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 21 May 2018 22:57:14 +0530 Subject: [PATCH 12/12] remoteproc: q6v5: Allow defining GLINK edge for mss remoteproc Add GLINK subdevice to allow definition of GLINK edge as a child of modem-pil. Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index b48e5f36dd71..2190debf3d35 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -183,6 +183,7 @@ 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; @@ -1333,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); @@ -1356,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);