uboot/arch/sh/include/asm/system.h
<<
>>
Prefs
   1#ifndef __ASM_SH_SYSTEM_H
   2#define __ASM_SH_SYSTEM_H
   3
   4/*
   5 * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
   6 * Copyright (C) 2002 Paul Mundt
   7 *
   8 * from linux kernel code.
   9 */
  10
  11#include <asm/irqflags.h>
  12#include <asm/types.h>
  13
  14/*
  15 *      switch_to() should switch tasks to task nr n, first
  16 */
  17
  18#define switch_to(prev, next, last) do {                                \
  19 struct task_struct *__last;                                            \
  20 register unsigned long *__ts1 __asm__ ("r1") = &prev->thread.sp;       \
  21 register unsigned long *__ts2 __asm__ ("r2") = &prev->thread.pc;       \
  22 register unsigned long *__ts4 __asm__ ("r4") = (unsigned long *)prev;  \
  23 register unsigned long *__ts5 __asm__ ("r5") = (unsigned long *)next;  \
  24 register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp;       \
  25 register unsigned long __ts7 __asm__ ("r7") = next->thread.pc;         \
  26 __asm__ __volatile__ (".balign 4\n\t"                                  \
  27                       "stc.l   gbr, @-r15\n\t"                         \
  28                       "sts.l   pr, @-r15\n\t"                          \
  29                       "mov.l   r8, @-r15\n\t"                          \
  30                       "mov.l   r9, @-r15\n\t"                          \
  31                       "mov.l   r10, @-r15\n\t"                         \
  32                       "mov.l   r11, @-r15\n\t"                         \
  33                       "mov.l   r12, @-r15\n\t"                         \
  34                       "mov.l   r13, @-r15\n\t"                         \
  35                       "mov.l   r14, @-r15\n\t"                         \
  36                       "mov.l   r15, @r1        ! save SP\n\t"          \
  37                       "mov.l   @r6, r15        ! change to new stack\n\t" \
  38                       "mova    1f, %0\n\t"                             \
  39                       "mov.l   %0, @r2         ! save PC\n\t"          \
  40                       "mov.l   2f, %0\n\t"                             \
  41                       "jmp     @%0             ! call __switch_to\n\t" \
  42                       " lds    r7, pr          !  with return to new PC\n\t" \
  43                       ".balign 4\n"                                    \
  44                       "2:\n\t"                                         \
  45                       ".long   __switch_to\n"                          \
  46                       "1:\n\t"                                         \
  47                       "mov.l   @r15+, r14\n\t"                         \
  48                       "mov.l   @r15+, r13\n\t"                         \
  49                       "mov.l   @r15+, r12\n\t"                         \
  50                       "mov.l   @r15+, r11\n\t"                         \
  51                       "mov.l   @r15+, r10\n\t"                         \
  52                       "mov.l   @r15+, r9\n\t"                          \
  53                       "mov.l   @r15+, r8\n\t"                          \
  54                       "lds.l   @r15+, pr\n\t"                          \
  55                       "ldc.l   @r15+, gbr\n\t"                         \
  56                       : "=z" (__last)                                  \
  57                       : "r" (__ts1), "r" (__ts2), "r" (__ts4),         \
  58                         "r" (__ts5), "r" (__ts6), "r" (__ts7)          \
  59                       : "r3", "t");                                    \
  60        last = __last;                                                  \
  61} while (0)
  62
  63/*
  64 * On SMP systems, when the scheduler does migration-cost autodetection,
  65 * it needs a way to flush as much of the CPU's caches as possible.
  66 *
  67 * TODO: fill this in!
  68 */
  69static inline void sched_cacheflush(void)
  70{
  71}
  72
  73#ifdef CONFIG_CPU_SH4A
  74#define __icbi()                        \
  75{                                       \
  76        unsigned long __addr;           \
  77        __addr = 0xa8000000;            \
  78        __asm__ __volatile__(           \
  79                "icbi   %0\n\t"         \
  80                : /* no output */       \
  81                : "m" (__m(__addr)));   \
  82}
  83#endif
  84
  85static inline unsigned long tas(volatile int *m)
  86{
  87        unsigned long retval;
  88
  89        __asm__ __volatile__ ("tas.b    @%1\n\t"
  90                              "movt     %0"
  91                              : "=r" (retval): "r" (m): "t", "memory");
  92        return retval;
  93}
  94
  95/*
  96 * A brief note on ctrl_barrier(), the control register write barrier.
  97 *
  98 * Legacy SH cores typically require a sequence of 8 nops after
  99 * modification of a control register in order for the changes to take
 100 * effect. On newer cores (like the sh4a and sh5) this is accomplished
 101 * with icbi.
 102 *
 103 * Also note that on sh4a in the icbi case we can forego a synco for the
 104 * write barrier, as it's not necessary for control registers.
 105 *
 106 * Historically we have only done this type of barrier for the MMUCR, but
 107 * it's also necessary for the CCR, so we make it generic here instead.
 108 */
 109#ifdef CONFIG_CPU_SH4A
 110#define mb()            __asm__ __volatile__ ("synco": : :"memory")
 111#define rmb()           mb()
 112#define wmb()           __asm__ __volatile__ ("synco": : :"memory")
 113#define ctrl_barrier()  __icbi()
 114#define read_barrier_depends()  do { } while(0)
 115#else
 116#define mb()            __asm__ __volatile__ ("": : :"memory")
 117#define rmb()           mb()
 118#define wmb()           __asm__ __volatile__ ("": : :"memory")
 119#define ctrl_barrier()  __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
 120#define read_barrier_depends()  do { } while(0)
 121#endif
 122
 123#ifdef CONFIG_SMP
 124#define smp_mb()        mb()
 125#define smp_rmb()       rmb()
 126#define smp_wmb()       wmb()
 127#define smp_read_barrier_depends()      read_barrier_depends()
 128#else
 129#define smp_mb()        barrier()
 130#define smp_rmb()       barrier()
 131#define smp_wmb()       barrier()
 132#define smp_read_barrier_depends()      do { } while(0)
 133#endif
 134
 135#define set_mb(var, value) do { xchg(&var, value); } while (0)
 136
 137/*
 138 * Jump to P2 area.
 139 * When handling TLB or caches, we need to do it from P2 area.
 140 */
 141#define jump_to_P2()                    \
 142do {                                    \
 143        unsigned long __dummy;          \
 144        __asm__ __volatile__(           \
 145                "mov.l  1f, %0\n\t"     \
 146                "or     %1, %0\n\t"     \
 147                "jmp    @%0\n\t"        \
 148                " nop\n\t"              \
 149                ".balign 4\n"           \
 150                "1:     .long 2f\n"     \
 151                "2:"                    \
 152                : "=&r" (__dummy)       \
 153                : "r" (0x20000000));    \
 154} while (0)
 155
 156/*
 157 * Back to P1 area.
 158 */
 159#define back_to_P1()                                    \
 160do {                                                    \
 161        unsigned long __dummy;                          \
 162        ctrl_barrier();                                 \
 163        __asm__ __volatile__(                           \
 164                "mov.l  1f, %0\n\t"                     \
 165                "jmp    @%0\n\t"                        \
 166                " nop\n\t"                              \
 167                ".balign 4\n"                           \
 168                "1:     .long 2f\n"                     \
 169                "2:"                                    \
 170                : "=&r" (__dummy));                     \
 171} while (0)
 172
 173static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
 174{
 175        unsigned long flags, retval;
 176
 177        local_irq_save(flags);
 178        retval = *m;
 179        *m = val;
 180        local_irq_restore(flags);
 181        return retval;
 182}
 183
 184static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
 185{
 186        unsigned long flags, retval;
 187
 188        local_irq_save(flags);
 189        retval = *m;
 190        *m = val & 0xff;
 191        local_irq_restore(flags);
 192        return retval;
 193}
 194
 195extern void __xchg_called_with_bad_pointer(void);
 196
 197#define __xchg(ptr, x, size)                            \
 198({                                                      \
 199        unsigned long __xchg__res;                      \
 200        volatile void *__xchg_ptr = (ptr);              \
 201        switch (size) {                                 \
 202        case 4:                                         \
 203                __xchg__res = xchg_u32(__xchg_ptr, x);  \
 204                break;                                  \
 205        case 1:                                         \
 206                __xchg__res = xchg_u8(__xchg_ptr, x);   \
 207                break;                                  \
 208        default:                                        \
 209                __xchg_called_with_bad_pointer();       \
 210                __xchg__res = x;                        \
 211                break;                                  \
 212        }                                               \
 213                                                        \
 214        __xchg__res;                                    \
 215})
 216
 217#define xchg(ptr,x)     \
 218        ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
 219
 220static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
 221        unsigned long new)
 222{
 223        __u32 retval;
 224        unsigned long flags;
 225
 226        local_irq_save(flags);
 227        retval = *m;
 228        if (retval == old)
 229                *m = new;
 230        local_irq_restore(flags);       /* implies memory barrier  */
 231        return retval;
 232}
 233
 234/* This function doesn't exist, so you'll get a linker error
 235 * if something tries to do an invalid cmpxchg(). */
 236extern void __cmpxchg_called_with_bad_pointer(void);
 237
 238#define __HAVE_ARCH_CMPXCHG 1
 239
 240static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
 241                unsigned long new, int size)
 242{
 243        switch (size) {
 244        case 4:
 245                return __cmpxchg_u32(ptr, old, new);
 246        }
 247        __cmpxchg_called_with_bad_pointer();
 248        return old;
 249}
 250
 251#define cmpxchg(ptr,o,n)                                                 \
 252  ({                                                                     \
 253     __typeof__(*(ptr)) _o_ = (o);                                       \
 254     __typeof__(*(ptr)) _n_ = (n);                                       \
 255     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,           \
 256                                    (unsigned long)_n_, sizeof(*(ptr))); \
 257  })
 258
 259extern void *set_exception_table_vec(unsigned int vec, void *handler);
 260
 261static inline void *set_exception_table_evt(unsigned int evt, void *handler)
 262{
 263        return set_exception_table_vec(evt >> 5, handler);
 264}
 265
 266/* XXX
 267 * disable hlt during certain critical i/o operations
 268 */
 269#define HAVE_DISABLE_HLT
 270void disable_hlt(void);
 271void enable_hlt(void);
 272
 273#define arch_align_stack(x) (x)
 274
 275static inline void trigger_address_error(void)
 276{
 277        __asm__ __volatile__ (
 278                "ldc %0, sr\n\t"
 279                "mov.l @%1, %0"
 280                :
 281                : "r" (0x10000000), "r" (0x80000001)
 282        );
 283}
 284
 285#endif
 286