boards/intel_adsp_cavs15: Remove ancient tooling

There were several generations of loader/logger tooling in this
directory, several of which no longer work.  They have all been
replaced by just one pythong script in the soc directory.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2022-01-20 18:02:53 -08:00 committed by Anas Nashif
commit cd5302fa00
21 changed files with 0 additions and 2565 deletions

View file

@ -1,22 +0,0 @@
For various legacy reasons this directory has two similar log tools:
logtool.py and adsplog.py
Both may be used in automation so merging them would require some
coordination.
They both read from the same data from the exact same shared memory
yet they have significant differences:
- logtool.py reads /sys/kernel/debug/sof/etrace which requires the
kernel driver to be loaded.
- adsplog.py finds the memory address by scanning
/sys/bus/pci/devices/; this does not require a driver.
- logtool.py supports reading from a special QEMU location.
- logtool.py performs a raw dump of the memory and exits immediately.
- adsplog.py parses the data, understands the ring buffer and reads
continuously. Its output is much more human-readable.
- adsplog.py has technical details explained in a comment at the top.

View file

@ -1,104 +0,0 @@
#!/usr/bin/python3
# Copyright (c) 2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import os
import sys
import time
import mmap
import struct
# Log reader for the trace output buffer on a ADSP device.
#
# When run with no arguments, it will detect the device, dump the
# contents of the trace buffer and continue to poll for more output.
# The "--no-history" argument can be passed to suppress emission of the
# history, and emit only new output. This can be useful for test
# integration where the user does not want to see any previous runs in
# the log output.
#
# The trace buffer is inside a shared memory region exposed by the
# audio PCI device as a BAR at index 4. The hardware provides 4 128k
# "windows" starting at 512kb in the BAR which the DSP firmware can
# map to 4k-aligned locations within its own address space. By
# protocol convention log output is an 8k region at window index 3.
MAP_SIZE = 8192
WIN_OFFSET = 0x80000
WIN_IDX = 3
WIN_SIZE = 0x20000
LOG_OFFSET = WIN_OFFSET + WIN_IDX * WIN_SIZE
mem = None
sys_devices = "/sys/bus/pci/devices"
for dev_addr in os.listdir(sys_devices):
class_file = sys_devices + "/" + dev_addr + "/class"
pciclass = open(class_file).read()
vendor_file = sys_devices + "/" + dev_addr + "/vendor"
pcivendor = open(vendor_file).read()
if not "0x8086" in pcivendor:
continue
# Intel Multimedia audio controller
# 0x040100 -> DSP is present
# 0x040380 -> DSP is present but optional
if "0x040100" in pciclass or "0x040380" in pciclass:
barfile = sys_devices + "/" + dev_addr + "/resource4"
fd = open(barfile)
try:
mem = mmap.mmap(fd.fileno(), MAP_SIZE, offset=LOG_OFFSET,
prot=mmap.PROT_READ)
except OSError as ose:
sys.stderr.write("""\
mmap failed! If CONFIG IO_STRICT_DEVMEM is set then you must unload the kernel driver.
""")
raise ose
break
if mem is None:
sys.stderr.write("ERROR: No ADSP device found.\n")
sys.exit(1)
# This SHOULD be just "mem[start:start+length]", but slicing an mmap
# array seems to be unreliable on one of my machines (python 3.6.9 on
# Ubuntu 18.04). Read out bytes individually.
def read_mem(start, length):
return b''.join(mem[x].to_bytes(1, 'little') for x in range(start, start + length))
def read_hdr():
return struct.unpack("<IIII", read_mem(0, 16))
# Python implementation of the same algorithm in sys_winstream_read(),
# see there for details.
def winstream_read(last_seq):
while True:
(wlen, start, end, seq) = read_hdr()
if seq == last_seq or start == end:
return (seq, "")
behind = seq - last_seq
if behind > ((end - start) % wlen):
return (seq, "")
copy = (end - behind) % wlen
suffix = min(behind, wlen - copy)
result = read_mem(16 + copy, suffix)
if suffix < behind:
result += read_mem(16, behind - suffix)
(wlen, start1, end, seq1) = read_hdr()
if start1 == start and seq1 == seq:
return (seq, result.decode("utf-8"))
# Choose our last_seq based on whether to dump the pre-existing buffer
(wlen, start, end, seq) = read_hdr()
last_seq = seq
if len(sys.argv) < 2 or sys.argv[1] != "--no-history":
last_seq -= (end - start) % wlen
while True:
time.sleep(0.1)
(last_seq, output) = winstream_read(last_seq)
if output:
sys.stdout.write(output)

View file

