Skip to content

Commit dbff586

Browse files
Andy Rossnashif
authored andcommitted
soc/intel_adsp: Fixups for cavs18 SMP boot
This platform was stale for a long time and got a little left behind. Basic OS stuff was working but secondary core bringup didn't. It has a slightly different set of choices from the "weird hardware quirks" menu: + Like cAVS 1.5, it boots from a ROM that needs a short delay after power-up before it can receive the startup IDC. + But, like 2.5 and unlike 1.5, it doesn't start running until the PWRCTL bit for the core gets set by DSP software (1.5 gets launched by the host). So the delay needed to move down a bit. + It wants that PWRCTL bit to be set last, after CLKCTL enables the clock. (Which makes sense I guess: EE classes always tell you hold circuits in reset while an initial clock propagates). Not sure why it was in the reverse order originally; this way works for everything. + The ROM likes to scribble on the interrupt controller and mask its own IDC interrupts after we've already set it up. They have to be unmasked. We had code to do this already, thinking it was a workaround for legecy SOF code (that we never actually located). Now I'm thinking it was this behavior all along being detected by SOF's more extensive hardware CI. Take out the test and do it always, it's like nine instructions. + The host/loader-side behavior is a mix of 1.5 and 2.5. It won't actually start the secondary cores under host command, but it does need to see bits set for them in ADSPCS for the DSP-initiated power-up to work (2.5 would just ignore all but core 0's bits). + Also, like 1.5, it needs the host DMA stream to be explicitly stopped (and not just reset) or else further loads will be unstable. Note that the loader changes now require more logic than just "1.5 or not", so the platform detection has been enhanced to fully categorize the device based on PCI ID (not quite: we don't have any 2.0 platform hardware, so I left that alone for now). Signed-off-by: Andy Ross <[email protected]>
1 parent 1a7bc06 commit dbff586

File tree

2 files changed

+33
-33
lines changed

2 files changed

+33
-33
lines changed

soc/xtensa/intel_adsp/common/mp_cavs.c

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,6 @@ void soc_start_core(int cpu_num)
6363
{
6464
uint32_t curr_cpu = prid();
6565

66-
#ifdef CONFIG_SOC_SERIES_INTEL_CAVS_V15
67-
/* On the older hardware, core power is managed by the host
68-
* and aren't able to poll for anything to know it's
69-
* available. Need a delay here so that the hardware and ROM
70-
* firmware can complete initialization and be waiting for the
71-
* IDC we're about to send.
72-
*/
73-
k_busy_wait(CAVS15_ROM_IDC_DELAY);
74-
#endif
75-
7666
#ifdef CONFIG_SOC_SERIES_INTEL_CAVS_V25
7767
/* On cAVS v2.5, MP startup works differently. The core has
7868
* no ROM, and starts running immediately upon receipt of an
@@ -113,23 +103,25 @@ void soc_start_core(int cpu_num)
113103
* turn itself off when it gets to the WAITI instruction in
114104
* the idle thread.
115105
*/
116-
CAVS_SHIM.pwrctl |= CAVS_PWRCTL_TCPDSPPG(cpu_num);
117106
if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V15)) {
118107
CAVS_SHIM.clkctl |= CAVS_CLKCTL_TCPLCG(cpu_num);
119108
}
109+
CAVS_SHIM.pwrctl |= CAVS_PWRCTL_TCPDSPPG(cpu_num);
120110

121-
/* Workaround. SOF seems to have some older code on pre-2.5
122-
* hardware that is remasking these interrupts (probably a
123-
* variant of the same code we inherited earlier to mask it
124-
* while the ROM handles the startup IDC?). Unmask
125-
* unconditionally while we get this figured out, it's cheap
126-
* and safe.
111+
/* Older devices boot from a ROM and needs some time to
112+
* complete initialization and be waiting for the IDC we're
113+
* about to send.
127114
*/
128-
if (IS_ENABLED(CONFIG_SOF)) {
129-
CAVS_INTCTRL[cpu_num].l2.clear = CAVS_L2_IDC;
130-
for (int c = 0; c < CONFIG_MP_NUM_CPUS; c++) {
131-
IDC[c].busy_int |= IDC_ALL_CORES;
132-
}
115+
if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V25)) {
116+
k_busy_wait(CAVS15_ROM_IDC_DELAY);
117+
}
118+
119+
/* We set the interrupt controller up already, but the ROM on
120+
* some platforms will mess it up.
121+
*/
122+
CAVS_INTCTRL[cpu_num].l2.clear = CAVS_L2_IDC;
123+
for (int c = 0; c < CONFIG_MP_NUM_CPUS; c++) {
124+
IDC[c].busy_int |= IDC_ALL_CORES;
133125
}
134126

135127
/* Send power-up message to the other core. Start address

soc/xtensa/intel_adsp/tools/cavstool.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ def map_regs():
2727
p = runx(f"grep -iPl 'PCI_CLASS=40(10|38)0' /sys/bus/pci/devices/*/uevent")
2828
pcidir = os.path.dirname(p)
2929

30-
cavs15 = open(f"{pcidir}/device").read().rstrip() in [ "0x5a98", "0x1a98", "0x3198" ]
30+
# Platform/quirk detection. ID lists cribbed from the SOF kernel driver
31+
global cavs15, cavs18, cavs25
32+
did = int(open(f"{pcidir}/device").read().rstrip(), 16)
33+
cavs15 = did in [ 0x5a98, 0x1a98, 0x3198 ]
34+
cavs18 = did in [ 0x9dc8, 0xa348, 0x02c8, 0x06c8, 0xa3f0 ]
35+
cavs25 = did in [ 0xa0c8, 0x43c8, 0x4b55, 0x4b58, 0x7ad0, 0x51c8 ]
3136

3237
# Check sysfs for a loaded driver and remove it
3338
if os.path.exists(f"{pcidir}/driver"):
@@ -77,7 +82,7 @@ def map_regs():
7782
dsp.SRAM_FW_STATUS = 0x80000 # Start of first SRAM window
7883
dsp.freeze()
7984

80-
return (hda, sd, dsp, hda_ostream_id, cavs15)
85+
return (hda, sd, dsp, hda_ostream_id)
8186

8287
def setup_dma_mem(fw_bytes):
8388
(mem, phys_addr) = map_phys_mem()
@@ -210,10 +215,12 @@ def load_firmware(fw_file):
210215
hda.SPBFCTL |= (1 << hda_ostream_id)
211216
hda.SD_SPIB = len(fw_bytes)
212217

213-
# Start DSP. Just core 0 on 1.8+ (secondary core startup is handled
214-
# internally), but on 1.5 the host controls the power levers.
218+
# Start DSP. Host needs to provide power to all cores on 1.5
219+
# (which also starts them) and 1.8 (merely gates power, DSP also
220+
# has to set PWRCTL). The bits for cores other than 0 are ignored
221+
# on 2.5 where the DSP has full control.
215222
log.info(f"Starting DSP, ADSPCS = 0x{dsp.ADSPCS:x}")
216-
dsp.ADSPCS = 0xff0000 if cavs15 else 0x01fefe
223+
dsp.ADSPCS = 0xff0000 if not cavs25 else 0x01fefe
217224
while (dsp.ADSPCS & 0x1000000) == 0: pass
218225

219226
# Wait for the ROM to boot and signal it's ready. This short
@@ -248,10 +255,11 @@ def load_firmware(fw_file):
248255
if not alive:
249256
log.warning(f"Load failed? FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}")
250257

251-
# Turn DMA off and reset the stream. Clearing START first is a noop
252-
# per the spec, but required for 1.5, and makes the load on 1.8
253-
# unstable. Go figure.
254-
if cavs15:
258+
# Turn DMA off and reset the stream. Clearing START first is a
259+
# noop per the spec, but required for early versions (apparently
260+
# the reset doesn't stop the stream and the next load fails), and
261+
# makes the load on 2.5 unstable. Go figure.
262+
if not cavs25:
255263
sd.CTL &= ~2 # clear START
256264
sd.CTL |= 1
257265
log.info(f"cAVS firmware load complete")
@@ -288,9 +296,9 @@ def winstream_read(last_seq):
288296
return (seq, result.decode("utf-8"))
289297

290298
async def main():
291-
global hda, sd, dsp, hda_ostream_id, cavs15
299+
global hda, sd, dsp, hda_ostream_id
292300
try:
293-
(hda, sd, dsp, hda_ostream_id, cavs15) = map_regs()
301+
(hda, sd, dsp, hda_ostream_id) = map_regs()
294302
except Exception:
295303
log.error("Could not map device in sysfs; run as root.")
296304
sys.exit(1)

0 commit comments

Comments
 (0)