File: /usr/src/linux/include/asm-arm/proc-armv/system.h

1     /*
2      *  linux/include/asm-arm/proc-armv/system.h
3      *
4      *  Copyright (C) 1996 Russell King
5      *
6      * This program is free software; you can redistribute it and/or modify
7      * it under the terms of the GNU General Public License version 2 as
8      * published by the Free Software Foundation.
9      */
10     #ifndef __ASM_PROC_SYSTEM_H
11     #define __ASM_PROC_SYSTEM_H
12     
13     #include <linux/config.h>
14     
15     #define set_cr(x)					\
16     	__asm__ __volatile__(				\
17     	"mcr	p15, 0, %0, c1, c0	@ set CR"	\
18     	: : "r" (x))
19     
20     #define CR_M	(1 << 0)	/* MMU enable				*/
21     #define CR_A	(1 << 1)	/* Alignment abort enable		*/
22     #define CR_C	(1 << 2)	/* Dcache enable			*/
23     #define CR_W	(1 << 3)	/* Write buffer enable			*/
24     #define CR_P	(1 << 4)	/* 32-bit exception handler		*/
25     #define CR_D	(1 << 5)	/* 32-bit data address range		*/
26     #define CR_L	(1 << 6)	/* Implementation defined		*/
27     #define CD_B	(1 << 7)	/* Big endian				*/
28     #define CR_S	(1 << 8)	/* System MMU protection		*/
29     #define CD_R	(1 << 9)	/* ROM MMU protection			*/
30     #define CR_F	(1 << 10)	/* Implementation defined		*/
31     #define CR_Z	(1 << 11)	/* Implementation defined		*/
32     #define CR_I	(1 << 12)	/* Icache enable			*/
33     #define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
34     #define CR_RR	(1 << 14)	/* Round Robin cache replacement	*/
35     
36     extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
37     extern unsigned long cr_alignment;	/* defined in entry-armv.S */
38     
39     #ifdef __ARM_ARCH_4__
40     #define vectors_base()	((cr_alignment & CR_V) ? 0xffff0000 : 0)
41     #else
42     #define vectors_base()	(0)
43     #endif
44     
45     /*
46      * A couple of speedups for the ARM
47      */
48     
49     /*
50      * Save the current interrupt enable state & disable IRQs
51      */
52     #define __save_flags_cli(x)					\
53     	({							\
54     		unsigned long temp;				\
55     	__asm__ __volatile__(					\
56     	"mrs	%0, cpsr		@ save_flags_cli\n"	\
57     "	orr	%1, %0, #128\n"					\
58     "	msr	cpsr_c, %1"					\
59     	: "=r" (x), "=r" (temp)					\
60     	:							\
61     	: "memory");						\
62     	})
63     	
64     /*
65      * Enable IRQs
66      */
67     #define __sti()							\
68     	({							\
69     		unsigned long temp;				\
70     	__asm__ __volatile__(					\
71     	"mrs	%0, cpsr		@ sti\n"		\
72     "	bic	%0, %0, #128\n"					\
73     "	msr	cpsr_c, %0"					\
74     	: "=r" (temp)						\
75     	:							\
76     	: "memory");						\
77     	})
78     
79     /*
80      * Disable IRQs
81      */
82     #define __cli()							\
83     	({							\
84     		unsigned long temp;				\
85     	__asm__ __volatile__(					\
86     	"mrs	%0, cpsr		@ cli\n"		\
87     "	orr	%0, %0, #128\n"					\
88     "	msr	cpsr_c, %0"					\
89     	: "=r" (temp)						\
90     	:							\
91     	: "memory");						\
92     	})
93     
94     /*
95      * Enable FIQs
96      */
97     #define __stf()							\
98     	({							\
99     		unsigned long temp;				\
100     	__asm__ __volatile__(					\
101     	"mrs	%0, cpsr		@ stf\n"		\
102     "	bic	%0, %0, #64\n"					\
103     "	msr	cpsr_c, %0"					\
104     	: "=r" (temp)						\
105     	:							\
106     	: "memory");						\
107     	})
108     
109     /*
110      * Disable FIQs
111      */
112     #define __clf()							\
113     	({							\
114     		unsigned long temp;				\
115     	__asm__ __volatile__(					\
116     	"mrs	%0, cpsr		@ clf\n"		\
117     "	orr	%0, %0, #64\n"					\
118     "	msr	cpsr_c, %0"					\
119     	: "=r" (temp)						\
120     	:							\
121     	: "memory");						\
122     	})
123     
124     /*
125      * save current IRQ & FIQ state
126      */
127     #define __save_flags(x)						\
128     	__asm__ __volatile__(					\
129     	"mrs	%0, cpsr		@ save_flags\n"		\
130     	  : "=r" (x)						\
131     	  :							\
132     	  : "memory")
133     
134     /*
135      * restore saved IRQ & FIQ state
136      */
137     #define __restore_flags(x)					\
138     	__asm__ __volatile__(					\
139     	"msr	cpsr_c, %0		@ restore_flags\n"	\
140     	:							\
141     	: "r" (x)						\
142     	: "memory")
143     
144     #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
145     /*
146      * On the StrongARM, "swp" is terminally broken since it bypasses the
147      * cache totally.  This means that the cache becomes inconsistent, and,
148      * since we use normal loads/stores as well, this is really bad.
149      * Typically, this causes oopsen in filp_close, but could have other,
150      * more disasterous effects.  There are two work-arounds:
151      *  1. Disable interrupts and emulate the atomic swap
152      *  2. Clean the cache, perform atomic swap, flush the cache
153      *
154      * We choose (1) since its the "easiest" to achieve here and is not
155      * dependent on the processor type.
156      */
157     #define swp_is_buggy
158     #endif
159     
160     static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
161     {
162     	extern void __bad_xchg(volatile void *, int);
163     	unsigned long ret;
164     #ifdef swp_is_buggy
165     	unsigned long flags;
166     #endif
167     
168     	switch (size) {
169     #ifdef swp_is_buggy
170     		case 1:
171     			__save_flags_cli(flags);
172     			ret = *(volatile unsigned char *)ptr;
173     			*(volatile unsigned char *)ptr = x;
174     			__restore_flags(flags);
175     			break;
176     
177     		case 4:
178     			__save_flags_cli(flags);
179     			ret = *(volatile unsigned long *)ptr;
180     			*(volatile unsigned long *)ptr = x;
181     			__restore_flags(flags);
182     			break;
183     #else
184     		case 1:	__asm__ __volatile__ ("swpb %0, %1, [%2]"
185     					: "=r" (ret)
186     					: "r" (x), "r" (ptr)
187     					: "memory");
188     			break;
189     		case 4:	__asm__ __volatile__ ("swp %0, %1, [%2]"
190     					: "=r" (ret)
191     					: "r" (x), "r" (ptr)
192     					: "memory");
193     			break;
194     #endif
195     		default: __bad_xchg(ptr, size);
196     	}
197     
198     	return ret;
199     }
200     
201     #endif
202