soc/xtensa/intel_adsp/tools: Make cavstool.py DSP resetting more stable

When using more than one core on cavs25, some hangs were made
"persistent", as it seems not all cores were being properly reset, thus
compromising tests - if a test hangs for any reason, subsequent tests
that were not restrict to a single CPU would also fail.

This patch mitigates these issues by two changes:
  - Closely mimics SOF Linux driver way of loading the firmware. So,
    explicit stall and reset (and "unstall" and "unreset") of cores, with
    appropriate checks that states have been reached;
  - More generous sleep before resetting the stream.

Also, the status of ADSPCS (Audio DSP Control and Status) register is
logged more thoroughly to aid debugging in case new issues arise.

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
This commit is contained in:
Ederson de Souza 2022-05-18 12:09:10 -07:00 committed by Carles Cufí
parent f875d027a0
commit 3209bc1a4a
4 changed files with 40 additions and 14 deletions

View file

@ -46,6 +46,12 @@ OUTBOX_OFFSET = (512 + (0 * 128)) * 1024 + 4096
INBOX_OFFSET = (512 + (1 * 128)) * 1024 INBOX_OFFSET = (512 + (1 * 128)) * 1024
WINSTREAM_OFFSET = (512 + (3 * 128)) * 1024 WINSTREAM_OFFSET = (512 + (3 * 128)) * 1024
# ADSPCS bits
CRST = 0
CSTALL = 8
SPA = 16
CPA = 24
class HDAStream: class HDAStream:
# creates an hda stream with at 2 buffers of buf_len # creates an hda stream with at 2 buffers of buf_len
def __init__(self, stream_id: int): def __init__(self, stream_id: int):
@ -355,6 +361,14 @@ class Regs:
def runx(cmd): def runx(cmd):
return subprocess.check_output(cmd, shell=True).decode().rstrip() return subprocess.check_output(cmd, shell=True).decode().rstrip()
def mask(bit):
if cavs25:
return 0b1 << bit
if cavs18:
return 0b1111 << bit
if cavs15:
return 0b11 << bit
def load_firmware(fw_file): def load_firmware(fw_file):
try: try:
fw_bytes = open(fw_file, "rb").read() fw_bytes = open(fw_file, "rb").read()
@ -377,9 +391,14 @@ def load_firmware(fw_file):
hda.GCTL = 1 hda.GCTL = 1
while not hda.GCTL & 1: pass while not hda.GCTL & 1: pass
log.info("Powering down DSP cores") log.info(f"Stalling and Resetting DSP cores, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS = 0xffff dsp.ADSPCS |= mask(CSTALL)
while dsp.ADSPCS & 0xff000000: pass dsp.ADSPCS |= mask(CRST)
while (dsp.ADSPCS & mask(CRST)) == 0: pass
log.info(f"Powering down DSP cores, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS &= ~mask(SPA)
while dsp.ADSPCS & mask(CPA): pass
log.info(f"Configuring HDA stream {hda_ostream_id} to transfer firmware image") log.info(f"Configuring HDA stream {hda_ostream_id} to transfer firmware image")
(buf_list_addr, num_bufs) = setup_dma_mem(fw_bytes) (buf_list_addr, num_bufs) = setup_dma_mem(fw_bytes)
@ -403,18 +422,25 @@ def load_firmware(fw_file):
# Start DSP. Host needs to provide power to all cores on 1.5 # Start DSP. Host needs to provide power to all cores on 1.5
# (which also starts them) and 1.8 (merely gates power, DSP also # (which also starts them) and 1.8 (merely gates power, DSP also
# has to set PWRCTL). The bits for cores other than 0 are ignored # has to set PWRCTL). On 2.5 where the DSP has full control,
# on 2.5 where the DSP has full control. # and only core 0 is set.
log.info(f"Starting DSP, ADSPCS = 0x{dsp.ADSPCS:x}") log.info(f"Starting DSP, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS = 0xff0000 if not cavs25 else 0x01fefe dsp.ADSPCS = mask(SPA)
while (dsp.ADSPCS & 0x1000000) == 0: pass while (dsp.ADSPCS & mask(CPA)) == 0: pass
# Wait for the ROM to boot and signal it's ready. This short log.info(f"Unresetting DSP cores, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS &= ~mask(CRST)
while (dsp.ADSPCS & 1) != 0: pass
log.info(f"Running DSP cores, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS &= ~mask(CSTALL)
# Wait for the ROM to boot and signal it's ready. This not so short
# sleep seems to be needed; if we're banging on the memory window # sleep seems to be needed; if we're banging on the memory window
# during initial boot (before/while the window control registers # during initial boot (before/while the window control registers
# are configured?) the DSP hardware will hang fairly reliably. # are configured?) the DSP hardware will hang fairly reliably.
log.info("Wait for ROM startup") log.info(f"Wait for ROM startup, ADSPCS = 0x{dsp.ADSPCS:x}")
time.sleep(0.1) time.sleep(1)
while (dsp.SRAM_FW_STATUS >> 24) != 5: pass while (dsp.SRAM_FW_STATUS >> 24) != 5: pass
# Send the DSP an IPC message to tell the device how to boot. # Send the DSP an IPC message to tell the device how to boot.
@ -443,7 +469,7 @@ def load_firmware(fw_file):
# chromebook) putting the two writes next each other also hangs # chromebook) putting the two writes next each other also hangs
# the DSP! # the DSP!
sd.CTL &= ~2 # clear START sd.CTL &= ~2 # clear START
time.sleep(0.1) time.sleep(1)
sd.CTL |= 1 sd.CTL |= 1
log.info(f"cAVS firmware load complete") log.info(f"cAVS firmware load complete")

View file

@ -9,7 +9,7 @@
#include <zephyr/drivers/dma.h> #include <zephyr/drivers/dma.h>
#include "tests.h" #include "tests.h"
#define IPC_TIMEOUT K_MSEC(500) #define IPC_TIMEOUT K_MSEC(1500)
#define DMA_BUF_SIZE 256 #define DMA_BUF_SIZE 256
#define TRANSFER_SIZE 256 #define TRANSFER_SIZE 256
#define TRANSFER_COUNT 8 #define TRANSFER_COUNT 8

View file

@ -15,7 +15,7 @@
#define HDA_REGBLOCK_SIZE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_out), reg, 1) #define HDA_REGBLOCK_SIZE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_out), reg, 1)
#include <cavs_hda.h> #include <cavs_hda.h>
#define IPC_TIMEOUT K_MSEC(500) #define IPC_TIMEOUT K_MSEC(1500)
#define STREAM_ID 3U #define STREAM_ID 3U
#define HDA_BUF_SIZE 256 #define HDA_BUF_SIZE 256
#define TRANSFER_COUNT 8 #define TRANSFER_COUNT 8

View file

@ -17,7 +17,7 @@
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(hda_test, LOG_LEVEL_DBG); LOG_MODULE_REGISTER(hda_test, LOG_LEVEL_DBG);
#define IPC_TIMEOUT K_MSEC(500) #define IPC_TIMEOUT K_MSEC(1500)
void hda_log_hook(uint32_t written) void hda_log_hook(uint32_t written)
{ {