@ -1,123 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright(c) 2021 Intel Corporation. All rights reserved.
import struct
import sys
import time
from cavs_fw_common import *
# Intel Audio DSP firmware loader. No dependencies on anything
# outside this file beyond Python3 builtins. Assumes the host system
# has a hugetlbs mounted at /dev/hugepages. Confirmed to run out of
# the box on Ubuntu 18.04 and 20.04. Run as root with the firmware
# file as the single argument.
logging.basicConfig()
log = logging.getLogger("cavs-fw")
log.setLevel(logging.INFO)
FW_FILE = sys.argv[2] if sys.argv[1] == "-f" else sys.argv[1]
HDA_PPCTL__GPROCEN = 1 << 30
HDA_SD_CTL__TRAFFIC_PRIO = 1 << 18
HDA_SD_CTL__START = 1 << 1
def main():
with open(FW_FILE, "rb") as f:
fw_bytes = f.read()
(magic, sz) = struct.unpack("4sI", fw_bytes[0:8])
if magic == b'XMan':
fw_bytes = fw_bytes[sz:len(fw_bytes)]
(hda, sd, dsp, hda_ostream_id, cavs15) = map_regs() # Device register mappings
log.info(f"Detected cAVS {'1.5' if cavs15 else '1.8+'} hardware")
# Turn on HDA "global processing enable" first, which actually
# means "enable access to the ADSP registers in PCI BAR 4" (!)
hda.PPCTL |= HDA_PPCTL__GPROCEN
# Turn off the DSP CPUs (each byte of ADSPCS is a bitmask for each
# of 1-8 DSP cores: lowest byte controls "stall", the second byte
# engages "reset", the third controls power, and the highest byte
# is the output state for "powered" to be read after a state
# change. Set stall and reset, and turn off power for everything:
dsp.ADSPCS = 0xffff
while dsp.ADSPCS & 0xff000000: pass
# Reset the HDA device
hda.GCTL = 0
while hda.GCTL & 1: pass
hda.GCTL = 1
while not hda.GCTL & 1: pass
# Power up (and clear stall and reset on) all the cores on the DSP
# and wait for CPU0 to show that it has power
dsp.ADSPCS = 0xff0000
while (dsp.ADSPCS & 0x1000000) == 0: pass
# Wait for the ROM to boot and signal it's ready. This short
# sleep seems to be needed; if we're banging on the memory window
# during initial boot (before/while the window control registers
# are configured?) the DSP hardware will hang fairly reliably.
time.sleep(0.1)
while (dsp.SRAM_FW_STATUS >> 24) != 5: pass
# Send the DSP an IPC message to tell the device how to boot
# ("PURGE_FW" means "load new code") and which DMA channel to use.
# The high bit is the "BUSY" signal bit that latches a device
# interrupt.
dsp.HIPCI = ( (1 << 31) # BUSY bit
| (0x01 << 24) # type = PURGE_FW
| (1 << 14) # purge_fw = 1
| (hda_ostream_id << 9)) # dma_id
# Configure our DMA stream to transfer the firmware image
(buf_list_addr, num_bufs) = setup_dma_mem(fw_bytes)
sd.BDPU = (buf_list_addr >> 32) & 0xffffffff
sd.BDPL = buf_list_addr & 0xffffffff
sd.CBL = len(fw_bytes)
sd.LVI = num_bufs - 1
# Enable "processing" on the output stream (send DMA to the DSP
# and not the audio output hardware)
hda.PPCTL |= (HDA_PPCTL__GPROCEN | (1 << hda_ostream_id))
# SPIB ("Software Position In Buffer") a Intel HDA extension that
# puts a transfer boundary into the stream beyond which the other
# side will not read. The ROM wants to poll on a "buffer full"
# bit on the other side that only works with this enabled.
hda.SD_SPIB = len(fw_bytes)
hda.SPBFCTL |= (1 << hda_ostream_id)
# Uncork the stream
sd.CTL |= HDA_SD_CTL__START
# FIXME: The ROM sets a FW_ENTERED value of 5 into the bottom 28
# bit "state" field of FW_STATUS on entry to the app. But this is
# actually ephemeral and racy, because Zephyr is free to write its
# own data once the app launches and we might miss it. There's no
# standard "alive" signaling from the OS, which is really what we
# want to wait for. So give it one second and move on.
for _ in range(100):
alive = dsp.SRAM_FW_STATUS & ((1 << 28) - 1) == 5
if alive: break
time.sleep(0.01)
if not alive:
log.warning(f"Load failed? FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
# Turn DMA off and reset the stream. If this doesn't happen the
# hardware continues streaming out of our now-stale page and can
# has been observed to glitch the next boot.
sd.CTL &= ~HDA_SD_CTL__START
sd.CTL |= 1
time.sleep(1)
log.info(f"ADSPCS = 0x{dsp.ADSPCS:x}")
log.info(f"cAVS v15 firmware load complete, {ncores(dsp)} cores active")
if __name__ == "__main__":
log.info("cAVS firmware loader v15")
main()

View file

@ -1,189 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright(c) 2021 Intel Corporation. All rights reserved.
import os
import struct
import sys
import time
from cavs_fw_common import *
# Intel Audio DSP firmware loader. No dependencies on anything
# outside this file beyond Python3 builtins. Pass a signed rimage
# file as the single argument.
logging.basicConfig()
log = logging.getLogger("cavs-fw")
log.setLevel(logging.INFO)
FW_FILE = sys.argv[1]
HDA_PPCTL__GPROCEN = 1 << 30
HDA_SD_CTL__TRAFFIC_PRIO = 1 << 18
HDA_SD_CTL__START = 1 << 1
def main():
if os.system("lsmod | grep -q snd_sof_pci") == 0:
log.warning("The Linux snd-sof-pci kernel module is loaded. While this")
log.warning(" loader will normally work in such circumstances, things")
log.warning(" will get confused if the system tries to touch the hardware")
log.warning(" simultaneously. Operation is most reliable if it is")
log.warning(" unloaded first.")
# Make sure hugetlbfs is mounted (not there on chromeos)
os.system("mount | grep -q hugetlbfs ||"
+ " (mkdir -p /dev/hugepages; "
+ " mount -t hugetlbfs hugetlbfs /dev/hugepages)")
with open(FW_FILE, "rb") as f:
fw_bytes = f.read()
(magic, sz) = struct.unpack("4sI", fw_bytes[0:8])
if magic == b'XMan':
log.info(f"Trimming {sz} bytes of extended manifest")
fw_bytes = fw_bytes[sz:len(fw_bytes)]
(hda, sd, dsp, hda_ostream_id, cavs15) = map_regs() # Device register mappings
log.info(f"Detected cAVS {'1.5' if cavs15 else '1.8+'} hardware")
# Reset the HDA device
log.info("Reset HDA device")
hda.GCTL = 0
while hda.GCTL & 1: pass
hda.GCTL = 1
while not hda.GCTL & 1: pass
# Turn on HDA "global processing enable" first. As documented,
# this enables the audio DSP (vs. hardware HDA emulation). But it
# actually means "enable access to the ADSP registers in PCI BAR 4" (!)
log.info("Enable HDA global processing")
hda.PPCTL |= HDA_PPCTL__GPROCEN
# Turn off the DSP CPUs (each byte of ADSPCS is a bitmask for each
# of 1-8 DSP cores: lowest byte controls "stall", the second byte
# engages "reset", the third controls power, and the highest byte
# is the output state for "powered" to be read after a state
# change. Set stall and reset, and turn off power for everything:
log.info(f"Powering down, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS = 0xffff
while dsp.ADSPCS & 0xff000000: pass
log.info(f"Powered down, ADSPCS = 0x{dsp.ADSPCS:x}")
# Configure our DMA stream to transfer the firmware image
log.info(f"Configuring DMA output stream {hda_ostream_id}...")
(buf_list_addr, num_bufs) = setup_dma_mem(fw_bytes)
# Reset stream
sd.CTL = 1
while (sd.CTL & 1) == 0: pass
sd.CTL = 0
while (sd.CTL & 1) == 1: pass
sd.CTL = (1 << 20) # Set stream ID to anything non-zero
sd.BDPU = (buf_list_addr >> 32) & 0xffffffff
sd.BDPL = buf_list_addr & 0xffffffff
sd.CBL = len(fw_bytes)
sd.LVI = num_bufs - 1
# Enable "processing" on the output stream (send DMA to the DSP
# and not the audio output hardware)
hda.PPCTL |= (HDA_PPCTL__GPROCEN | (1 << hda_ostream_id))
# SPIB ("Software Position In Buffer") is an Intel HDA extension
# that puts a transfer boundary into the stream beyond which the
# other side will not read. The ROM wants to poll on a "buffer
# full" bit on the other side that only works with this enabled.
hda.SPBFCTL |= (1 << hda_ostream_id)
hda.SD_SPIB = len(fw_bytes)
# Power up all the cores on the DSP and wait for CPU0 to show that
# it has power. Leave stall and reset high for now
log.info(f"Powering up DSP core #0, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS = 0x01ffff
while (dsp.ADSPCS & 0x01000000) == 0: pass
log.info(f"Powered up {ncores(dsp)} cores, ADSPCS = 0x{dsp.ADSPCS:x}")
# Send the DSP an IPC message to tell the device how to boot
# ("PURGE_FW" means "load new code") and which DMA channel to use.
# The high bit is the "BUSY" signal bit that latches a device
# interrupt.
#
# Note: with cAVS 1.8+ the ROM receives the stream argument as an index
# within the array of output streams (and we always use the first
# one by construction). But with 1.5 it's the HDA index, and
# depends on the number of input streams on the device.
stream_idx = hda_ostream_id if cavs15 else 0
ipcval = ( (1 << 31) # BUSY bit
| (0x01 << 24) # type = PURGE_FW
| (1 << 14) # purge_fw = 1
| (stream_idx << 9)) # dma_id
log.info(f"Sending PURGW_FW IPC, HIPCR = 0x{ipcval:x}")
dsp.HIPCI = ipcval
# Now start CPU #0 by dropping stall and reset
log.info(f"Starting {ncores(dsp)} cores, ADSPCS = 0x{dsp.ADSPCS:x}")
dsp.ADSPCS = 0x01fffe # Out of reset
time.sleep(0.1)
dsp.ADSPCS = 0x01fefe # Un-stall
log.info(f"Started {ncores(dsp)} cores, ADSPCS = 0x{dsp.ADSPCS:x}")
# Experimentation shows that these steps aren't actually required,
# the ROM just charges ahead and initializes itself correctly even
# if we don't wait for it. Do them anyway for better visibility,
# when requested. Potentially remove later once this code is
# mature.
if log.level <= logging.INFO:
# Wait for the ROM to boot and signal it's ready. NOTE: This
# short sleep seems to be needed; if we're banging on the
# memory window during initial boot (before/while the window
# control registers are configured?) the DSP hardware will
# hang fairly reliably.
time.sleep(0.1)
log.info(f"Waiting for ROM init, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
while (dsp.SRAM_FW_STATUS >> 24) != 5: pass
log.info(f"ROM ready, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
# Newer devices have an ACK bit we can check
if not cavs15:
log.info(f"Awaiting IPC acknowledgment, HIPCA 0x{dsp.HIPCA:x}")
while not dsp.HIPCA & (1 << 31): pass
dsp.HIPCA |= ~(1 << 31)
# Wait for it to signal ROM_INIT_DONE
log.info(f"Awaiting ROM init... FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
while (dsp.SRAM_FW_STATUS & 0x00ffffff) != 1: pass
# It's ready, uncork the stream
log.info(f"Starting DMA, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
sd.CTL |= HDA_SD_CTL__START
# The ROM sets a FW_ENTERED value of 5 into the bottom 28 bit
# "state" field of FW_STATUS on entry to the app. (Pedantry: this
# is actually ephemeral and racy, because Zephyr is free to write
# its own data once the app launches and we might miss it.
# There's no standard "alive" signaling from the OS, which is
# really what we want to wait for. So give it one second and move
# on).
log.info(f"Waiting for load, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
for _ in range(100):
alive = dsp.SRAM_FW_STATUS & ((1 << 28) - 1) == 5
if alive: break
time.sleep(0.01)
if alive:
log.info("ROM reports firmware was entered")
else:
log.warning(f"Load failed? FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
# Turn DMA off and reset the stream. If this doesn't happen the
# hardware continues streaming out of our now-stale page and has
# been observed to glitch the next boot.
sd.CTL = 1
time.sleep(1)
log.info(f"ADSPCS = 0x{dsp.ADSPCS:x}")
log.info(f"cAVS v25 firmware load complete, {ncores(dsp)} cores active")
if __name__ == "__main__":
log.info("cAVS firmware loader v25")
main()

View file

@ -1,174 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright(c) 2021 Intel Corporation. All rights reserved.
import ctypes
import mmap
import os
import struct
import subprocess
import time
import logging
logging.basicConfig()
log = logging.getLogger("cavs-fw")
log.setLevel(logging.INFO)
global_mmaps = [] # protect mmap mappings from garbage collection!
PAGESZ = 4096
HUGEPAGESZ = 2 * 1024 * 1024
HUGEPAGE_FILE = "/dev/hugepages/cavs-fw-dma.tmp"
# Count of active/running cores
def ncores(dsp):
return bin(dsp.ADSPCS >> 24).count("1")
def map_regs():
# List cribbed from kernel SOF driver. Not all tested!
for id in ["119a", "5a98", "1a98", "3198", "9dc8",
"a348", "34C8", "38c8", "4dc8", "02c8",
"06c8", "a3f0", "a0c8", "4b55", "4b58"]:
p = runx(f"grep -il PCI_ID=8086:{id} /sys/bus/pci/devices/*/uevent")
if p:
pcidir = os.path.dirname(p)
break
# Detect hardware version, this matters in a few spots
cavs15 = id in [ "5a98", "1a98", "3198" ]
# Disengage runtime power management so the kernel doesn't put it to sleep
with open(pcidir + b"/power/control", "w") as ctrl:
ctrl.write("on")
# Make sure PCI memory space access and busmastering are enabled.
# Also disable interrupts so as not to confuse the kernel.
with open(pcidir + b"/config", "wb+") as cfg:
cfg.seek(4)
cfg.write(b'\x06\x04')
time.sleep(0.1)
hdamem = bar_map(pcidir, 0)
# Standard HD Audio Registers
hda = Regs(hdamem)
hda.GCAP = 0x0000
hda.GCTL = 0x0008
hda.SPBFCTL = 0x0704
hda.PPCTL = 0x0804
# Find the ID of the first output stream
hda_ostream_id = (hda.GCAP >> 8) & 0x0f # number of input streams
log.info(f"Selected output stream {hda_ostream_id} (GCAP = 0x{hda.GCAP:x})")
hda.SD_SPIB = 0x0708 + (8 * hda_ostream_id)
hda.freeze()
# Standard HD Audio Stream Descriptor
sd = Regs(hdamem + 0x0080 + (hda_ostream_id * 0x20))
sd.CTL = 0x00
sd.LPIB = 0x04
sd.CBL = 0x08
sd.LVI = 0x0c
sd.FMT = 0x12
sd.BDPL = 0x18
sd.BDPU = 0x1c
sd.freeze()
# Intel Audio DSP Registers
dsp = Regs(bar_map(pcidir, 4))
dsp.ADSPCS = 0x00004
if cavs15:
dsp.HIPCI = 0x00048 # original name of the register...
else:
dsp.HIPCI = 0x000d0 # ...now named "HIPCR" per 1.8+ docs
dsp.HIPCA = 0x000d4
dsp.SRAM_FW_STATUS = 0x80000 # Start of first SRAM window
dsp.freeze()
return (hda, sd, dsp, hda_ostream_id, cavs15)
def setup_dma_mem(fw_bytes):
(mem, phys_addr) = map_phys_mem()
mem[0:len(fw_bytes)] = fw_bytes
log.info("Mapped 2M huge page at 0x%x to contain %d bytes of firmware"
% (phys_addr, len(fw_bytes)))
# HDA requires at least two buffers be defined, but we don't care
# about boundaries because it's all a contiguous region. Place a
# vestigial 128-byte (minimum size and alignment) buffer after the
# main one, and put the 4-entry BDL list into the final 128 bytes
# of the page.
buf0_len = HUGEPAGESZ - 2 * 128
buf1_len = 128
bdl_off = buf0_len + buf1_len
mem[bdl_off:bdl_off + 32] = struct.pack("<QQQQ",
phys_addr, buf0_len,
phys_addr + buf0_len, buf1_len)
log.info("Filled the buffer descriptor list (BDL) for DMA.")
return (phys_addr + bdl_off, 2)
# Maps 2M of contiguous memory using a single page from hugetlbfs,
# then locates its physical address for use as a DMA buffer.
def map_phys_mem():
# Ensure the kernel has enough budget for one new page
free = int(runx("awk '/HugePages_Free/ {print $2}' /proc/meminfo"))
if free == 0:
tot = 1 + int(runx("awk '/HugePages_Total/ {print $2}' /proc/meminfo"))
os.system(f"echo {tot} > /proc/sys/vm/nr_hugepages")
hugef = open(HUGEPAGE_FILE, "w+")
hugef.truncate(HUGEPAGESZ)
mem = mmap.mmap(hugef.fileno(), HUGEPAGESZ)
global_mmaps.append(mem)
os.unlink(HUGEPAGE_FILE)
# Find the local process address of the mapping, then use that to
# extract the physical address from the kernel's pagemap
# interface. The physical page frame number occupies the bottom
# bits of the entry.
mem[0] = 0 # Fault the page in so it has an address!
vaddr = ctypes.addressof(ctypes.c_int.from_buffer(mem))
vpagenum = vaddr >> 12
pagemap = open("/proc/self/pagemap", "rb")
pagemap.seek(vpagenum * 8)
pent = pagemap.read(8)
paddr = (struct.unpack("Q", pent)[0] & ((1 << 55) - 1)) * PAGESZ
pagemap.close()
log.info("Obtained the physical address of the mapped huge page.")
return (mem, paddr)
# Maps a PCI BAR and returns the in-process address
def bar_map(pcidir, barnum):
f = open(pcidir.decode() + "/resource" + str(barnum), "r+")
mm = mmap.mmap(f.fileno(), os.fstat(f.fileno()).st_size)
global_mmaps.append(mm)
log.info("Mapped PCI bar %d of length %d bytes." % (barnum, os.fstat(f.fileno()).st_size))
return ctypes.addressof(ctypes.c_int.from_buffer(mm))
# Syntactic sugar to make register block definition & use look nice.
# Instantiate from a base address, assign offsets to (uint32) named
# registers as fields, call freeze(), then the field acts as a direct
# alias for the register!
class Regs:
def __init__(self, base_addr):
vars(self)["base_addr"] = base_addr
vars(self)["ptrs"] = {}
vars(self)["frozen"] = False
def freeze(self):
vars(self)["frozen"] = True
def __setattr__(self, name, val):
if not self.frozen and name not in self.ptrs:
addr = self.base_addr + val
self.ptrs[name] = ctypes.c_uint32.from_address(addr)
else:
self.ptrs[name].value = val
def __getattr__(self, name):
return self.ptrs[name].value
def runx(cmd):
return subprocess.Popen(["sh", "-c", cmd],
stdout=subprocess.PIPE).stdout.read()

View file

@ -1,117 +0,0 @@
#!/bin/sh
# Copyright (c) 2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
set -e
# General purpose loader tool for a remote ssh-accessible CAVS 1.5
# device (e.g. an Up Squared board running Linux). Can be used as the
# twister hook for both --device-serial-pty and --west-flash, e.g.:
#
# twister -p intel_adsp_cavs15 \
# --device-testing --device-serial-pty=/path/to/cavsload.sh \
# --west-flash=/path/to/cavsload.sh
#
# Alternatively, pass a built "zephyr.elf" file (in a complete build
# tree, not just a standalone file) as the single argument and the
# script will synchronously flash the device and begin emitting its
# logs to standard output.
#
# The remote host must be accessible via non-interactive ssh access
# and the remote account must have password-free sudo ability. (The
# intent is that isolating the host like this to be a CAVS test unit
# means that simple device access at root is acceptable.) There must
# be a current Zephyr tree on the host, and a working loadable
# "diag_driver" kernel module.
# Remote host on which to test
HOST=up2
# Zephyr tree on the host
HOST_ZEPHYR_BASE=z/zephyr
# rimage key to use for signing binaries
KEY=$HOME/otc_private_key.pem
# Local path to a built rimage (https://github.com/thesofproject/rimage)
RIMAGE=$ZEPHYR_BASE/../modules/audio/sof/zephyr/ext/rimage
# Kernel module on host (https://github.com/thesofproject/sof-diagnostic-driver)
HOST_DRIVER=sof-diagnostic-driver/diag_driver.ko
########################################################################
#
# Twister has frustrating runtime behavior with this device. The
# flash tool is run via west as part of the build, has a working
# directory in the build tree, and is passed the build directory as
# its command line argument. The console/serial tool is run globally
# in $ZEPHYR_BASE. But the console script has no arguments, and thus
# can't find the test directory! And worse, the scripts are
# asynchronous and may start in either order, but our console script
# can't be allowed to run until after the flash. If it does, it will
# pull old data (from the last test run!) out of the buffer and
# confuse twister.
#
# So the solution here is to have the console script do the trace
# reading AND the flashing. The flash script merely signs the binary
# and places it into ZEPHYR_BASE for the console script to find. The
# console script then just has to wait for the binary to appear (which
# solves the ordering problem), flash it, delete it (so as not to
# confuse the next test run), and emit the adsplog output as expected.
#
# One side effect is that the logs for the firmware load appear in a
# separate file ("cavslog_load.log" in $ZEPHYR_BASE) and not the
# device.log file that twister expects.
if [ "$(basename $1)" = "zephyr.elf" ]; then
# Standalone mode (argument is a path to zephyr.elf)
BLDDIR=$(dirname $(dirname $1))
DO_SIGN=1
DO_LOAD=1
DO_LOG=1
elif [ "$1" = "" ]; then
# Twister --device-serial-pty mode
DO_LOAD=1
DO_LOG=1
else
# Twister --west-flash mode
BLDDIR=$1
DO_SIGN=1
fi
IMAGE=$ZEPHYR_BASE/_cavstmp.ri
LOADLOG=$ZEPHYR_BASE/_cavsload_load.log
HOST_TOOLS=$HOST_ZEPHYR_BASE/boards/xtensa/intel_adsp_cavs15/tools
FWLOAD=$HOST_TOOLS/fw_loader.py
ADSPLOG=$HOST_TOOLS/adsplog.py
if [ "$DO_SIGN" = "1" ]; then
ELF=$BLDDIR/zephyr/zephyr.elf.mod
BOOT=$BLDDIR/zephyr/bootloader.elf.mod
$RIMAGE/rimage -v -k $KEY -o $IMAGE -c $RIMAGE/config/apl.toml \
-i 3 -e $BOOT $ELF > $BLDDIR/rimage.log
fi
if [ "$DO_LOAD" = "1" ]; then
while [ ! -e $IMAGE ]; do
sleep 0.1
done
scp $IMAGE $HOST:_cavstmp.ri
ssh $HOST "(lsmod | grep -q diag_driver) || sudo insmod $HOST_DRIVER"
# The script sometimes gets stuck
ssh $HOST "sudo pkill -f -9 fw_loader.py" || true
ssh $HOST "sudo $FWLOAD -f _cavstmp.ri || true" > $LOADLOG 2>&1
if [ "$DO_SIGN" = "1" ]; then
cat $LOADLOG
fi
sleep 1
rm -f $IMAGE
fi
if [ "$DO_LOG" = "1" ]; then
ssh $HOST "sudo pkill -f -9 adsplog.py" || true
ssh $HOST "sudo $ADSPLOG"
fi

View file

@ -1,65 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import os
import argparse
import logging
from lib.device import Device
from lib.etrace import Etrace
def parse_args():
arg_parser = argparse.ArgumentParser(description="Dump trace message")
arg_parser.add_argument("-o", "--output-file", default=None,
help="Save to output file")
arg_parser.add_argument("-d", "--debug", default=False, action='store_true',
help="Display debug information")
arg_parser.add_argument("-x", "--hexdump", default=False, action='store_true',
help="Display hexdump")
args = arg_parser.parse_args()
return args
def main():
""" Main Entry Point """
args = parse_args()
log_level = logging.INFO
if args.debug:
log_level = logging.DEBUG
logging.basicConfig(level=log_level, format="%(message)s")
dev = Device()
dev.open_device()
etrace = Etrace(dev)
etrace.print()
if args.hexdump:
etrace.hexdump()
if args.output_file:
etrace.save(args.output_file)
if __name__ == "__main__":
try:
main()
os._exit(0)
except KeyboardInterrupt: # Ctrl-C
os._exit(14)
except SystemExit:
raise
except BaseException:
import traceback
traceback.print_exc()
os._exit(16)

View file

@ -1,19 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
BUILD=$1
FIRMWARE=${BUILD}/zephyr/zephyr.ri
FLASHER=${ZEPHYR_BASE}/boards/xtensa/intel_adsp_cavs15/tools/fw_loader.py
if [ -z "$2" ]
then
echo "Signing using default key"
west sign -d ${BUILD} -t rimage
elif [ -n "$3" ] && [ -n "$4" ]
then
echo "Signing with key " $key
west sign -d ${BUILD} -t rimage -p $4 -D $3 -- -k $2 --no-manifest
fi
echo ${FLASHER} -f ${FIRMWARE}
${FLASHER} -f ${FIRMWARE} || /bin/true 2>&1

View file

@ -1,90 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import os
import argparse
import logging
from colorama import Fore, Style
from lib.loader import FirmwareLoader, FirmwareStatus
import lib.platforms as plat_def
def check_args(args):
# Check if firmware exists
firmware_abs = os.path.abspath(args.firmware)
if not os.path.exists(firmware_abs):
raise ValueError("File not found: %s" % firmware_abs)
def parse_args():
arg_parser = argparse.ArgumentParser(description="ADSP firmware loader")
arg_parser.add_argument("-f", "--firmware", required=True,
help="ADSP firmware file to load")
arg_parser.add_argument("-d", "--debug", default=False, action='store_true',
help="Display debug information")
args = arg_parser.parse_args()
check_args(args)
return args
def main():
""" Main Entry Point """
args = parse_args()
log_level = logging.INFO
if args.debug:
log_level = logging.DEBUG
logging.basicConfig(level=log_level, format="%(message)s")
logging.info("Start firmware downloading...")
fw_loader = FirmwareLoader()
# Use Stream #7 for firmware download DMA
fw_loader.init(plat_def.DMA_ID)
logging.info("Reset DSP...")
fw_loader.reset_dsp()
FirmwareStatus(fw_loader.dev.fw_status.value).print()
logging.info(" IPC CMD : %s" % fw_loader.dev.ipc_cmd)
logging.info(" IPC LEN : %s" % fw_loader.dev.ipc_len)
logging.info("Booting up DSP...")
fw_loader.boot_dsp()
FirmwareStatus(fw_loader.dev.fw_status.value).print()
fw_loader.wait_for_fw_boot_status(plat_def.BOOT_STATUS_INIT_DONE)
logging.info("Downloading firmware...")
fw_loader.download_firmware(args.firmware)
logging.info("Checking firmware status...")
if fw_loader.check_fw_boot_status(plat_def.BOOT_STATUS_FW_ENTERED):
logging.info(Fore.LIGHTGREEN_EX +
"Firmware download completed successfully"
+ Style.RESET_ALL)
logging.info("Reading IPC FwReady Message...")
fw_loader.ipc.read_fw_ready()
else:
logging.error(Fore.RED +
"!!!!! Failed to download firmware !!!!!"
+ Style.RESET_ALL)
fw_loader.close()
if __name__ == "__main__":
try:
main()
os._exit(0)
except KeyboardInterrupt: # Ctrl-C
os._exit(14)
except SystemExit:
raise
except BaseException:
import traceback
traceback.print_exc()
os._exit(16)

View file

@ -1,5 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

View file

@ -1,245 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import time
import logging
from ctypes import c_uint16, addressof
from lib.driver import DiagDriver, Register
import lib.registers as regs_def
import lib.platforms as plat_def
class Device:
def __init__(self):
self.__opened = False
self.drv = DiagDriver()
self.dev_info = None
self.hda_bar_mmap = None
self.dsp_bar_mmap = None
self.hda_gctl = None
self.hda_gcap = None
self.hda_ppctl = None
self.hda_spibe = None
self.dsp_ctl_sts = None
self.dsp_hipci = None
self.dsp_hipcie = None
self.dsp_hipct = None
self.fw_status = None
self.fw_err_code = None
self.ipc_len = None
self.ipc_cmd = None
self.allocated = []
def close(self):
if not self.__opened:
logging.warning("Audio device not opened!!!")
return
self.__opened = False
def open_device(self):
logging.debug(">>> Device.open_device()")
# Open device to get HDA BAR and DSP BAR
self.dev_info = self.drv.open_device()
# HDA MMAP
self.hda_bar_mmap = self.drv.mmap(self.dev_info.hda_bar.base_p,
self.dev_info.hda_bar.size)
self.dev_info.hda_bar.base_v = addressof(self.hda_bar_mmap)
# DSP MMAP
self.dsp_bar_mmap = self.drv.mmap(self.dev_info.dsp_bar.base_p,
self.dev_info.dsp_bar.size)
self.dev_info.dsp_bar.base_v = addressof(self.dsp_bar_mmap)
logging.debug(self.dev_info)
# Registers from HDA
self.hda_gctl = Register(self.hda_bar_mmap,
regs_def.HDA_GR_GCTL)
self.hda_gcap = Register(self.hda_bar_mmap,
regs_def.HDA_GR_GCAP, c_uint16)
self.hda_ppctl = Register(self.hda_bar_mmap,
regs_def.HDA_PPC_PPCTL)
self.hda_spibe = Register(self.hda_bar_mmap,
regs_def.HDA_SPBF_SPBFCTL)
# Registers from DSP
self.dsp_ctl_sts = Register(self.dsp_bar_mmap,
regs_def.ADSP_GR_ADSPCS)
self.dsp_hipci = Register(self.dsp_bar_mmap,
regs_def.ADSP_IPC_HIPCI)
self.dsp_hipcie = Register(self.dsp_bar_mmap,
regs_def.ADSP_IPC_HIPCIE)
self.dsp_hipct = Register(self.dsp_bar_mmap,
regs_def.ADSP_IPC_HIPCT)
self.fw_status = Register(self.dsp_bar_mmap,
plat_def.FW_STATUS)
self.fw_err_code = Register(self.dsp_bar_mmap,
plat_def.FW_ERR_CODE)
self.ipc_len = Register(self.dsp_bar_mmap,
plat_def.FW_MBOX_UPLINK + plat_def.IPC_GLOBAL_LEN)
self.ipc_cmd = Register(self.dsp_bar_mmap,
plat_def.FW_MBOX_UPLINK + plat_def.IPC_GLOBAL_CMD)
self.__opened = True
logging.debug("<<< Device.open_device()")
def alloc_memory(self, size):
logging.debug(">>> Device.alloc_memory()")
buf = self.drv.alloc_mem(size)
if buf.dma_addr_p == 0:
raise RuntimeError("Could not allocate the memory")
self.allocated.append(buf)
logging.debug("<<< Device.alloc_memory()")
return buf
def free_memory(self, mem):
logging.debug(">>> Device.free_memory()")
if mem in self.allocated:
ret = self.drv.free_mem(mem)
if ret != 0:
logging.error("Failed to free memory")
self.allocated.remove(mem)
else:
logging.warning("Cannot find the memory from list")
logging.debug("<<< Device.free_memory()")
def power_cycle(self):
logging.debug("Controller power down")
self.hda_gctl.value = 0
while self.hda_gctl.value != 0:
time.sleep(0.1)
logging.debug(" HDA_GCTL=%s" % self.hda_gctl)
logging.debug("Controller power up")
self.hda_gctl.value = 1
while self.hda_gctl.value != 1:
time.sleep(0.1)
logging.debug(" HDA_GCTL=%s" % self.hda_gctl)
def enable_proc_pipe_ctl(self):
logging.debug("Enable processing pipe control")
iss = ((self.hda_gcap.value & regs_def.HDA_GR_GCAP_ISS)
>> regs_def.HDA_GR_GCAP_ISS_OFFSET)
oss = ((self.hda_gcap.value & regs_def.HDA_GR_GCAP_OSS)
>> regs_def.HDA_GR_GCAP_OSS_OFFSET)
iss_mask = int("1" * iss, 2)
oss_mask = int("1" * oss, 2)
dma_mask = iss_mask + (oss_mask << iss)
# Enable processing pipe
self.hda_ppctl.value = self.hda_ppctl.value | 0x40000000 | dma_mask
logging.debug(" HDA_PPCTL=%s" % self.hda_ppctl)
def get_ipc_message(self):
logging.info("Read IPC message from DSP")
logging.info("IPC LEN: %s" % self.ipc_len)
logging.info("IPC CMD: %s" % self.ipc_cmd)
def core_reset_enter(self, core_mask):
# Set Reset Bit for cores
logging.debug("Enter core reset(mask=0x%08X)" % core_mask)
reset = core_mask << regs_def.ADSP_GR_ADSPCS_CRST_OFFSET
self._update_bits(self.dsp_ctl_sts, reset, reset)
# Check core entered reset
reg = self.dsp_ctl_sts.value
if (reg & reset) != reset:
raise RuntimeError("Reset enter failed: DSP_CTL_STS=%s core_maks=0x%08X"
% (self.dsp_ctl_sts, core_mask))
logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
def core_reset_leave(self, core_mask):
# Set Reset Bit for cores
logging.debug("Leave core reset(mask=0x%08X)" % core_mask)
leave = core_mask << regs_def.ADSP_GR_ADSPCS_CRST_OFFSET
self._update_bits(self.dsp_ctl_sts, leave, 0)
# Check core entered reset
reg = self.dsp_ctl_sts.value
if (reg & leave) != 0:
raise RuntimeError("Reset leave failed: DSP_CTL_STS=%s core_maks=0x%08X"
% (self.dsp_ctl_sts, core_mask))
logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
def core_stall_reset(self, core_mask):
logging.debug("Stall core(mask=0x%08X)" % core_mask)
stall = core_mask << regs_def.ADSP_GR_ADSPCS_CSTALL_OFFSET
self._update_bits(self.dsp_ctl_sts, stall, stall)
logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
self.core_reset_enter(core_mask)
def core_run(self, core_mask):
self.core_reset_leave(core_mask)
logging.debug("Run/Unstall core(mask=0x%08X)" % core_mask)
run = core_mask << regs_def.ADSP_GR_ADSPCS_CSTALL_OFFSET
self._update_bits(self.dsp_ctl_sts, run, 0)
logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
def core_power_down(self, core_mask):
logging.debug("Power down core(mask=0x%08X)" % core_mask)
mask = core_mask << regs_def.ADSP_GR_ADSPCS_SPA_OFFSET
self._update_bits(self.dsp_ctl_sts, mask, 0)
cnt = 0
while cnt < 10:
cpa = self.dsp_ctl_sts.value & regs_def.ADSP_GR_ADSPCS_CPA
mask = (core_mask & 0) << regs_def.ADSP_GR_ADSPCS_CPA_OFFSET
if cpa == mask:
logging.debug("Confirmed match value: 0x%04X" % cpa)
break
time.sleep(0.01)
cnt += 1
if cnt == 10:
logging.error(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
raise RuntimeError("Failed to power down the core")
logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
def core_power_up(self, core_mask):
logging.debug("Power Up core(mask=0x%08X)" % core_mask)
mask = core_mask << regs_def.ADSP_GR_ADSPCS_SPA_OFFSET
self._update_bits(self.dsp_ctl_sts, mask, mask)
cnt = 0
while cnt < 10:
cpa = self.dsp_ctl_sts.value & regs_def.ADSP_GR_ADSPCS_CPA
mask = core_mask << regs_def.ADSP_GR_ADSPCS_CPA_OFFSET
if cpa == mask:
logging.debug("Confirmed match value: 0x%04X" % cpa)
break
time.sleep(0.01)
cnt += 1
if cnt == 10:
logging.error(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
raise RuntimeError("Failed to power up the core")
logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts)
@staticmethod
def _update_bits(reg, mask, value):
old_val = reg.value
new_val = (old_val & ~mask) | (value & mask)
if old_val == new_val:
return False
reg.value = new_val
return True

View file

@ -1,241 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import os
import fcntl
import struct
import mmap
import logging
from ctypes import cast, POINTER, c_uint8, c_uint32, c_uint16, c_uint64,\
addressof, byref
# diag_driver file
DIAG_DRV_PATH = "/dev/hda"
# Diag Driver Definition - sof-diagnostic-driver/ioctl.h
# IOCTL definition
CMD_OPEN_DEVICE = 0x47
CMD_ALLOC_MEMORY = 0x3A
CMD_FREE_MEMORY = 0x3B
CMD_OPEN_DEVICE_LEN = 40
class HdaBar:
""" Data structure for HDA BAR information """
def __init__(self, raw):
self.base_p = 0
self.base_v = 0
self.size = 0
(self.base_p, self.base_v, self.size) = struct.unpack('=QQL', raw)
def __str__(self):
return " Base Physical Address: 0x%08X\n" \
" Base Virtual Address: 0x%08X\n" \
" Base Size: 0x%08X" \
% (self.base_p, self.base_v, self.size)
class HdaMemory:
""" Data structure for HDA memory allocation """
def __init__(self, size=0):
self.dma_addr_p = 0
self.dma_addr_v = 0
self.size = size
self.memmap = None
def set_value(self, raw):
(self.dma_addr_p,
self.dma_addr_v,
self.size) = struct.unpack('=QQL', raw)
def get_value(self):
data = bytearray(struct.pack('=QQL', self.dma_addr_p,
self.dma_addr_v,
self.size))
return data
def __str__(self):
return " DMA Physical Address: 0x%08X\n" \
" DMA Virtual Address: 0x%08X\n" \
" DMA Size: 0x%08X" \
% (self.dma_addr_p, self.dma_addr_v, self.size)
class HdaHandle:
""" Data structure for HDA handles """
def __init__(self, raw):
data = struct.unpack('20s20s', raw)
self.hda_bar = HdaBar(data[0])
self.dsp_bar = HdaBar(data[1])
def __str__(self):
output = (
"HDA BAR:\n"
"{hda}\n"
"DSP BAR:\n"
"{dsp}"
).format(
hda = self.hda_bar, dsp = self.dsp_bar
)
return output
class DiagDriver:
""" Interface for diag_driver """
def __init__(self):
self._handle = None
self._mem_map_list = []
self._buff_list = []
def open_device(self):
"""
Send CMD_OPEN_DEVICE and get HDA BAR and DSP BAR
Returns:
(handle)(obj:HdaHandle): HDA and DSP Bars objs
"""
logging.debug(">>> DiagDriver.open_device()")
# Allocate bytearry for HDABusTest_OpenDevice
buf = bytearray(CMD_OPEN_DEVICE_LEN)
logging.info("Open HDA device: %s" % DIAG_DRV_PATH)
# Send CMD_OPEN_DEVICE
with open(DIAG_DRV_PATH) as fd:
fcntl.ioctl(fd, CMD_OPEN_DEVICE, buf)
self._handle = HdaHandle(buf)
logging.debug("<<< DiagDriver.open_device()")
return self._handle
def alloc_mem(self, size):
"""
Send CMD_ALLOC_MEMORY to allocate DMA buffer
Returns:
hda_mem (obj:HDAMemory): Allocated DMA buffer information
"""
logging.debug(">>> Diag_Driver.alloc_mem(size=0x%08X)" % size)
hda_buf = HdaMemory(size)
# Allocate bytearray for HDABusTestMem
buf = hda_buf.get_value()
# Send CMD_ALLOC_MEMORY
with open(DIAG_DRV_PATH) as fd:
fcntl.ioctl(fd, CMD_ALLOC_MEMORY, buf)
hda_buf.set_value(buf)
mem = self.mmap(hda_buf.dma_addr_p, hda_buf.size)
hda_buf.memmap = mem
hda_buf.dma_addr_v = addressof(mem)
logging.debug("DMA Memory:\n%s" % hda_buf)
# Append to buffer list for later clean up.
self._buff_list.append(hda_buf)
logging.debug("<<< Diag_Driver.alloc_mem()")
return hda_buf
def free_mem(self, hda_buf):
"""
Send CMD_FREE_MEMORY to free the DMA buffer
Params:
had_mem (obj:HDAMemory): DMA buffer information to be freed
Returns:
0 for success, otherwise fail.
"""
logging.debug(">>> Diag_Driver.free_mem()")
if hda_buf not in self._buff_list:
logging.error("Cannot find buffer from the list")
raise ValueError("Cannot find buffer to free")
logging.debug("Buffer to Free:\n%s" % hda_buf)
buf = hda_buf.get_value()
# Send CMD_FREE_MEMORY
with open(DIAG_DRV_PATH) as fd:
ret = fcntl.ioctl(fd, CMD_FREE_MEMORY, buf)
self._buff_list.remove(hda_buf)
logging.debug("<<< Diag_Driver.free_mem()")
return ret
def mmap(self, addr, length):
"""
Setup mmap for HDA and DSP from /dev/mem
Returns:
(mem map,..)(uint32_t..): Array of uint32_t in mapped memory
"""
logging.debug(">>> Diag_Driver.mmap(addr=0x%08X, length=0x%08X)"
% (addr, length))
try:
fd = os.open(DIAG_DRV_PATH, os.O_RDWR)
mem_map = mmap.mmap(fd, length, offset=addr,
prot=mmap.PROT_READ | mmap.PROT_WRITE,
flags=mmap.MAP_SHARED)
self._mem_map_list.append(mem_map)
# Array of uint8
mem = (c_uint8 * length).from_buffer(mem_map)
finally:
os.close(fd)
logging.debug("<<< Diag_Driver.mmap()")
return mem
class Register:
def __init__(self, base_addr, offset, type=c_uint32):
self._type = type
self._obj = cast(byref(base_addr, offset), POINTER(type))
def __str__(self):
if self._type == c_uint8:
return "0x%02X" % self.value
elif self._type == c_uint16:
return "0x%04X" % self.value
elif self._type == c_uint32:
return "0x%08X" % self.value
elif self._type == c_uint64:
return "0x%08X %08X" % (
self.value >> 32,
self.value & 0xFFFFFFFF
)
else:
return "0x%08X (unknown type)" % self.value
@property
def value(self):
return self._obj.contents.value
@value.setter
def value(self, value):
self._obj[0] = value

View file

@ -1,71 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import logging
from ctypes import c_uint8, addressof
import lib.platforms as plat_def
import sys
sys.path.append('..')
from logtool import Loglist
def is_ascii(c):
if 32 <= c <= 126:
return str(chr(c))
else:
return "."
class Etrace:
def __init__(self, dev, win_id=3, size=0x2000):
self.drv = dev.drv
self.dsp_base_p = dev.dev_info.dsp_bar.base_p
self.win_id = win_id
self.size = size
self.offset = self.get_sram_win_offset(self.win_id)
# memory map MBOX UPLINK
self.mmap = self.drv.mmap(self.dsp_base_p + self.offset, self.size)
self.mmap_addr = addressof(self.mmap)
@staticmethod
def get_sram_win_offset(win_id):
return plat_def.FW_SRAM + (win_id * 0x20000)
def hexdump(self):
data = (c_uint8 * self.size).from_address(self.mmap_addr)
i = 1
s = ""
a = ""
offset = 0x00
for r in data:
s = s + ("%02X " % r)
a = a + ("%s" % is_ascii(r))
offset += 1
if not i % 16:
logging.info("0x%04X: %s %s" % ((offset - 16), s, a))
s = ""
a = ""
i += 1
if s:
logging.info("0x%04X: %s %s" % ((offset - 16), s, a))
def print(self):
l = Loglist(self.mmap_addr)
l.print()
def save(self, output_file):
data = (c_uint8 * self.size).from_address(self.mmap_addr)
with open(output_file, "wb+") as f:
f.write(data)

View file

@ -1,253 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import logging
from ctypes import Structure, c_uint64, c_uint32, c_uint16, \
c_uint8, addressof, sizeof
import lib.platforms as plat_def
# Global Message - Generic
IPC_GLB_TYPE_OFFSET = 28
IPC_GLB_TYPE_MASK = (0xF << IPC_GLB_TYPE_OFFSET)
# Command Message
IPC_CMD_TYPE_OFFSET = 16
IPC_CMD_TYPE_MASK = (0xFFF << IPC_CMD_TYPE_OFFSET)
# Message Type
IPC_FW_READY = 0x07 << IPC_GLB_TYPE_OFFSET
# Extended data types that can be appended onto end of IpCFwReady message
IpcExtData = {
0: 'IPC_EXT_DMA_BUFFER',
1: 'IPC_EXT_WINDOW'
}
# Extended Firmware Data
IpcRegion = {
0: 'IPC_REGION_DOWNBOX',
1: 'IPC_REGION_UPBOX',
2: 'IPC_REGION_TRACE',
3: 'IPC_REGION_DEBUG',
4: 'IPC_REGION_STREAM',
5: 'IPC_REGION_REGS',
6: 'IPC_REGION_EXCEPTION'
}
class IpcHdr(Structure):
""" Data structure for IPC Header """
_pack_ = 1
_fields_ = [
("size", c_uint32)
]
def __str__(self):
output = ("Size: 0x%08X" % self.size)
return output
class IpcCmdHdr(Structure):
""" Data structure for IPC Command Header """
_pack_ = 1
_fields_ = [
("size", c_uint32),
("cmd", c_uint32)
]
def __str__(self):
output = (
"IPC Command Hdr:\n"
" Command: {cmd:>10} (0x{cmd:0>8X})\n"
" Size: {size:>10} (0x{size:0>4X})"
).format(
size = self.size,
cmd = self.cmd
)
return output
class IpcFwVersion(Structure):
""" Data structure for IPC FwVersion message """
_pack_ = 1
_fields_ = [
("hdr", IpcHdr),
("major", c_uint16),
("minor", c_uint16),
("micro", c_uint16),
("build", c_uint16),
("date", c_uint8 * 12),
("time", c_uint8 * 10),
("tag", c_uint8 * 6),
("abi_version", c_uint32),
("reserved", c_uint32 * 4)
]
def __str__(self):
output = (
"Firmware Version:\n"
" Major version: {major: >5} (0x{major:0>4X})\n"
" Minor version: {minor: >5} (0x{minor:0>4X})\n"
" Micro number: {micro: >5} (0x{micro:0>4X})\n"
" Build number: {build: >5} (0x{build:0>4X})\n"
" Date: {date: >24}\n"
" Time: {time: >24}\n"
" Tag: {tag: >24}\n"
" Abi version: {abi_version: >5} (0x{abi_version:0>4X})"
).format(
major = self.major,
minor = self.minor,
micro = self.micro,
build = self.build,
date=''.join([chr(i) for i in list(self.date)]),
time=''.join([chr(i) for i in list(self.time)]),
tag=''.join([chr(i) for i in list(self.tag)]),
abi_version = self.abi_version)
return output
class IpcFwReady(Structure):
""" Data structure for IpcFwReady message """
_pack_ = 1
_fields_ = [
("hdr", IpcCmdHdr),
("dspbox_offset", c_uint32),
("hostbox_offset", c_uint32),
("dspbox_size", c_uint32),
("hostbox_size", c_uint32),
("version", IpcFwVersion),
("flags", c_uint64),
("reserved", c_uint32 * 4)
]
def __str__(self):
output = (
"IPC Firmware Ready Message: (0x{cmd:0>8X}) (0x{size:0>8X})\n"
" DSP box offset: {dsp_offset: >5} (0x{dsp_offset:0>4X})\n"
" Host box offset:{host_offset: >5} (0x{host_offset:0>4X})\n"
" DSP box size: {dsp_size: >5} (0x{dsp_size:0>4X})\n"
" Host box size: {host_size: >5} (0x{host_size:0>4X})\n\n"
"{version}\n\n"
"Flags:"
" 0x{flags:0>8X}"
).format(
cmd = self.hdr.cmd,
size = self.hdr.size,
dsp_offset = self.dspbox_offset,
host_offset = self.hostbox_offset,
dsp_size = self.dspbox_size,
host_size = self.hostbox_size,
version = str(self.version),
flags = self.flags
)
return output
class IpcExtDataHdr(Structure):
""" Data structure for IPC extended data header """
_pack_ = 1
_fields_ = [
("hdr", IpcCmdHdr),
("type", c_uint32)
]
class IpcWindowElem(Structure):
""" Data structure for Window Element message """
_pack_ = 1
_fields_ = [
("hdr", IpcHdr),
("type", c_uint32),
("id", c_uint32),
("flags", c_uint32),
("size", c_uint32),
("offset", c_uint32)
]
def __str__(self):
output = (
"Window type: {type_str:>20} ({type:d})\n"
"Window id: {id: >5}\n"
"Window flags: {flags: >5} (0x{flags:0>4X})\n"
"Window size: {size: >5} (0x{size:0>4X})\n"
"Window offset: {offset: >5} (0x{offset:0>4X})\n"
).format(
type_str = IpcRegion[self.type],
type = self.type,
id = self.id,
flags = self.flags,
size = self.size,
offset = self.offset
)
return output
class IpcWindow(Structure):
""" Data structure for extended data memory windows """
_pack_ = 1
_fields_ = [
("ext_hdr", IpcExtDataHdr),
("num_windows", c_uint32),
]
def __str__(self):
output = ("\n"
"IPC Firmware Ready Extended Message: (0x{cmd:0>8X}) (0x{size:0>8X})\n"
"Message Type: {ext_type: >5d} ({ext_type_str})\n\n"
"Number of Windows: {num_windows: >2d}\n"
).format(
cmd = self.ext_hdr.hdr.cmd,
size = self.ext_hdr.hdr.size,
ext_type = self.ext_hdr.type,
ext_type_str = IpcExtData[self.ext_hdr.type],
num_windows = int(self.num_windows)
)
return output
class Ipc:
""" Class for IPC handle """
def __init__(self, dev):
self.drv = dev.drv
self.dsp_base_p = dev.dev_info.dsp_bar.base_p
# memory map MBOX UPLINK
self.mmap = self.drv.mmap(self.dsp_base_p + (plat_def.FW_MBOX_UPLINK),
plat_def.FW_MBOX_SIZE)
self.mmap_addr = addressof(self.mmap)
def read_fw_ready(self):
""" FwReady message consist of two messages:
1. FwReady
2. ExtendedData
"""
msg = IpcFwReady.from_address(self.mmap_addr)
logging.info(str(msg))
self.read_fw_ready_ext()
def read_fw_ready_ext(self):
addr_offset = self.mmap_addr + sizeof(IpcFwReady())
msg = IpcWindow.from_address(addr_offset)
logging.info(str(msg))
# Extended Windows data type
if msg.ext_hdr.type != 1:
raise RuntimeError("Not Implemented: ext_hdr.type != 1")
win_elem_list = []
addr_offset += sizeof(IpcWindow())
num_win = int(msg.num_windows)
for _ in range(num_win):
win_elem = IpcWindowElem.from_address(addr_offset)
win_elem_list.append(win_elem)
addr_offset += sizeof(IpcWindowElem())
for elem in win_elem_list:
logging.info(str(elem))

View file

@ -1,202 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import time
import logging
import array
from lib.stream_desc import StreamDescList
from lib.device import Device
from lib.ipc import Ipc
import lib.registers as regs_def
import lib.platforms as plat_def
class FirmwareStatus():
""" Data structure for Firmware Status register """
def __init__(self, value=None):
self.value = None
self.boot_state = None
self.wait_state = None
self.moudle = None
self.error = None
if value:
self.set(value)
def set(self, value):
self.value = value
self.boot_state = self.value & plat_def.FW_STATUS_BOOT_STATE
self.wait_state = ((self.value & plat_def.FW_STATUS_WAIT_STATE)
>> plat_def.FW_STATUS_WAIT_STATE_OFFSET)
self.moudle = ((self.value & plat_def.FW_STATUS_MODULE)
>> plat_def.FW_STATUS_MODULE_OFFSET)
self.error = ((self.value & plat_def.FW_STATUS_ERROR)
>> plat_def.FW_STATUS_ERROR_OFFSET)
def __str__(self):
return "0x%08X" % self.value
def print(self):
output = ("Firmware Status Register (%s)\n"
" Boot: 0x%06X (%s)\n"
" Wait: 0x%02X (%s)\n"
" Module: 0x%02X\n"
" Error: 0x%02X" %
(self,
self.boot_state, plat_def.BOOT_STATUS_STR(self.boot_state),
self.wait_state, plat_def.WAIT_STATUS_STR(self.wait_state),
self.moudle, self.error))
logging.info(output)
class FirmwareLoader():
def __init__(self):
self._init_done = False
self.dma_id = None
self.dev = None
self.sdl = None
def init(self, dma_id):
if self._init_done:
logging.warning("Already initialized! Skip init")
return
self.dma_id = dma_id
self.dev = Device()
self.dev.open_device()
self.sdl = StreamDescList(self.dev)
self.ipc = Ipc(self.dev)
self._init_done = True
def close(self):
if not self._init_done:
logging.warning("Not initialized! Skip closing.")
return
self.sdl.close()
self.dev.close()
self._init_done = False
def reset_dsp(self):
logging.debug(">>> FirmwareLoader.reset_dsp()")
logging.debug("Recycling controller power...")
self.dev.power_cycle()
# This should be enabled prior to power down the cores.
self.dev.enable_proc_pipe_ctl()
logging.debug("Power down cores...")
self.dev.core_stall_reset(plat_def.CORE_MASK)
self.dev.core_power_down(plat_def.CORE_MASK)
logging.debug("<<< FirmwareLoader.reset_dsp()")
def boot_dsp(self):
logging.debug(">>> FirmwareLoader.boot_dsp()")
self.dev.enable_proc_pipe_ctl()
self.sdl.reset_all()
self.dev.core_power_up(0x1)
self.dev.dsp_hipct.value = self.dev.dsp_hipct.value
logging.debug("Purging pending FW request")
boot_config = plat_def.FW_IPC_PURGE | regs_def.ADSP_IPC_HIPCI_BUSY
boot_config = boot_config | ((self.dma_id - 7) << 9)
self.dev.dsp_hipci.value = boot_config
time.sleep(0.1)
logging.debug(" DSP_HIPCI=%s" % self.dev.dsp_hipci)
self.dev.core_power_up(plat_def.CORE_MASK)
self.dev.core_run(plat_def.CORE_0)
self.dev.core_run(plat_def.CORE_1)
logging.debug("Wait for IPC DONE bit from ROM")
while True:
ipc_ack = self.dev.dsp_hipcie.value
if (ipc_ack & (1 << regs_def.ADSP_IPC_HIPCIE_DONE_OFFSET)) != 0:
break
time.sleep(0.1)
logging.debug("<<< FirmwareLoader.boot_dsp()")
def check_fw_boot_status(self, expected):
logging.debug(">>> FirmwareLoader.check_fw_boot_status(0x%08X)" % expected)
raw_status = self.dev.fw_status.value
FirmwareStatus(raw_status).print()
if (raw_status & plat_def.FW_STATUS_ERROR) != 0:
output = ("Firmware Status error:"
" Status: 0x%08X\n"
" Error Code 0x%08X" %
(raw_status, self.dev.fw_err_code.value))
raise RuntimeError(output)
status = raw_status & plat_def.FW_STATUS_BOOT_STATE
logging.debug("<<< FirmwareLoader.check_fw_boot_status()")
return status == expected
def wait_for_fw_boot_status(self, boot_status):
logging.debug("Waiting for FW Boot Status: 0x%08X (%s)"
% (boot_status,
plat_def.BOOT_STATUS_STR(boot_status)))
for _ in range(10):
reg = self.dev.fw_status.value
bs = reg & plat_def.FW_STATUS_BOOT_STATE
if bs == boot_status:
logging.debug("Received Expected Boot Status")
return True
time.sleep(0.01)
logging.error("Failed to receive expected status")
return False
def wait_for_fw_wait_status(self, wait_status):
logging.debug("Waiting for FW Wait Status: 0x%08X (%s)"
% (wait_status,
plat_def.WAIT_STATUS_STR(wait_status)))
for _ in range(10):
reg = self.dev.fw_status.value
ws = reg & plat_def.FW_STATUS_WAIT_STATE
if ws == (wait_status << plat_def.FW_STATUS_WAIT_STATE_OFFSET):
logging.debug("Received Expected Wait Status")
return True
time.sleep(0.01)
logging.error("Failed to receive expected status")
return False
def load_firmware(self, fw_file):
logging.debug(">>> FirmwareLoader.load_firmware()")
with open(fw_file, "rb") as fd:
data = array.array('B', fd.read())
sd = self.sdl.get_sd(self.dma_id)
sd.enable = True
sd.alloc_memory(len(data))
sd.buf.copy(data, len(data))
sd.config()
sd.set_stream_id(1)
sd.set_traffic_priority(1)
sd.set_bitrate(0x4)
time.sleep(0.1)
logging.debug("<<< FirmwareLoader.load_firmware()")
return sd
def download_firmware(self, fw_file):
logging.debug(">>> FirmwareLoader.download_firmware(fw_file=%s)" % fw_file)
# Load firmware to DMA buffer and update SD and SDL
sd = self.load_firmware(fw_file)
try:
self.dev.hda_spibe.value |= (1 << self.dma_id)
self.wait_for_fw_wait_status(plat_def.WAIT_STATUS_DMA_BUFFER_FULL)
logging.info("Start firmware downloading...")
sd.start()
time.sleep(0.5)
self.wait_for_fw_boot_status(plat_def.BOOT_STATUS_FW_ENTERED)
finally:
sd.pause()
sd.reset()
self.sdl.release_sd(sd.idx)
self.dev.hda_spibe.value = 0
logging.debug("<<< FirmwareLoader.download_firmware()")

View file

@ -1,56 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
from ctypes import string_at
MAGIC = 0x55aa
SLOT_LEN = 64
SLOT_NUM = int(8192 / SLOT_LEN)
def read_bytes(buffer):
return int.from_bytes(buffer, byteorder='little')
class Loglist:
"""Loglist class"""
def __init__(self, argument, debug=False):
"""Constructor for the loglist takes argument filename or buffer"""
if isinstance(argument, str):
f = open(argument, "rb")
self.buffer = f.read(SLOT_NUM * SLOT_LEN)
elif isinstance(argument, int):
self.buffer = string_at(argument, SLOT_NUM * SLOT_LEN)
else:
return
self.loglist = []
self.parse()
self.debug = debug
def parse_slot(self, slot):
magic = read_bytes(slot[0:2])
if magic == MAGIC:
# Sequence number starting from 1, see
# soc/xtensa/intel_adsp/common/trace_out.c
id_num = read_bytes(slot[2:4])
before_first_zero = slot[4:].split(b'\x00')[0]
logstr = before_first_zero.decode(errors='replace')
self.loglist.append((id_num, logstr))
def parse(self):
for x in range(0, SLOT_NUM):
slot = self.buffer[x * SLOT_LEN : (x + 1) * SLOT_LEN]
self.parse_slot(slot)
def print(self):
for pair in sorted(self.loglist):
if self.debug:
# Add slot number when debug is enabled
print('{{[{}] : {}}}; '.format(*pair), end='')
else:
print('{}'.format(pair[1]), end='')

View file

@ -1,92 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
from enum import Enum
# BXT
# CORE ID MASK
CORE_0 = 0x1
CORE_1 = 0x2
CORE_MASK = 0x3
# Number of Input Streams Supported (GCAP[11:8])
NUM_ISS = 6
# Number of Output Streams Supported (GCAP[15:12])
NUM_OSS = 7
# Total Number of Streams supported
NUM_STREAMS = NUM_ISS + NUM_OSS
# DMA Index for FW download
DMA_ID = 7
# DMA Page Size
DMA_PAGE_SIZE = 0x1000
# FW Registers in SRAM
FW_SRAM = 0x80000
FW_REGS = FW_SRAM + 0x00
FW_MBOX_UPLINK = FW_SRAM + 0x1000
FW_MBOX_DWLINK = FW_SRAM + 0x20000
FW_MBOX_SIZE = 0x1000
# FW Status Register
FW_STATUS = FW_REGS + 0x0000
FW_STATUS_BOOT_STATE = 0x00FFFFFF
FW_STATUS_BOOT_STATE_OFFSET = 0
FW_STATUS_WAIT_STATE = 0x0F000000
FW_STATUS_WAIT_STATE_OFFSET = 24
FW_STATUS_MODULE = 0x70000000
FW_STATUS_MODULE_OFFSET = 28
FW_STATUS_ERROR = 0x80000000
FW_STATUS_ERROR_OFFSET = 31
class BOOT_STATUS(Enum):
INIT = 0
INIT_DONE = 1
FW_ENTERED = 5
def BOOT_STATUS_STR(status):
try:
e = BOOT_STATUS(status)
except Exception:
return "UNKNOWN"
return e.name
# Boot Status
BOOT_STATUS_INIT = 0x00
BOOT_STATUS_INIT_DONE = 0x01
BOOT_STATUS_FW_ENTERED = 0x05
class WAIT_STATUS(Enum):
DMA_BUFFER_FULL = 5
def WAIT_STATUS_STR(status):
try:
e = WAIT_STATUS(status)
except Exception:
return "UNKNOWN"
return e.name
# Wait Status
WAIT_STATUS_DMA_BUFFER_FULL = 0x05
# FW Error Status
FW_ERR_CODE = FW_SRAM + 0x0004
# IPC Purge FW message
FW_IPC_PURGE = 0x01004000
# IPC GLOBAL LENGTH register
IPC_GLOBAL_LEN = 0x00
IPC_GLOBAL_CMD = 0x04

View file

@ -1,150 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
# Registers
######################################
# High Definition Audio Memory Space #
######################################
# HDA Register Blocks
HDA_GR_BASE = 0x0000 # HDA Global Register Block
HDA_SD_BASE = 0x0080 # HDA Stream Descriptor Register Block - index 0
HDA_SPBF_BASE = 0x0700 # HDA Software Position Based FIFO Capability Structure
HDA_PPC_BASE = 0x0800 # HDA Processing Pipe Capabilities Structure
# Global Capabilities
HDA_GR_GCAP = HDA_GR_BASE + 0x0000
HDA_GR_GCAP_ISS = 0x0F00 # Number of Input Streams Supported
HDA_GR_GCAP_ISS_OFFSET = 8 # Number of Input Streams Supported Offset
HDA_GR_GCAP_OSS = 0xF000 # Number of Output Streams Supported
HDA_GR_GCAP_OSS_OFFSET = 12 # Number of Offset Streams Supported Offset
# Golbal Control
HDA_GR_GCTL = HDA_GR_BASE + 0x0008
# Stream Descriptor X Control/Status - only within the blcok
HDA_SD_CS = 0x0000
HDA_SD_CS_SRST = 0x000001 # Stream Reset
HDA_SD_CS_SRST_OFFSET = 0 # Stream Reset Offset
HDA_SD_CS_RUN = 0x000002 # Stream Run
HDA_SD_CS_RUN_OFFSET = 1 # Stream Run Offset
HDA_SD_CS_TP = 0x040000 # Traffic Priority
HDA_SD_CS_TP_OFFSET = 18 # Traffic Priority Offset
HDA_SD_CS_STRM = 0xF00000 # Stream Number
HDA_SD_CS_STRM_OFFSET = 20 # Stream Number Offset
# Stream Descriptor X Link Position in Buffer
HDA_SD_LPIB = 0x0004
# Stream Descriptor X Cyclic Buffer Length
HDA_SD_CBL = 0x0008
# Stream Descriptor X Last Valid Index
HDA_SD_LVI = 0x000C
# Stream Descriptor X FIFO Eviction Watermark
HDA_SD_FIFOW = 0x000E
# Stream Descriptor X FIFO Size
HDA_SD_FIFOS = 0x0010
# Stream Descriptor X Format
HDA_SD_FMT = 0x0012
HDA_SD_FMT_BITS = 0x00F0 # Bit Rate
HDA_SD_FMT_BITS_OFFSET = 4 # Bit Rate Offset
# Stream Descriptor X FIFO Limit
HDA_SD_FIFOL = 0x0014
# Stream Descriptor X Buffer Descriptor List Pointer Lower Base Address
HDA_SD_BDLPLBA = 0x0018
# Stream Descriptor X Buffer Descriptor List Pointer Upper Base Address
HDA_SD_BDLPUBA = 0x001C
# Stream Descriptor Size
HDA_SD_SIZE = 0x20
# Software Position Based FIFO Capability Control
HDA_SPBF_SPBFCTL = HDA_SPBF_BASE + 0x0004
HDA_SPBF_SPBFCTL_SPIBE = 0xFFFFFFFF # Software Position in Buffer Enable
HDA_SPBF_SPBFCTL_SPIBE_OFFSET = 0 # Software Position in Buffer Enable Offset
# Stream Descriptor X Software Position in Buffer
HDA_SPBF_SD_BASE = HDA_SPBF_BASE + 0x0008
HDA_SPBF_SDSPIB = 0x00
# Stream Descriptor X Max FIFO Size
HDA_SPBF_SDMAXFIFOS = 0x04
# Software Position Based FIFO Stream Descritpro Size
HDA_SPBF_SD_SIZE = 0x08
# Processing Pipe Control
HDA_PPC_PPCTL = HDA_PPC_BASE + 0x0004
HDA_PPC_PPCTL_PROCEN = 0x3FFFFFFF # Processing Enable
HDA_PPC_PPCTL_PROCEN_OFFSET = 0 # Processing Enable Offset
HDA_PPC_PPCTL_GPROCEN = 0x40000000 # Global Processing Enable
HDA_PPC_PPCTL_GPROCEN_OFFSET = 30 # Global Processing Enable Offset
# ADSP Register Blocks
ADSP_GR_BASE = 0x0000 # ADSP General DSP Registers
ADSP_IPC_BASE = 0x0040 # ADSP IPC Register
# ADSP Control & Status
ADSP_GR_ADSPCS = ADSP_GR_BASE + 0x0004
ADSP_GR_ADSPCS_CRST = 0x000000FF # Core Reset
ADSP_GR_ADSPCS_CRST_OFFSET = 0 # Core Reset Offset
ADSP_GR_ADSPCS_CSTALL = 0x0000FF00 # Core Run#/Stall
ADSP_GR_ADSPCS_CSTALL_OFFSET = 8 # Core Run#/Stall Offset
ADSP_GR_ADSPCS_SPA = 0x00FF0000 # Set Power Active
ADSP_GR_ADSPCS_SPA_OFFSET = 16 # Set Power Active Offset
ADSP_GR_ADSPCS_CPA = 0xFF000000 # Current Power Active
ADSP_GR_ADSPCS_CPA_OFFSET = 24 # Current Power Active Offset
# ADSP Interrupt Control
ADSP_GR_ADSPIC = ADSP_GR_BASE + 0x0008
ADSP_GR_ADSPIC_IPC = 0x00000001 # IPC Interrupt
ADSP_GR_ADSPIC_IPC_OFFSET = 0 # IPC Interrupt Offset
ADSP_GR_ADSPIC_CLDMA = 0x00000002 # Code Loader DMA Interrupt
ADSP_GR_ADSPIC_CLDMA_OFFSET = 1 # Code Loader DMA Interrupt Offset
# ADSP IPC DSP to Host
ADSP_IPC_HIPCT = ADSP_IPC_BASE + 0x0000
ADSP_IPC_HIPCT_BUSY = 0x80000000 # Busy
ADSP_IPC_HIPCT_BUSY_OFFSET = 31 # Busy Offset
ADSP_IPC_HIPCT_MSG = 0x7FFFFFFF # Message
ADSP_IPC_HIPCT_MSG_OFFSET = 0 # Message Offset
# ADSP IPC DSP to Host Extension
ADSP_IPC_HIPCTE = ADSP_IPC_BASE + 0x0004
ADSP_IPC_HIPCTE_MSGEXT = 0x3FFFFFFF # Message Extension
ADSP_IPC_HIPCTE_MSGEXT_OFFSET = 0 # Message Extension Offset
# ADSP IPC Host to DSP
ADSP_IPC_HIPCI = ADSP_IPC_BASE + 0x0008
ADSP_IPC_HIPCI_BUSY = 0x80000000 # Busy
ADSP_IPC_HIPCI_BUSY_OFFSET = 31 # Busy Offset
ADSP_IPC_HIPCI_MSG = 0x7FFFFFFF # Message
ADSP_IPC_HIPCI_MSG_OFFSET = 0 # Message Offset
# ADSP IPC Host to DSP Extension
ADSP_IPC_HIPCIE = ADSP_IPC_BASE + 0x000C
ADSP_IPC_HIPCIE_ERR = 0x80000000 # Error
ADSP_IPC_HIPCIE_ERR_OFFSET = 31 # Error Offset
ADSP_IPC_HIPCIE_DONE = 0x40000000 # Done
ADSP_IPC_HIPCIE_DONE_OFFSET = 30 # Done Offset
ADSP_IPC_HIPCIE_MSGEXT = 0x3FFFFFFF # Message Extension
ADSP_IPC_HIPCIE_MSGEXT_OFFSET = 0 # Message Extension Offset
# ADSP IPC Control
ADSP_IPC_HIPCCTL = ADSP_IPC_BASE + 0x0010
ADSP_IPC_HIPCCTL_IPCTBIE = 0x00000001 # IPC Target Busy Interrupt Enable
ADSP_IPC_HIPCCTL_IPCTBIE_OFFSET = 0 # IPC Target Busy Interrupt Enable Offset
ADSP_IPC_HIPCCTL_IPCIDIE = 0x00000002 # IPC Initiator Done Interrupt Enable
ADSP_IPC_HIPCCTL_IPCIDIE_OFFSET = 1 # IPC Initiator Done Interrupt Enable Offset

View file

@ -1,228 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import math
import logging
from time import sleep
from ctypes import c_uint16, POINTER, cast, c_uint8, c_uint64
from lib.driver import Register
import lib.registers as regs_def
import lib.platforms as plat_def
class DmaBuf:
""" Class for DMA buffer """
def __init__(self, drv, size):
self.drv = drv
self.size = size
# Allocated DMA buffer should be a multiplication of page size
self.page_count = math.ceil(self.size / plat_def.DMA_PAGE_SIZE)
logging.debug("Page Count: %d" % self.page_count)
self.alloc_size = self.page_count * plat_def.DMA_PAGE_SIZE
logging.debug("Allocate DMA Buffer: size=0x%08X alloc_size=0x%08X"
% (self.size, self.alloc_size))
self.mem = self.drv.alloc_mem(self.alloc_size)
self.addr_p = self.mem.dma_addr_p
self.buf = cast(self.mem.dma_addr_v,
POINTER(c_uint8 * self.alloc_size)).contents
def copy(self, data, size):
""" Copying data to allocated DMA buffer """
if size > self.alloc_size:
raise ValueError("Not enough buffer. allocated: %d requested: %d"
% (self.alloc_size, size))
logging.debug("Copying Data to DMA buffer")
self.buf[:size] = data[:size]
def free(self):
if self.mem:
self.drv.free_mem(self.mem)
self.mem = None
class DmaBufDescList:
""" Class DMA Buffer Descriptor List """
def __init__(self, drv, fw_buf):
self.drv = drv
self.bd_count = fw_buf.page_count
# Single Page for Buffer Descriptor List
self.buf = DmaBuf(drv, plat_def.DMA_PAGE_SIZE)
curr_ptr = 0
# Map BDLE with data buffer
logging.debug("Update Buffer Descriptor List:")
for i in range(self.bd_count):
bdle_addr = Register(self.buf.mem.memmap, (i * 16) + 0x00, c_uint64)
bdle_len = Register(self.buf.mem.memmap, (i * 16) + 0x08)
bdle_ioc = Register(self.buf.mem.memmap, (i * 16) + 0x0C)
if fw_buf.alloc_size - curr_ptr > plat_def.DMA_PAGE_SIZE:
bdle_len.value = plat_def.DMA_PAGE_SIZE
bdle_ioc.value = 0
bdle_addr.value = fw_buf.addr_p + curr_ptr
else:
bdle_len.value = fw_buf.alloc_size - curr_ptr
bdle_ioc.value = 1
bdle_addr.value = fw_buf.addr_p + curr_ptr
logging.debug(" BDLE#%02d: ADDR: %s LEN: %s IOC: %s"
% (i, bdle_addr, bdle_len, bdle_ioc))
break
curr_ptr += plat_def.DMA_PAGE_SIZE
logging.debug(" BDLE#%02d: ADDR: %s LEN: %s IOC: %s"
% (i, bdle_addr, bdle_len, bdle_ioc))
def free(self):
if self.buf:
self.drv.free_mem(self.buf.mem)
self.buf = None
class StreamDesc:
""" Class for Stream Descriptor """
def __init__(self, idx, dev):
self.idx = idx
self.dev = dev
self.used = False
self.buf = None
self.bdl = None
offset = regs_def.HDA_SD_BASE + (regs_def.HDA_SD_SIZE * (idx))
# Registers in SD
self.ctl_sts = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_CS)
self.lpib = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_LPIB)
self.cbl = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_CBL)
self.lvi = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_LVI, c_uint16)
self.fifow = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_FIFOW, c_uint16)
self.fifos = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_FIFOS, c_uint16)
self.fmt = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_FMT, c_uint16)
self.fifol = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_FIFOL)
self.bdlplba = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_BDLPLBA)
self.bdlpuba = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SD_BDLPUBA)
# Register for SPIB
offset = regs_def.HDA_SPBF_SD_BASE + (regs_def.HDA_SPBF_SD_SIZE * (idx))
self.sdspib = Register(self.dev.hda_bar_mmap,
offset + regs_def.HDA_SPBF_SDSPIB)
def free_memory(self):
if self.buf is not None:
self.buf.free()
self.buf = None
if self.bdl is not None:
self.bdl.free()
self.bdl = None
def alloc_memory(self, size):
self.free_memory()
self.buf = DmaBuf(self.dev.drv, size)
self.bdl = DmaBufDescList(self.dev.drv, self.buf)
def config(self):
self.bdlplba.value = self.bdl.buf.addr_p & 0xFFFFFFFF
self.bdlpuba.value = self.bdl.buf.addr_p >> 32
self.cbl.value = self.buf.size
self.lvi.value = self.bdl.bd_count - 1
self.sdspib.value = self.cbl.value
def set_bitrate(self, bit_rate):
logging.debug("SD#%02d: Set Bitrate: 0x%04X" % (self.idx, bit_rate))
sdfmt = self.fmt.value
sdfmt |= (bit_rate << 4)
self.fmt.value = sdfmt
logging.debug("SD#%02d: SD_FMT=%s" % (self.idx, self.fmt))
def set_stream_id(self, stream_id):
logging.debug("SD#%02d: Set Stream ID: 0x%04X" % (self.idx, stream_id))
sd_ctl = self.ctl_sts.value
sd_ctl &= ~(0xF << 20)
sd_ctl |= (stream_id << 20)
self.ctl_sts.value = sd_ctl
logging.debug("SD#%02d: SD_CTL_STS=%s" % (self.idx, self.ctl_sts))
def set_traffic_priority(self, value):
logging.debug("SD#%02d: Set Traffic Priority(0x%02X)" % (self.idx, value))
sd_ctl = self.ctl_sts.value
sd_ctl |= (value << 18)
self.ctl_sts.value = sd_ctl
logging.debug("SD#%02d: SD_CTL_STS=%s" % (self.idx, self.ctl_sts))
def start(self):
""" Start DMA transfer """
logging.debug("SD#%02d: Start DMA stream" % self.idx)
self.ctl_sts.value = self.ctl_sts.value | (1 << 1)
logging.debug("SD#%02d: SD_CTL_STS=%s" % (self.idx, self.ctl_sts))
while self.ctl_sts.value & (1 << 1) == 0:
sleep(0.001)
def pause(self):
logging.debug("SD#%02d: Pause DMA stream" % self.idx)
self.ctl_sts.value = self.ctl_sts.value & ~(1 << 1)
while self.ctl_sts.value & (1 << 1):
sleep(0.001)
def reset(self):
logging.debug("SD#%02d: Reset DAM stream" % self.idx)
self.pause()
self.ctl_sts.value = self.ctl_sts.value | 1
sleep(0.01)
self.ctl_sts.value = self.ctl_sts.value & ~1
sleep(0.01)
class StreamDescList:
""" Class for DMA Stream Descriptor List """
def __init__(self, dev):
self.dev = dev
self.sdl = []
for i in range(plat_def.NUM_STREAMS):
sd = StreamDesc(i, self.dev)
self.sdl.append(sd)
def close(self):
for sd in self.sdl:
if sd.used:
self.release(sd)
def reset_all(self):
for sd in self.sdl:
sd.reset()
def get_sd(self, idx):
sd = self.sdl[idx]
if sd.used:
raise ResourceWarning("IOB #%d already in use!" % idx)
sd.used = True
return sd
def release(self, sd):
return self.release_sd(sd.idx)
def release_sd(self, idx, reset_hw=True):
if not self.sdl[idx].used:
logging.warning("SD#%d: Not used!!!" % idx)
self.sdl[idx].used = False
if reset_hw:
self.sdl[idx].pause()
self.sdl[idx].reset()
self.sdl[idx].free_memory()

