diff --git a/soc/xtensa/intel_adsp/common/mp_cavs.c b/soc/xtensa/intel_adsp/common/mp_cavs.c index 2c64ff5b384..5379064d74c 100644 --- a/soc/xtensa/intel_adsp/common/mp_cavs.c +++ b/soc/xtensa/intel_adsp/common/mp_cavs.c @@ -63,16 +63,6 @@ void soc_start_core(int cpu_num) { uint32_t curr_cpu = prid(); -#ifdef CONFIG_SOC_SERIES_INTEL_CAVS_V15 - /* On the older hardware, core power is managed by the host - * and aren't able to poll for anything to know it's - * available. Need a delay here so that the hardware and ROM - * firmware can complete initialization and be waiting for the - * IDC we're about to send. - */ - k_busy_wait(CAVS15_ROM_IDC_DELAY); -#endif - #ifdef CONFIG_SOC_SERIES_INTEL_CAVS_V25 /* On cAVS v2.5, MP startup works differently. The core has * no ROM, and starts running immediately upon receipt of an @@ -113,23 +103,25 @@ void soc_start_core(int cpu_num) * turn itself off when it gets to the WAITI instruction in * the idle thread. */ - CAVS_SHIM.pwrctl |= CAVS_PWRCTL_TCPDSPPG(cpu_num); if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V15)) { CAVS_SHIM.clkctl |= CAVS_CLKCTL_TCPLCG(cpu_num); } + CAVS_SHIM.pwrctl |= CAVS_PWRCTL_TCPDSPPG(cpu_num); - /* Workaround. SOF seems to have some older code on pre-2.5 - * hardware that is remasking these interrupts (probably a - * variant of the same code we inherited earlier to mask it - * while the ROM handles the startup IDC?). Unmask - * unconditionally while we get this figured out, it's cheap - * and safe. + /* Older devices boot from a ROM and needs some time to + * complete initialization and be waiting for the IDC we're + * about to send. */ - if (IS_ENABLED(CONFIG_SOF)) { - CAVS_INTCTRL[cpu_num].l2.clear = CAVS_L2_IDC; - for (int c = 0; c < CONFIG_MP_NUM_CPUS; c++) { - IDC[c].busy_int |= IDC_ALL_CORES; - } + if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V25)) { + k_busy_wait(CAVS15_ROM_IDC_DELAY); + } + + /* We set the interrupt controller up already, but the ROM on + * some platforms will mess it up. + */ + CAVS_INTCTRL[cpu_num].l2.clear = CAVS_L2_IDC; + for (int c = 0; c < CONFIG_MP_NUM_CPUS; c++) { + IDC[c].busy_int |= IDC_ALL_CORES; } /* Send power-up message to the other core. Start address diff --git a/soc/xtensa/intel_adsp/tools/cavstool.py b/soc/xtensa/intel_adsp/tools/cavstool.py index b46f933ff40..328f5a0e913 100755 --- a/soc/xtensa/intel_adsp/tools/cavstool.py +++ b/soc/xtensa/intel_adsp/tools/cavstool.py @@ -27,7 +27,12 @@ def map_regs(): p = runx(f"grep -iPl 'PCI_CLASS=40(10|38)0' /sys/bus/pci/devices/*/uevent") pcidir = os.path.dirname(p) - cavs15 = open(f"{pcidir}/device").read().rstrip() in [ "0x5a98", "0x1a98", "0x3198" ] + # Platform/quirk detection. ID lists cribbed from the SOF kernel driver + global cavs15, cavs18, cavs25 + did = int(open(f"{pcidir}/device").read().rstrip(), 16) + cavs15 = did in [ 0x5a98, 0x1a98, 0x3198 ] + cavs18 = did in [ 0x9dc8, 0xa348, 0x02c8, 0x06c8, 0xa3f0 ] + cavs25 = did in [ 0xa0c8, 0x43c8, 0x4b55, 0x4b58, 0x7ad0, 0x51c8 ] # Check sysfs for a loaded driver and remove it if os.path.exists(f"{pcidir}/driver"): @@ -77,7 +82,7 @@ def map_regs(): dsp.SRAM_FW_STATUS = 0x80000 # Start of first SRAM window dsp.freeze() - return (hda, sd, dsp, hda_ostream_id, cavs15) + return (hda, sd, dsp, hda_ostream_id) def setup_dma_mem(fw_bytes): (mem, phys_addr) = map_phys_mem() @@ -210,10 +215,12 @@ def load_firmware(fw_file): hda.SPBFCTL |= (1 << hda_ostream_id) hda.SD_SPIB = len(fw_bytes) - # Start DSP. Just core 0 on 1.8+ (secondary core startup is handled - # internally), but on 1.5 the host controls the power levers. + # 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 + # has to set PWRCTL). The bits for cores other than 0 are ignored + # on 2.5 where the DSP has full control. log.info(f"Starting DSP, ADSPCS = 0x{dsp.ADSPCS:x}") - dsp.ADSPCS = 0xff0000 if cavs15 else 0x01fefe + dsp.ADSPCS = 0xff0000 if not cavs25 else 0x01fefe while (dsp.ADSPCS & 0x1000000) == 0: pass # Wait for the ROM to boot and signal it's ready. This short @@ -248,10 +255,11 @@ def load_firmware(fw_file): if not alive: log.warning(f"Load failed? FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}") - # Turn DMA off and reset the stream. Clearing START first is a noop - # per the spec, but required for 1.5, and makes the load on 1.8 - # unstable. Go figure. - if cavs15: + # Turn DMA off and reset the stream. Clearing START first is a + # noop per the spec, but required for early versions (apparently + # the reset doesn't stop the stream and the next load fails), and + # makes the load on 2.5 unstable. Go figure. + if not cavs25: sd.CTL &= ~2 # clear START sd.CTL |= 1 log.info(f"cAVS firmware load complete") @@ -288,9 +296,9 @@ def winstream_read(last_seq): return (seq, result.decode("utf-8")) async def main(): - global hda, sd, dsp, hda_ostream_id, cavs15 + global hda, sd, dsp, hda_ostream_id try: - (hda, sd, dsp, hda_ostream_id, cavs15) = map_regs() + (hda, sd, dsp, hda_ostream_id) = map_regs() except Exception: log.error("Could not map device in sysfs; run as root.") sys.exit(1)