246 lines
8.6 KiB
Python
246 lines
8.6 KiB
Python
#!/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
|