[PATCH] remoteproc: Add APSS based Qualcomm ADSP PIL driver for SDM845

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds Qualcomm ADSP PIL driver support for SDM845 with ADSP bootup
and shutdown operation handled from Application Processor SubSystem(APSS).

Signed-off-by: Rohit kumar <rohitkr@xxxxxxxxxxxxxx>
Signed-off-by: RajendraBabu Medisetti <rajendrabm@xxxxxxxxxxxxxx>
Signed-off-by: Krishnamurthy Renu <krishnamurthy.renu@xxxxxxxxxxxxxx>
---
 .../devicetree/bindings/remoteproc/qcom,adsp.txt   |   1 +
 drivers/remoteproc/Makefile                        |   3 +-
 drivers/remoteproc/qcom_adsp_pil.c                 | 122 ++++-----
 drivers/remoteproc/qcom_adsp_pil.h                 |  86 ++++++
 drivers/remoteproc/qcom_adsp_pil_sdm845.c          | 304 +++++++++++++++++++++
 5 files changed, 454 insertions(+), 62 deletions(-)
 create mode 100644 drivers/remoteproc/qcom_adsp_pil.h
 create mode 100644 drivers/remoteproc/qcom_adsp_pil_sdm845.c

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
index 728e419..a9fe033 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
@@ -10,6 +10,7 @@ on the Qualcomm ADSP Hexagon core.
 		    "qcom,msm8974-adsp-pil"
 		    "qcom,msm8996-adsp-pil"
 		    "qcom,msm8996-slpi-pil"
+		    "qcom,sdm845-apss-adsp-pil"
 
 - interrupts-extended:
 	Usage: required
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 02627ed..759831b 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_OMAP_REMOTEPROC)		+= omap_remoteproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)		+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC)		+= da8xx_remoteproc.o
 obj-$(CONFIG_KEYSTONE_REMOTEPROC)	+= keystone_remoteproc.o
-obj-$(CONFIG_QCOM_ADSP_PIL)		+= qcom_adsp_pil.o
+obj-$(CONFIG_QCOM_ADSP_PIL)		+= qcom_adsp.o
+qcom_adsp-objs				+= qcom_adsp_pil.o qcom_adsp_pil_sdm845.o
 obj-$(CONFIG_QCOM_RPROC_COMMON)		+= qcom_common.o
 obj-$(CONFIG_QCOM_Q6V5_PIL)		+= qcom_q6v5_pil.o
 obj-$(CONFIG_QCOM_SYSMON)		+= qcom_sysmon.o
