diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2008-10-07 16:25:10 +0000 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2008-10-07 16:25:10 +0000 |
commit | 964f0665594bfdc260b49b6a2eac57b2dabeabaa (patch) | |
tree | f69c66320aa8e5f717f903d36388212fad2d490a /src | |
parent | 0994c397a5ef65c4ee8ae4551cc90000c4b0c857 (diff) |
[PATCH] coreboot: Don't loop forever waiting for HDA codecs
We shouldn't assume the presence of a working HDA codec, so put in
a reasonable timeout of 50usecs (timeout value borrowed from the kernel).
This makes SimNow work, since apparently though the codec is
present in Simnow, it is non functional.
Signed-off-by: Jordan Crouse <jordan.crouse@amd.com>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3640 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src')
-rw-r--r-- | src/southbridge/amd/sb600/sb600_hda.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/src/southbridge/amd/sb600/sb600_hda.c b/src/southbridge/amd/sb600/sb600_hda.c index 1e21025efd..b8044fadf1 100644 --- a/src/southbridge/amd/sb600/sb600_hda.c +++ b/src/southbridge/amd/sb600/sb600_hda.c @@ -26,6 +26,10 @@ #include <delay.h> #include "sb600.h" +#define HDA_ICII_REG 0x68 +#define HDA_ICII_BUSY (1 << 0) +#define HDA_ICII_VALID (1 << 1) + static int set_bits(u8 * port, u32 mask, u32 val) { u32 dword; @@ -160,6 +164,51 @@ static unsigned find_verb(u32 viddid, u32 ** verb) return sizeof(cim_verb_data) / sizeof(u32); } +/** + * Wait 50usec for for the codec to indicate it is ready + * no response would imply that the codec is non-operative + */ + +static int wait_for_ready(u8 *base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + + while(timeout--) { + u32 dword=readl(base + HDA_ICII_REG); + if (!(dword & HDA_ICII_BUSY)) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Wait 50usec for for the codec to indicate that it accepted + * the previous command. No response would imply that the code + * is non-operative + */ + +static int wait_for_valid(u8 *base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + while(timeout--) { + u32 dword = readl(base + HDA_ICII_REG); + if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) == + HDA_ICII_VALID) + return 0; + udelay(1); + } + + return 1; +} + static void codec_init(u8 * base, int addr) { u32 dword; @@ -168,16 +217,14 @@ static void codec_init(u8 * base, int addr) int i; /* 1 */ - do { - dword = readl(base + 0x68); - } while (dword & 1); + if (wait_for_ready(base) == -1) + return; dword = (addr << 28) | 0x000f0000; writel(dword, base + 0x60); - do { - dword = readl(base + 0x68); - } while ((dword & 3) != 2); + if (wait_for_valid(base) == -1) + return; dword = readl(base + 0x64); @@ -193,15 +240,13 @@ static void codec_init(u8 * base, int addr) printk_debug("verb_size: %d\n", verb_size); /* 3 */ for (i = 0; i < verb_size; i++) { - do { - dword = readl(base + 0x68); - } while (dword & 1); + if (wait_for_ready(base) == -1) + return; writel(verb[i], base + 0x60); - do { - dword = readl(base + 0x68); - } while ((dword & 3) != 2); + if (wait_for_valid(base) == -1) + return; } printk_debug("verb loaded!\n"); } |