ia64/xen-unstable

changeset 12911:8cb0d0eea355

[XEN][POWERPC] SCOM access is fully known and working

Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Thu Sep 21 07:36:17 2006 -0400 (2006-09-21)
parents 776efe262006
children e108c5ac16ac
files xen/arch/powerpc/powerpc64/ppc970_scom.c
line diff
     1.1 --- a/xen/arch/powerpc/powerpc64/ppc970_scom.c	Mon Sep 18 17:47:10 2006 -0400
     1.2 +++ b/xen/arch/powerpc/powerpc64/ppc970_scom.c	Thu Sep 21 07:36:17 2006 -0400
     1.3 @@ -22,33 +22,13 @@
     1.4  #include <xen/types.h>
     1.5  #include <xen/lib.h>
     1.6  #include <xen/console.h>
     1.7 +#include <xen/errno.h>
     1.8 +#include <asm/delay.h>
     1.9  
    1.10  #define SPRN_SCOMC 276
    1.11  #define SPRN_SCOMD 277
    1.12 -
    1.13 -static inline void mtscomc(ulong scomc)
    1.14 -{
    1.15 -    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomc), "i"(SPRN_SCOMC));
    1.16 -}
    1.17 -
    1.18 -static inline ulong mfscomc(void)
    1.19 -{
    1.20 -    ulong scomc;
    1.21 -    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomc): "i"(SPRN_SCOMC));
    1.22 -    return scomc;
    1.23 -}
    1.24 -
    1.25 -static inline void mtscomd(ulong scomd)
    1.26 -{
    1.27 -    __asm__ __volatile__ ("mtspr %1, %0" : : "r" (scomd), "i"(SPRN_SCOMD));
    1.28 -}
    1.29 -
    1.30 -static inline ulong mfscomd(void)
    1.31 -{
    1.32 -    ulong scomd;
    1.33 -    __asm__ __volatile__ ("mfspr %0, %1" : "=r" (scomd): "i"(SPRN_SCOMD));
    1.34 -    return scomd;
    1.35 -}
    1.36 +#define SCOMC_READ 1
    1.37 +#define SCOMC_WRITE (!(SCOMC_READ))
    1.38  
    1.39  union scomc {
    1.40      struct scomc_bits {
    1.41 @@ -68,50 +48,127 @@ union scomc {
    1.42  };
    1.43  
    1.44  
    1.45 -static inline ulong read_scom(ulong addr)
    1.46 +static inline int read_scom(uint addr, ulong *d)
    1.47  {
    1.48      union scomc c;
    1.49 -    ulong d;
    1.50 -
    1.51 -    c.word = 0;
    1.52 -    c.bits.addr = addr;
    1.53 -    c.bits.RW = 0;
    1.54 +    ulong flags;
    1.55  
    1.56 -    mtscomc(c.word);
    1.57 -    d = mfscomd();
    1.58 -    c.word = mfscomc();
    1.59 -    if (c.bits.failure)
    1.60 -        panic("scom status: 0x%016lx\n", c.word);
    1.61 +    /* drop the low 8bits (including parity) */
    1.62 +    addr >>= 8;
    1.63  
    1.64 -    return d;
    1.65 +    /* these give iface errors because the address is ambiguous after
    1.66 +     * the above bit dropping */
    1.67 +    BUG_ON(addr == 0x8000);
    1.68 +
    1.69 +    for (;;) {
    1.70 +        c.word = 0;
    1.71 +        c.bits.addr = addr;
    1.72 +        c.bits.RW = SCOMC_READ;
    1.73 +
    1.74 +        local_irq_save(flags);
    1.75 +        asm volatile (
    1.76 +            "sync         \n\t"
    1.77 +            "mtspr %2, %0 \n\t"
    1.78 +            "isync        \n\t"
    1.79 +            "mfspr %1, %3 \n\t"
    1.80 +            "isync        \n\t"
    1.81 +            "mfspr %0, %2 \n\t"
    1.82 +            "isync        \n\t"
    1.83 +            : "+r" (c.word), "=r" (*d)
    1.84 +            : "i"(SPRN_SCOMC), "i"(SPRN_SCOMD));
    1.85 +
    1.86 +        local_irq_restore(flags);
    1.87 +        /* WARNING! older 970s (pre FX) shift the bits right 1 position */
    1.88 +
    1.89 +        if (!c.bits.failure)
    1.90 +            return 0;
    1.91 +
    1.92 +        /* deal with errors */
    1.93 +        /* has SCOM been disabled? */
    1.94 +        if (c.bits.disabled)
    1.95 +            return -ENOSYS;
    1.96 +
    1.97 +        /* we were passed a bad addr return -1 */
    1.98 +        if (c.bits.addr_error)
    1.99 +            return -EINVAL;
   1.100 +
   1.101 +        /* this is way bad and we will checkstop soon */
   1.102 +        BUG_ON(c.bits.proto_error);
   1.103 +
   1.104 +        if (c.bits.iface_error)
   1.105 +            udelay(10);
   1.106 +    }
   1.107  }
   1.108  
   1.109 -static inline void write_scom(ulong addr, ulong val)
   1.110 +static inline int write_scom(uint addr, ulong d)
   1.111  {
   1.112      union scomc c;
   1.113 -
   1.114 -    c.word = 0;
   1.115 -    c.bits.addr = addr;
   1.116 -    c.bits.RW = 1;
   1.117 +    ulong flags;
   1.118  
   1.119 -    mtscomd(val);
   1.120 -    mtscomc(c.word);
   1.121 -    c.word = mfscomc();
   1.122 -    if (c.bits.failure)
   1.123 -        panic("scom status: 0x%016lx\n", c.word);
   1.124 +    /* drop the low 8bits (including parity) */
   1.125 +    addr >>= 8;
   1.126 +
   1.127 +    /* these give iface errors because the address is ambiguous after
   1.128 +     * the above bit dropping */
   1.129 +    BUG_ON(addr == 0x8000);
   1.130 +
   1.131 +    for (;;) {
   1.132 +        c.word = 0;
   1.133 +        c.bits.addr = addr;
   1.134 +        c.bits.RW = SCOMC_WRITE;
   1.135 +
   1.136 +        local_irq_save(flags);
   1.137 +        asm volatile(
   1.138 +            "sync         \n\t"
   1.139 +            "mtspr %3, %1 \n\t"
   1.140 +            "isync        \n\t"
   1.141 +            "mtspr %2, %0 \n\t"
   1.142 +            "isync        \n\t"
   1.143 +            "mfspr %0, %2 \n\t"
   1.144 +            "isync        \n\t"
   1.145 +            : "+r" (c.word)
   1.146 +            : "r" (d), "i"(SPRN_SCOMC), "i"(SPRN_SCOMD));
   1.147 +        local_irq_restore(flags);
   1.148 +
   1.149 +        if (!c.bits.failure)
   1.150 +            return 0;
   1.151 +
   1.152 +        /* has SCOM been disabled? */
   1.153 +        if (c.bits.disabled)
   1.154 +            return -ENOSYS;
   1.155 +
   1.156 +        /* we were passed a bad addr return -1 */
   1.157 +        if (c.bits.addr_error)
   1.158 +            return -EINVAL;
   1.159 +
   1.160 +        /* this is way bad and we will checkstop soon */
   1.161 +        BUG_ON(c.bits.proto_error);
   1.162 +
   1.163 +        /* check for iface and retry */
   1.164 +        if (c.bits.iface_error)
   1.165 +            udelay(10);
   1.166 +    }
   1.167  }
   1.168  
   1.169 +/* SCOMC addresses are 16bit but we are given 24 bits in the
   1.170 + * books. The low oerder 8 bits are some kinda parity thin and should
   1.171 + * be ignored */
   1.172  #define SCOM_AMCS_REG      0x022601
   1.173  #define SCOM_AMCS_AND_MASK 0x022700
   1.174  #define SCOM_AMCS_OR_MASK  0x022800
   1.175  #define SCOM_CMCE          0x030901
   1.176  #define SCOM_PMCR          0x400801
   1.177 +#define SCOM_PTSR          0x408001
   1.178 +
   1.179 +/* cannot access these since only top 16bits are considered */
   1.180 +#define SCOM_STATUS        0x800003
   1.181  
   1.182  void cpu_scom_init(void)
   1.183  {
   1.184 -#ifdef not_yet
   1.185 +    ulong val;
   1.186      console_start_sync();
   1.187 -    printk("scom PMCR: 0x%016lx\n", read_scom(SCOM_PMCR));
   1.188 +    if (!read_scom(SCOM_PTSR, &val))
   1.189 +        printk("SCOM PTSR: 0x%016lx\n", val);
   1.190 +
   1.191      console_end_sync();
   1.192 -#endif
   1.193  }