clear-pkgs-linux-iot-lts2018/1070-SoC-Intel-Skylake-BXT-...

115 lines
3.3 KiB
Diff
Raw Permalink Normal View History

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Bozek <dominikx.bozek@intel.com>
Date: Fri, 17 May 2019 10:47:00 +0200
Subject: [PATCH] SoC: Intel: Skylake: BXT: Stop polling FwStauts after halt
Implementation of skl_dsp_fw_ops.load_fw() reuse generic function
sst_dsp_register_poll(). But this function shouldn't be used for
polling states in FwStatus. FW may notify halt state earlier and
further polling for particular state is waist of the time.
This patch add function dedicated to poll FwStatus.
Change-Id: I23783a507ccd71fd514f0a0e2246c40e406b7c47
Tracked-On: ACI-5767
Tracked-On: OAM-80502
Signed-off-by: Dominik Bozek <dominikx.bozek@intel.com>
---
sound/soc/intel/skylake/bxt-sst.c | 67 ++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c
2020-10-27 02:14:06 +08:00
index b158883ef7b6..887a43bcd43b 100644
--- a/sound/soc/intel/skylake/bxt-sst.c
+++ b/sound/soc/intel/skylake/bxt-sst.c
@@ -144,6 +144,69 @@ bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count)
return ret;
}
+int sst_fw_status_poll(struct sst_dsp *ctx, u32 module, u32 state,
+ u32 time, char *operation)
+{
+ union {
+ struct {
+ u32 state:24;
+ u32 waits:4;
+ u32 module:3;
+ u32 halted:1;
+ };
+ u32 raw;
+ } fwsts;
+ unsigned long timeout;
+ int k = 0, s;
+ int ret;
+ char *state_desc;
+
+ /*
+ * split the loop into sleeps of varying resolution.
+ * By observation, FW responds in 10 to 20ms.
+ */
+
+ timeout = jiffies + msecs_to_jiffies(time);
+
+ fwsts.raw = sst_dsp_shim_read_unlocked(ctx, BXT_ADSP_FW_STATUS);
+ while (!fwsts.halted
+ && (fwsts.module == module)
+ && (fwsts.state != state)
+ && time_before(jiffies, timeout)) {
+
+ k++;
+ switch (k) {
+ case 1:
+ case 12:
+ s = 10000;
+ break;
+ case 2:
+ s = 1000;
+ break;
+ }
+
+ usleep_range(s, s+100);
+
+ fwsts.raw = sst_dsp_shim_read_unlocked(ctx, BXT_ADSP_FW_STATUS);
+ }
+
+ if (!fwsts.halted && (fwsts.module == module)
+ && (fwsts.state == state)) {
+ state_desc = "success";
+ ret = 0;
+ } else if (fwsts.halted || fwsts.module != module) {
+ state_desc = "unexpected state";
+ ret = -EPROTO;
+ } else {
+ state_desc = "timeout";
+ ret = -ETIME;
+ }
+ dev_dbg(ctx->dev, "FW Status=%08x %s %s\n", fwsts.raw,
+ operation, state_desc);
+
+ return ret;
+}
+
/*
* First boot sequence has some extra steps. Core 0 waits for power
* status on core 1, so power up core 1 also momentarily, keep it in
@@ -210,7 +273,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
skl_ipc_op_int_enable(ctx);
/* Step 7: Wait for ROM init */
- ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK,
+ ret = sst_fw_status_poll(ctx, 0,
SKL_FW_INIT, BXT_ROM_INIT_TIMEOUT, "ROM Load");
if (ret < 0) {
dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret);
@@ -234,7 +297,7 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx)
ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag,
SNDRV_PCM_STREAM_PLAYBACK);
- ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK,
+ ret = sst_fw_status_poll(ctx, 0,
BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot");
ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag,
--
https://clearlinux.org