[PATCH] coreboot: Don't loop forever waiting for HDA codecs
authorJordan Crouse <jordan.crouse@amd.com>
Tue, 7 Oct 2008 16:25:10 +0000 (16:25 +0000)
committerJordan Crouse <jordan.crouse@amd.com>
Tue, 7 Oct 2008 16:25:10 +0000 (16:25 +0000)
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

src/southbridge/amd/sb600/sb600_hda.c

index 1e21025efde982dabbe0602e9df7c8138ddc43f8..b8044fadf138a5c8d8ca44aceae76b553e4c398c 100644 (file)
 #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");
 }