lkml.org 
[lkml]   [2018]   [May]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] remoteproc: Add APSS based Qualcomm ADSP PIL driver for SDM845
Date
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@codeaurora.org>
Signed-off-by: RajendraBabu Medisetti <rajendrabm@codeaurora.org>
Signed-off-by: Krishnamurthy Renu <krishnamurthy.renu@codeaurora.org>
---
.../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.
\
 
 \ /
  Last update: 2018-05-13 10:27    [W:0.503 / U:0.020 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site