View file

@ -1,53 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
"""Logging reader tool"""
import argparse
import os
import sys
from lib.loglist import Loglist
QEMU_ETRACE = "/dev/shm/qemu-bridge-hp-sram-mem"
SOF_ETRACE = "/sys/kernel/debug/sof/etrace"
def parse_args():
"""Parsing command line arguments"""
parser = argparse.ArgumentParser(description='Logging tool')
parser.add_argument('-e', '--etrace', choices=['sof', 'qemu'], default="sof",
help="Specify the trace target")
parser.add_argument('-f', '--file', help="Specify the trace file created by"
" dump_trace tool")
args = parser.parse_args()
return args
def main():
"""Main"""
args = parse_args()
if os.geteuid() != 0:
sys.exit("Please run this program as root / sudo")
if args.file is not None:
etrace = args.file
else:
if args.etrace == 'sof':
etrace = SOF_ETRACE
else:
etrace = QEMU_ETRACE
l = Loglist(etrace)
l.print()
if __name__ == "__main__":
main()

View file

@ -1,66 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2020 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
from time import sleep
from mmap import mmap, ACCESS_COPY
from ctypes import c_uint8
from lib.device import Device
import lib.registers as regs
MBOX = 0x91281000
LENGTH = 0x1000
with open("/dev/mem", "rb") as f:
mem_map = mmap(f.fileno(), LENGTH, access=ACCESS_COPY, offset=MBOX)
mem = (c_uint8 * LENGTH).from_buffer(mem_map)
def mailbox_poll_mem(dev):
while True:
if dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_BUSY:
# Use only id for passing character
line_len = dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_MSG
# Mask out internal bits
line_len &= 0x10FFFF
if line_len:
print(bytes(mem[:line_len]).decode())
# Clear interrupt
dev.dsp_hipct.value |= regs.ADSP_IPC_HIPCT_BUSY
else:
sleep(0.005)
# Character passed in mailbox ID field
def mailbox_poll_char(dev):
while True:
if dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_BUSY:
# Use only id for passing character
character = dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_MSG
# Get readable character
character &= 0x10FFFF
print('{}'.format(chr(character)), end='')
# Clear interrupt
dev.dsp_hipct.value |= regs.ADSP_IPC_HIPCT_BUSY
else:
sleep(0.005)
if __name__ == "__main__":
# Clear Done if needed
#dev.dsp_hipct.value |= regs.ADSP_IPC_HIPCT_BUSY
# Use Device library for controlling registers
device = Device()
device.open_device()
mailbox_poll_mem(device)