diff --git a/drivers/remoteproc/qcom_adsp_pil.c b/drivers/remoteproc/qcom_adsp_pil.c
index 89a86ce..9ab3698 100644
--- a/drivers/remoteproc/qcom_adsp_pil.c
+++ b/drivers/remoteproc/qcom_adsp_pil.c
@@ -1,5 +1,5 @@
 /*
- * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
+ * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974, MSM8996 and SDM845.
  *
  * Copyright (C) 2016 Linaro Ltd
  * Copyright (C) 2014 Sony Mobile Communications AB
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/qcom_scm.h>
 #include <linux/regulator/consumer.h>
 #include <linux/remoteproc.h>
@@ -30,56 +29,8 @@
 #include <linux/soc/qcom/smem.h>
 #include <linux/soc/qcom/smem_state.h>
 
-#include "qcom_common.h"
 #include "remoteproc_internal.h"
-
-struct adsp_data {
-	int crash_reason_smem;
-	const char *firmware_name;
-	int pas_id;
-	bool has_aggre2_clk;
-
-	const char *ssr_name;
-	const char *sysmon_name;
-	int ssctl_id;
-};
-
-struct qcom_adsp {
-	struct device *dev;
-	struct rproc *rproc;
-
-	int wdog_irq;
-	int fatal_irq;
-	int ready_irq;
-	int handover_irq;
-	int stop_ack_irq;
-
-	struct qcom_smem_state *state;
-	unsigned stop_bit;
-
-	struct clk *xo;
-	struct clk *aggre2_clk;
-
-	struct regulator *cx_supply;
-	struct regulator *px_supply;
-
-	int pas_id;
-	int crash_reason_smem;
-	bool has_aggre2_clk;
-
-	struct completion start_done;
-	struct completion stop_done;
-
-	phys_addr_t mem_phys;
-	phys_addr_t mem_reloc;
-	void *mem_region;
-	size_t mem_size;
-
-	struct qcom_rproc_glink glink_subdev;
-	struct qcom_rproc_subdev smd_subdev;
-	struct qcom_rproc_ssr ssr_subdev;
-	struct qcom_sysmon *sysmon;
-};
+#include "qcom_adsp_pil.h"
 
 static int adsp_load(struct rproc *rproc, const struct firmware *fw)
 {
@@ -112,18 +63,32 @@ static int adsp_start(struct rproc *rproc)
 	if (ret)
 		goto disable_cx_supply;
 
-	ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
-	if (ret) {
-		dev_err(adsp->dev,
-			"failed to authenticate image and release reset\n");
-		goto disable_px_supply;
+	if (adsp->is_apss_controlled) {
+		ret = adsp->ops->bringup(adsp);
+		if (ret) {
+			dev_err(adsp->dev, "adsp bringup failed\n");
+			adsp->ops->bringdown(adsp);
+			goto disable_px_supply;
+		}
+	} else {
+		ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
+		if (ret) {
+			dev_err(adsp->dev,
+				"failed to authenticate image and release reset\n");
+			goto disable_px_supply;
+		}
 	}
 
 	ret = wait_for_completion_timeout(&adsp->start_done,
 					  msecs_to_jiffies(5000));
 	if (!ret) {
 		dev_err(adsp->dev, "start timed out\n");
-		qcom_scm_pas_shutdown(adsp->pas_id);
+
+		if (adsp->is_apss_controlled)
+			adsp->ops->bringdown(adsp);
+		else
+			qcom_scm_pas_shutdown(adsp->pas_id);
+
 		ret = -ETIMEDOUT;
 		goto disable_px_supply;
 	}
@@ -160,7 +125,11 @@ static int adsp_stop(struct rproc *rproc)
 				    BIT(adsp->stop_bit),
 				    0);
 
-	ret = qcom_scm_pas_shutdown(adsp->pas_id);
+	if (adsp->is_apss_controlled)
+		ret = adsp->ops->bringdown(adsp);
+	else
+		ret = qcom_scm_pas_shutdown(adsp->pas_id);
+
 	if (ret)
 		dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
 
@@ -334,8 +303,9 @@ static int adsp_probe(struct platform_device *pdev)
 	if (!desc)
 		return -EINVAL;
 
-	if (!qcom_scm_is_available())
-		return -EPROBE_DEFER;
+	if (!desc->is_apss_controlled)
+		if (!qcom_scm_is_available())
+			return -EPROBE_DEFER;
 
 	rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
 			    desc->firmware_name, sizeof(*adsp));
@@ -350,6 +320,7 @@ static int adsp_probe(struct platform_device *pdev)
 	adsp->pas_id = desc->pas_id;
 	adsp->crash_reason_smem = desc->crash_reason_smem;
 	adsp->has_aggre2_clk = desc->has_aggre2_clk;
+	adsp->is_apss_controlled = desc->is_apss_controlled;
 	platform_set_drvdata(pdev, adsp);
 
 	init_completion(&adsp->start_done);
@@ -399,6 +370,19 @@ static int adsp_probe(struct platform_device *pdev)
 		goto free_rproc;
 	}
 
+	if (adsp->is_apss_controlled) {
+		if (!desc->ops || !desc->ops->bringup ||
+		    !desc->ops->bringdown || !desc->ops->map_regs) {
+			dev_err(&pdev->dev, "SoC ops not defined\n");
+			ret = -EINVAL;
+			goto free_rproc;
+		}
+		adsp->ops = desc->ops;
+		ret = adsp->ops->map_regs(adsp, pdev);
+		if (ret)
+			goto free_rproc;
+	}
+
 	qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
 	qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
 	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
@@ -434,11 +418,24 @@ static int adsp_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct adsp_data sdm845_apss_adsp_resource_init = {
+		.crash_reason_smem = 423,
+		.firmware_name = "adsp.mdt",
+		.pas_id = 1,
+		.has_aggre2_clk = false,
+		.is_apss_controlled = true,
+		.ssr_name = "lpass",
+		.sysmon_name = "adsp",
+		.ssctl_id = 0x14,
+		.ops = &sdm845_soc_ops,
+};
+
 static const struct adsp_data adsp_resource_init = {
 		.crash_reason_smem = 423,
 		.firmware_name = "adsp.mdt",
 		.pas_id = 1,
 		.has_aggre2_clk = false,
+		.is_apss_controlled = false,
 		.ssr_name = "lpass",
 		.sysmon_name = "adsp",
 		.ssctl_id = 0x14,
@@ -449,6 +446,7 @@ static int adsp_remove(struct platform_device *pdev)
 		.firmware_name = "slpi.mdt",
 		.pas_id = 12,
 		.has_aggre2_clk = true,
+		.is_apss_controlled = false,
 		.ssr_name = "dsps",
 		.sysmon_name = "slpi",
 		.ssctl_id = 0x16,
@@ -458,6 +456,8 @@ static int adsp_remove(struct platform_device *pdev)
 	{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
 	{ .compatible = "qcom,msm8996-adsp-pil", .data = &adsp_resource_init},
 	{ .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
+	{ .compatible = "qcom,sdm845-apss-adsp-pil",
+	  .data = &sdm845_apss_adsp_resource_init},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, adsp_of_match);
@@ -472,5 +472,5 @@ static int adsp_remove(struct platform_device *pdev)
 };
 
 module_platform_driver(adsp_driver);
-MODULE_DESCRIPTION("Qualcomm MSM8974/MSM8996 ADSP Peripherial Image Loader");
+MODULE_DESCRIPTION("Qualcomm MSM8974/MSM8996/SDM845 ADSP Peripherial Image Loader");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_adsp_pil.h b/drivers/remoteproc/qcom_adsp_pil.h
new file mode 100644
index 0000000..29fd086
--- /dev/null
+++ b/drivers/remoteproc/qcom_adsp_pil.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+// Copyright (c) 2018, The Linux Foundation. All rights reserved
+
+#ifndef __QCOM_ADSP_PIL_H__
+#define __QCOM_ADSP_PIL_H__
+
+#include <linux/platform_device.h>
+#include "qcom_common.h"
+
+struct qcom_adsp;
+
+struct soc_ops {
+	int (*bringup)(struct qcom_adsp *adsp);
+	int (*bringdown)(struct qcom_adsp *adsp);
+	int (*map_regs)(struct qcom_adsp *adsp, struct platform_device *pdev);
+};
+
+struct adsp_data {
+	int crash_reason_smem;
+	const char *firmware_name;
+	int pas_id;
+	bool has_aggre2_clk;
+	bool is_apss_controlled;
+	const char *ssr_name;
+	const char *sysmon_name;
+	int ssctl_id;
+	struct soc_ops *ops;
+};
+
+struct qcom_adsp {
+	struct device *dev;
+	struct rproc *rproc;
+
+	int wdog_irq;
+	int fatal_irq;
+	int ready_irq;
+	int handover_irq;
+	int stop_ack_irq;
+
+	struct qcom_smem_state *state;
+	unsigned int stop_bit;
+
+	struct clk *xo;
+	struct clk *aggre2_clk;
+
+	struct regulator *cx_supply;
+	struct regulator *px_supply;
+
+	int pas_id;
+	int crash_reason_smem;
+	bool has_aggre2_clk;
+	bool is_apss_controlled;
+
+	struct completion start_done;
+	struct completion stop_done;
+
+	phys_addr_t mem_phys;
+	phys_addr_t mem_reloc;
+	void *mem_region;
+	size_t mem_size;
+
+	struct soc_ops *ops;
+	void *priv_reg;
+
+	struct qcom_rproc_glink glink_subdev;
+	struct qcom_rproc_subdev smd_subdev;
+	struct qcom_rproc_ssr ssr_subdev;
+	struct qcom_sysmon *sysmon;
+};
+
+extern struct soc_ops sdm845_soc_ops;
+
+static inline void update_bits(void *reg, u32 mask_val, u32 set_val, u32 shift)
+{
+	u32 reg_val = 0;
+
+	reg_val = ((readl(reg)) & ~mask_val) | ((set_val << shift) & mask_val);
+	writel(reg_val, reg);
+}
+
+static inline unsigned int read_bit(void *reg, u32 mask, int shift)
+{
+	return ((readl(reg) & mask) >> shift);
+}
+
+#endif
diff --git a/drivers/remoteproc/qcom_adsp_pil_sdm845.c b/drivers/remoteproc/qcom_adsp_pil_sdm845.c
new file mode 100644
index 0000000..7518385
--- /dev/null
+++ b/drivers/remoteproc/qcom_adsp_pil_sdm845.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Qualcomm APSS Based ADSP bootup/shutdown ops for SDM845.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "qcom_adsp_pil.h"
+
+/* set values */
+#define CLK_ENABLE				0x1
+#define CLK_DISABLE				0x0
+/* time out value */
+#define ACK_TIMEOUT				200000
+/* mask values */
+#define CLK_MASK				GENMASK(4, 0)
+#define EVB_MASK				GENMASK(27, 4)
+#define SPIN_CLKOFF_MASK			BIT(31)
+#define AUDIO_SYNC_RESET_MASK			BIT(2)
+#define CLK_ENABLE_MASK				BIT(0)
+#define HAL_CLK_MASK				BIT(1)
+/* GCC register offsets */
+#define GCC_BASE				0x00147000
+#define SWAY_CBCR_OFFSET			0x00000008
+/*LPASS register base address and offsets*/
+#define LPASS_BASE				0x17000000
+#define AON_CBCR_OFFSET				0x00014098
+#define CMD_RCGR_OFFSET				0x00014000
+#define CFG_RCGR_OFFSET				0x00014004
+#define AHBS_AON_CBCR_OFFSET			0x00033000
+#define AHBM_AON_CBCR_OFFSET			0x00026000
+/*QDSP6SS register base address and offsets*/
+#define QDSP6SS_BASE				0x17300000
+#define RST_EVB_OFFSET				0x00000010
+#define SLEEP_CBCR_OFFSET			0x0000003C
+#define XO_CBCR_OFFSET				0x00000038
+#define CORE_CBCR_OFFSET			0x00000020
+#define CORE_START_OFFSET			0x00000400
+#define BOOT_CMD_OFFSET				0x00000404
+#define BOOT_STATUS_OFFSET			0x00000408
+#define RET_CFG_OFFSET				0x0000001C
+/*TCSR register base address and offsets*/
+#define TCSR_BASE				0x01F62000
+#define TCSR_LPASS_MASTER_IDLE_OFFSET		0x00000008
+#define TCSR_LPASS_HALTACK_OFFSET		0x00000004
+#define TCSR_LPASS_PWR_ON_OFFSET		0x00000010
+#define TCSR_LPASS_HALTREQ_OFFSET		0X00000000
+
+#define RPMH_PDC_SYNC_RESET_ADDR		0x0B2E0100
+#define AOSS_CC_LPASS_RESTART_ADDR		0x0C2D0000
+
+struct sdm845_reg {
+	void __iomem *gcc_base;
+	void __iomem *lpass_base;
+	void __iomem *qdsp6ss_base;
+	void __iomem *tcsr_base;
+	void __iomem *pdc_sync;
+	void __iomem *cc_lpass;
+};
+
+static int sdm845_map_registers(struct qcom_adsp *adsp,
+				struct platform_device *pdev)
+{
+	struct sdm845_reg *reg;
+
+	adsp->priv_reg = devm_kzalloc(&pdev->dev, sizeof(struct sdm845_reg),
+			GFP_KERNEL);
+	if (!adsp->priv_reg)
+		return -ENOMEM;
+
+	reg = adsp->priv_reg;
+
+	reg->gcc_base = devm_ioremap(adsp->dev, GCC_BASE, 0xc);
+	if (!reg->gcc_base) {
+		dev_err(adsp->dev, "%s: failed to map GCC base registers\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	reg->lpass_base = devm_ioremap(adsp->dev, LPASS_BASE, 0x8E004);
+	if (!reg->lpass_base) {
+		dev_err(adsp->dev, "%s: failed to map LPASS base registers\n",
+				__func__);
+		return -ENOMEM;
+	}
+	reg->qdsp6ss_base =  devm_ioremap(adsp->dev, QDSP6SS_BASE, 0x40c);
+	if (!reg->qdsp6ss_base) {
+		dev_err(adsp->dev, "%s: failed to map QDSP6SS base registers\n",
+				__func__);
+		return -ENOMEM;
+	}
+	reg->tcsr_base = devm_ioremap(adsp->dev, TCSR_BASE, 0x14);
+	if (!reg->tcsr_base) {
+		dev_err(adsp->dev, "%s: failed to map TCSR base registers\n",
+				__func__);
+		return -ENOMEM;
+	}
+	reg->pdc_sync = devm_ioremap(adsp->dev, RPMH_PDC_SYNC_RESET_ADDR, 0x4);
+	if (!reg->pdc_sync) {
+		dev_err(adsp->dev, "%s: failed to map RPMH_PDC_SYNC_RESET register\n",
+				__func__);
+		return -ENOMEM;
+	}
+	reg->cc_lpass = devm_ioremap(adsp->dev, AOSS_CC_LPASS_RESTART_ADDR,
+			0x4);
+	if (!reg->cc_lpass) {
+		dev_err(adsp->dev, "%s:failed to map AOSS_CC_LPASS_RESTART register\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int clk_enable_spin(void *reg, int read_shift, int write_shift)
+{
+	u32 maxDelay = 500;
+	u32 val;
+
+	update_bits(reg, CLK_ENABLE_MASK, CLK_ENABLE, write_shift);
+	val = readl(reg);
+	if (!(readl(reg) & HAL_CLK_MASK)) {
+		/*
+		 * wait for disabling of HW signal CLK_OFF to confirm that
+		 * clock is actually ON.
+		 */
+		while (maxDelay-- && read_bit(reg, SPIN_CLKOFF_MASK,
+							read_shift))
+			udelay(1);
+	}
+	if (!maxDelay) {
+		pr_err("%s: fail to update register = %p\n", __func__, reg);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int sdm845_adsp_clk_enable(struct qcom_adsp *adsp)
+{
+	u32 ret;
+	u32 maxDelay = 100;
+	struct sdm845_reg *reg = adsp->priv_reg;
+
+	/* Enable SWAY clock */
+	ret = clk_enable_spin(reg->gcc_base + SWAY_CBCR_OFFSET, CLK_MASK, 0x0);
+	if (ret)
+		return ret;
+
+	/* Enable LPASS AHB AON Bus */
+	ret = clk_enable_spin(reg->lpass_base + AON_CBCR_OFFSET, CLK_MASK, 0x0);
+	if (ret)
+		return ret;
+
+	/* Set the AON clock root to be sourced by XO */
+	writel(CLK_DISABLE, reg->lpass_base + CFG_RCGR_OFFSET);
+	writel(CLK_ENABLE, reg->lpass_base + CMD_RCGR_OFFSET);
+
+	while (read_bit((reg->lpass_base + CMD_RCGR_OFFSET), CLK_ENABLE, 0)
+						&& maxDelay--)
+		udelay(2);
+
+	if (!maxDelay) {
+		pr_err("%s: fail to enable CMD_RCGR clock\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	/* Enable the QDSP6SS AHBM and AHBS clocks */
+	ret = clk_enable_spin(reg->lpass_base + AHBS_AON_CBCR_OFFSET,
+				CLK_MASK, 0x0);
+	if (ret)
+		return ret;
+	ret = clk_enable_spin(reg->lpass_base + AHBM_AON_CBCR_OFFSET,
+				CLK_MASK, 0x0);
+	if (ret)
+		return ret;
+
+	/* Turn on the XO clock, required to boot FSM */
+	update_bits(reg->qdsp6ss_base + XO_CBCR_OFFSET, CLK_ENABLE_MASK,
+							CLK_ENABLE, 0x0);
+
+	/* Enable the QDSP6SS sleep clock for the QDSP6 watchdog enablement */
+	update_bits(reg->qdsp6ss_base + SLEEP_CBCR_OFFSET,
+					CLK_ENABLE_MASK, CLK_ENABLE, 0x0);
+
+	/* Configure QDSP6 core CBC to enable clock */
+	update_bits(reg->qdsp6ss_base + CORE_CBCR_OFFSET, CLK_ENABLE_MASK,
+					CLK_ENABLE, 0x0);
+	return 0;
+}
+
+static int sdm845_adsp_reset(struct qcom_adsp *adsp)
+{
+	u32 timeout = ACK_TIMEOUT;
+	struct sdm845_reg *reg = adsp->priv_reg;
+
+	/* De-assert QDSP6 stop core. QDSP6 will execute after out of reset */
+	update_bits(reg->qdsp6ss_base + CORE_START_OFFSET,
+					CLK_ENABLE_MASK, CLK_ENABLE, 0x0);
+	/* Trigger boot FSM to start QDSP6 */
+	writel(CLK_ENABLE, reg->qdsp6ss_base + BOOT_CMD_OFFSET);
+
+	/* Wait for core to come out of reset */
+	while ((!(readl(reg->qdsp6ss_base +
+			BOOT_STATUS_OFFSET))) && (timeout-- > 0))
+		udelay(5);
+
+	if (!timeout)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int sdm845_bringup(struct qcom_adsp *adsp)
+{
+	u32 ret;
+	struct sdm845_reg *reg = adsp->priv_reg;
+
+	ret = sdm845_adsp_clk_enable(adsp);
+	if (ret) {
+		dev_err(adsp->dev, "%s: sdm845_adsp_clk_enable failed\n",
+				__func__);
+		return ret;
+	}
+	/* Program boot address */
+	update_bits(reg->qdsp6ss_base + RST_EVB_OFFSET,
+				EVB_MASK, (adsp->mem_phys) >> 8, 0x4);
+
+	/* Wait for addresses to be programmed before starting adsp */
+	mb();
+	ret = sdm845_adsp_reset(adsp);
+	if (ret)
+		dev_err(adsp->dev, "%s: De-assert QDSP6 out of reset failed\n",
+					__func__);
+	return ret;
+}
+
+static int sdm845_bringdown(struct qcom_adsp *adsp)
+{
+	u32 acktimeout = ACK_TIMEOUT;
+	u32 temp;
+	struct sdm845_reg *reg = adsp->priv_reg;
+
+	/* Reset the retention logic */
+	update_bits(reg->qdsp6ss_base + RET_CFG_OFFSET,
+			CLK_ENABLE_MASK, CLK_ENABLE, 0x0);
+	/* Disable the slave way clock to LPASS */
+	update_bits(reg->gcc_base + SWAY_CBCR_OFFSET,
+			CLK_ENABLE_MASK, CLK_DISABLE, 0x0);
+
+	/* QDSP6 master port needs to be explicitly halted */
+	temp = read_bit(reg->tcsr_base + TCSR_LPASS_PWR_ON_OFFSET,
+			CLK_ENABLE, 0x0);
+	temp = temp && !read_bit(reg->tcsr_base + TCSR_LPASS_MASTER_IDLE_OFFSET,
+			CLK_ENABLE, 0x0);
+	if (temp) {
+		writel(CLK_ENABLE, reg->tcsr_base + TCSR_LPASS_HALTREQ_OFFSET);
+		/*  Wait for halt ACK from QDSP6 */
+		while ((read_bit(reg->tcsr_base + TCSR_LPASS_HALTACK_OFFSET,
+				CLK_DISABLE, 0x0) == 0) && (acktimeout-- > 0))
+			udelay(5);
+
+		if (acktimeout) {
+			if (read_bit(reg->tcsr_base +
+					TCSR_LPASS_MASTER_IDLE_OFFSET,
+						CLK_ENABLE, 0x0) != 1)
+				dev_warn(adsp->dev,
+						"%s: failed to receive %s\n",
+						__func__, "TCSR MASTER ACK");
+		} else {
+			dev_err(adsp->dev, "%s: failed to receive halt ack\n",
+					__func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* Assert the LPASS PDC Reset */
+	update_bits(reg->pdc_sync,  AUDIO_SYNC_RESET_MASK,
+			CLK_ENABLE, 0x2);
+	/* Place the LPASS processor into reset */
+	writel(CLK_ENABLE, reg->cc_lpass);
+	/* wait after asserting subsystem restart from AOSS */
+	udelay(200);
+
+	/* Clear the halt request for the AXIM and AHBM for Q6 */
+	writel(CLK_DISABLE, reg->tcsr_base + TCSR_LPASS_HALTREQ_OFFSET);
+
+	/* De-assert the LPASS PDC Reset */
+	update_bits(reg->pdc_sync, AUDIO_SYNC_RESET_MASK,
+			CLK_DISABLE, 0x2);
+	/* Remove the LPASS reset */
+	writel(CLK_DISABLE, reg->cc_lpass);
+	/* wait after de-asserting subsystem restart from AOSS */
+	udelay(200);
+
+	return 0;
+}
+
+struct soc_ops sdm845_soc_ops = {
+	.bringup = sdm845_bringup,
+	.bringdown = sdm845_bringdown,
+	.map_regs = sdm845_map_registers,
+};
-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux