device/azalia_device.c: Unify `wait_for_valid` timeouts

The timeout is never reached when the codec is functioning properly.
Using a small timeout value can result in spurious errors with some
codecs, e.g. a codec that is slow to respond but operates correctly.
When a codec is non-operative, the timeout is only reached once per
verb table, thus the impact on booting time is relatively small. So,
use a reasonably long enough timeout to cover all possible cases.

Remove the unconditional 25 µs delay and increase the timeout delay.
The new value of 1 ms is the maximum of all existing implementations.
Currently, the only boards using this code are AMD reference boards:
- AMD Bilby
- AMD Mandolin
- AMD Padmelon

Change-Id: Ia5e4829d404dcecdb9e7a377e896a319cb38531a
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/51634
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
This commit is contained in:
Angel Pons 2021-03-18 14:12:32 +01:00 committed by Patrick Georgi
parent 8c5994f92d
commit fa1befcb57
1 changed files with 11 additions and 8 deletions

View File

@ -162,26 +162,29 @@ static int wait_for_ready(u8 *base)
} }
/* /*
* Wait 50usec for the codec to indicate that it accepted the previous command. * Wait for the codec to indicate that it accepted the previous command.
* No response would imply that the code is non-operative. * No response would imply that the codec is non-operative.
*/ */
static int wait_for_valid(u8 *base) static int wait_for_valid(u8 *base)
{ {
struct stopwatch sw; struct stopwatch sw;
u32 reg32; u32 reg32;
/* Use a 50 usec timeout - the Linux kernel uses the same duration */
int timeout = 25;
/* Send the verb to the codec */ /* Send the verb to the codec */
reg32 = read32(base + HDA_ICII_REG); reg32 = read32(base + HDA_ICII_REG);
reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID; reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
write32(base + HDA_ICII_REG, reg32); write32(base + HDA_ICII_REG, reg32);
while (timeout--) /*
udelay(1); * The timeout is never reached when the codec is functioning properly.
* Using a small timeout value can result in spurious errors with some
stopwatch_init_usecs_expire(&sw, 50); * codecs, e.g. a codec that is slow to respond but operates correctly.
* When a codec is non-operative, the timeout is only reached once per
* verb table, thus the impact on booting time is relatively small. So,
* use a reasonably long enough timeout to cover all possible cases.
*/
stopwatch_init_msecs_expire(&sw, 1);
while (!stopwatch_expired(&sw)) { while (!stopwatch_expired(&sw)) {
reg32 = read32(base + HDA_ICII_REG); reg32 = read32(base + HDA_ICII_REG);
if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID) if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)