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 +    ulong flags;
    1.51 +
    1.52 +    /* drop the low 8bits (including parity) */
    1.53 +    addr >>= 8;
    1.54  
    1.55 -    c.word = 0;
    1.56 -    c.bits.addr = addr;
    1.57 -    c.bits.RW = 0;
    1.58 +    /* these give iface errors because the address is ambiguous after
    1.59 +     * the above bit dropping */
    1.60 +    BUG_ON(addr == 0x8000);
    1.61 +
    1.62 +    for (;;) {
    1.63 +        c.word = 0;
    1.64 +        c.bits.addr = addr;
    1.65 +        c.bits.RW = SCOMC_READ;
    1.66  
    1.67 -    mtscomc(c.word);
    1.68 -    d = mfscomd();
    1.69 -    c.word = mfscomc();
    1.70 -    if (c.bits.failure)
    1.71 -        panic("scom status: 0x%016lx\n", c.word);
    1.72 +        local_irq_save(flags);
    1.73 +        asm volatile (
    1.74 +            "sync         \n\t"
    1.75 +            "mtspr %2, %0 \n\t"
    1.76 +            "isync        \n\t"
    1.77 +            "mfspr %1, %3 \n\t"
    1.78 +            "isync        \n\t"
    1.79 +            "mfspr %0, %2 \n\t"
    1.80 +            "isync        \n\t"
    1.81 +            : "+r" (c.word), "=r" (*d)
    1.82 +            : "i"(SPRN_SCOMC), "i"(SPRN_SCOMD));
    1.83 +
    1.84 +        local_irq_restore(flags);
    1.85 +        /* WARNING! older 970s (pre FX) shift the bits right 1 position */
    1.86  
    1.87 -    return d;
    1.88 +        if (!c.bits.failure)
    1.89 +            return 0;
    1.90 +
    1.91 +        /* deal with errors */
    1.92 +        /* has SCOM been disabled? */
    1.93 +        if (c.bits.disabled)
    1.94 +            return -ENOSYS;
    1.95 +
    1.96 +        /* we were passed a bad addr return -1 */
    1.97 +        if (c.bits.addr_error)
    1.98 +            return -EINVAL;
    1.99 +
   1.100 +        /* this is way bad and we will checkstop soon */
   1.101 +        BUG_ON(c.bits.proto_error);
   1.102 +
   1.103 +        if (c.bits.iface_error)
   1.104 +            udelay(10);
   1.105 +    }
   1.106  }
   1.107  
   1.108 -static inline void write_scom(ulong addr, ulong val)
   1.109 +static inline int write_scom(uint addr, ulong d)
   1.110  {
   1.111      union scomc c;
   1.112 +    ulong flags;
   1.113  
   1.114 -    c.word = 0;
   1.115 -    c.bits.addr = addr;
   1.116 -    c.bits.RW = 1;
   1.117 +    /* drop the low 8bits (including parity) */
   1.118 +    addr >>= 8;
   1.119 +
   1.120 +    /* these give iface errors because the address is ambiguous after
   1.121 +     * the above bit dropping */
   1.122 +    BUG_ON(addr == 0x8000);
   1.123 +
   1.124 +    for (;;) {
   1.125 +        c.word = 0;
   1.126 +        c.bits.addr = addr;
   1.127 +        c.bits.RW = SCOMC_WRITE;
   1.128  
   1.129 -    mtscomd(val);
   1.130 -    mtscomc(c.word);
   1.131 -    c.word = mfscomc();
   1.132 -    if (c.bits.failure)
   1.133 -        panic("scom status: 0x%016lx\n", c.word);
   1.134 +        local_irq_save(flags);
   1.135 +        asm volatile(
   1.136 +            "sync         \n\t"
   1.137 +            "mtspr %3, %1 \n\t"
   1.138 +            "isync        \n\t"
   1.139 +            "mtspr %2, %0 \n\t"
   1.140 +            "isync        \n\t"
   1.141 +            "mfspr %0, %2 \n\t"
   1.142 +            "isync        \n\t"
   1.143 +            : "+r" (c.word)
   1.144 +            : "r" (d), "i"(SPRN_SCOMC), "i"(SPRN_SCOMD));
   1.145 +        local_irq_restore(flags);
   1.146 +
   1.147 +        if (!c.bits.failure)
   1.148 +            return 0;
   1.149 +
   1.150 +        /* has SCOM been disabled? */
   1.151 +        if (c.bits.disabled)
   1.152 +            return -ENOSYS;
   1.153 +
   1.154 +        /* we were passed a bad addr return -1 */
   1.155 +        if (c.bits.addr_error)
   1.156 +            return -EINVAL;
   1.157 +
   1.158 +        /* this is way bad and we will checkstop soon */
   1.159 +        BUG_ON(c.bits.proto_error);
   1.160 +
   1.161 +        /* check for iface and retry */
   1.162 +        if (c.bits.iface_error)
   1.163 +            udelay(10);
   1.164 +    }
   1.165  }
   1.166  
   1.167 +/* SCOMC addresses are 16bit but we are given 24 bits in the
   1.168 + * books. The low oerder 8 bits are some kinda parity thin and should
   1.169 + * be ignored */
   1.170  #define SCOM_AMCS_REG      0x022601
   1.171  #define SCOM_AMCS_AND_MASK 0x022700
   1.172  #define SCOM_AMCS_OR_MASK  0x022800
   1.173  #define SCOM_CMCE          0x030901
   1.174  #define SCOM_PMCR          0x400801
   1.175 +#define SCOM_PTSR          0x408001
   1.176 +
   1.177 +/* cannot access these since only top 16bits are considered */
   1.178 +#define SCOM_STATUS        0x800003
   1.179  
   1.180  void cpu_scom_init(void)
   1.181  {
   1.182 -#ifdef not_yet
   1.183 +    ulong val;
   1.184      console_start_sync();
   1.185 -    printk("scom PMCR: 0x%016lx\n", read_scom(SCOM_PMCR));
   1.186 +    if (!read_scom(SCOM_PTSR, &val))
   1.187 +        printk("SCOM PTSR: 0x%016lx\n", val);
   1.188 +
   1.189      console_end_sync();
   1.190 -#endif
   1.191  }