# HG changeset patch
# User Jimi Xenidis <[EMAIL PROTECTED]>
# Node ID e22cbd2ea1e4720b7853e4b05a4a9cdda2bff348
# Parent  91ee784bc36703985d5e841d18d65a4151666c57
[XEN][POWERPC] SCOM access is fully known and working

Signed-off-by: Jimi Xenidis <[EMAIL PROTECTED]>
---
 xen/arch/powerpc/powerpc64/ppc970_scom.c |  151 +++++++++++++++++++++----------
 1 files changed, 104 insertions(+), 47 deletions(-)

diff -r 91ee784bc367 -r e22cbd2ea1e4 xen/arch/powerpc/powerpc64/ppc970_scom.c
--- a/xen/arch/powerpc/powerpc64/ppc970_scom.c  Wed Sep 20 15:25:27 2006 -0500
+++ b/xen/arch/powerpc/powerpc64/ppc970_scom.c  Thu Sep 21 07:36:17 2006 -0400
@@ -22,33 +22,13 @@
 #include <xen/types.h>
 #include <xen/lib.h>
 #include <xen/console.h>
+#include <xen/errno.h>
+#include <asm/delay.h>
 
 #define SPRN_SCOMC 276
 #define SPRN_SCOMD 277
-
-static inline void mtscomc(ulong scomc)
-{
-    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomc), "i"(SPRN_SCOMC));
-}
-
-static inline ulong mfscomc(void)
-{
-    ulong scomc;
-    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomc): "i"(SPRN_SCOMC));
-    return scomc;
-}
-
-static inline void mtscomd(ulong scomd)
-{
-    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomd), "i"(SPRN_SCOMD));
-}
-
-static inline ulong mfscomd(void)
-{
-    ulong scomd;
-    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomd): "i"(SPRN_SCOMD));
-    return scomd;
-}
+#define SCOMC_READ 1
+#define SCOMC_WRITE (!(SCOMC_READ))
 
 union scomc {
     struct scomc_bits {
@@ -68,50 +48,127 @@ union scomc {
 };
 
 
-static inline ulong read_scom(ulong addr)
+static inline int read_scom(uint addr, ulong *d)
 {
     union scomc c;
-    ulong d;
+    ulong flags;
 
-    c.word = 0;
-    c.bits.addr = addr;
-    c.bits.RW = 0;
+    /* drop the low 8bits (including parity) */
+    addr >>= 8;
 
-    mtscomc(c.word);
-    d = mfscomd();
-    c.word = mfscomc();
-    if (c.bits.failure)
-        panic("scom status: 0x%016lx\n", c.word);
+    /* these give iface errors because the address is ambiguous after
+     * the above bit dropping */
+    BUG_ON(addr == 0x8000);
 
-    return d;
+    for (;;) {
+        c.word = 0;
+        c.bits.addr = addr;
+        c.bits.RW = SCOMC_READ;
+
+        local_irq_save(flags);
+        asm volatile (
+            "sync         \n\t"
+            "mtspr %2, %0 \n\t"
+            "isync        \n\t"
+            "mfspr %1, %3 \n\t"
+            "isync        \n\t"
+            "mfspr %0, %2 \n\t"
+            "isync        \n\t"
+            : "+r" (c.word), "=r" (*d)
+            : "i"(SPRN_SCOMC), "i"(SPRN_SCOMD));
+
+        local_irq_restore(flags);
+        /* WARNING! older 970s (pre FX) shift the bits right 1 position */
+
+        if (!c.bits.failure)
+            return 0;
+
+        /* deal with errors */
+        /* has SCOM been disabled? */
+        if (c.bits.disabled)
+            return -ENOSYS;
+
+        /* we were passed a bad addr return -1 */
+        if (c.bits.addr_error)
+            return -EINVAL;
+
+        /* this is way bad and we will checkstop soon */
+        BUG_ON(c.bits.proto_error);
+
+        if (c.bits.iface_error)
+            udelay(10);
+    }
 }
 
-static inline void write_scom(ulong addr, ulong val)
+static inline int write_scom(uint addr, ulong d)
 {
     union scomc c;
+    ulong flags;
 
-    c.word = 0;
-    c.bits.addr = addr;
-    c.bits.RW = 1;
+    /* drop the low 8bits (including parity) */
+    addr >>= 8;
 
-    mtscomd(val);
-    mtscomc(c.word);
-    c.word = mfscomc();
-    if (c.bits.failure)
-        panic("scom status: 0x%016lx\n", c.word);
+    /* these give iface errors because the address is ambiguous after
+     * the above bit dropping */
+    BUG_ON(addr == 0x8000);
+
+    for (;;) {
+        c.word = 0;
+        c.bits.addr = addr;
+        c.bits.RW = SCOMC_WRITE;
+
+        local_irq_save(flags);
+        asm volatile(
+            "sync         \n\t"
+            "mtspr %3, %1 \n\t"
+            "isync        \n\t"
+            "mtspr %2, %0 \n\t"
+            "isync        \n\t"
+            "mfspr %0, %2 \n\t"
+            "isync        \n\t"
+            : "+r" (c.word)
+            : "r" (d), "i"(SPRN_SCOMC), "i"(SPRN_SCOMD));
+        local_irq_restore(flags);
+
+        if (!c.bits.failure)
+            return 0;
+
+        /* has SCOM been disabled? */
+        if (c.bits.disabled)
+            return -ENOSYS;
+
+        /* we were passed a bad addr return -1 */
+        if (c.bits.addr_error)
+            return -EINVAL;
+
+        /* this is way bad and we will checkstop soon */
+        BUG_ON(c.bits.proto_error);
+
+        /* check for iface and retry */
+        if (c.bits.iface_error)
+            udelay(10);
+    }
 }
 
+/* SCOMC addresses are 16bit but we are given 24 bits in the
+ * books. The low oerder 8 bits are some kinda parity thin and should
+ * be ignored */
 #define SCOM_AMCS_REG      0x022601
 #define SCOM_AMCS_AND_MASK 0x022700
 #define SCOM_AMCS_OR_MASK  0x022800
 #define SCOM_CMCE          0x030901
 #define SCOM_PMCR          0x400801
+#define SCOM_PTSR          0x408001
+
+/* cannot access these since only top 16bits are considered */
+#define SCOM_STATUS        0x800003
 
 void cpu_scom_init(void)
 {
-#ifdef not_yet
+    ulong val;
     console_start_sync();
-    printk("scom PMCR: 0x%016lx\n", read_scom(SCOM_PMCR));
+    if (!read_scom(SCOM_PTSR, &val))
+        printk("SCOM PTSR: 0x%016lx\n", val);
+
     console_end_sync();
-#endif
 }

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to