Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
msp_regops.h
Go to the documentation of this file.
1 /*
2  * SMP/VPE-safe functions to access "registers" (see note).
3  *
4  * NOTES:
5 * - These macros use ll/sc instructions, so it is your responsibility to
6  * ensure these are available on your platform before including this file.
7  * - The MIPS32 spec states that ll/sc results are undefined for uncached
8  * accesses. This means they can't be used on HW registers accessed
9  * through kseg1. Code which requires these macros for this purpose must
10  * front-end the registers with cached memory "registers" and have a single
11  * thread update the actual HW registers.
12  * - A maximum of 2k of code can be inserted between ll and sc. Every
13  * memory accesses between the instructions will increase the chance of
14  * sc failing and having to loop.
15  * - When using custom_read_reg32/custom_write_reg32 only perform the
16  * necessary logical operations on the register value in between these
17  * two calls. All other logic should be performed before the first call.
18  * - There is a bug on the R10000 chips which has a workaround. If you
19  * are affected by this bug, make sure to define the symbol 'R10000_LLSC_WAR'
20  * to be non-zero. If you are using this header from within linux, you may
21  * include <asm/war.h> before including this file to have this defined
22  * appropriately for you.
23  *
24  * Copyright 2005-2007 PMC-Sierra, Inc.
25  *
26  * This program is free software; you can redistribute it and/or modify it
27  * under the terms of the GNU General Public License as published by the
28  * Free Software Foundation; either version 2 of the License, or (at your
29  * option) any later version.
30  *
31  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
32  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
34  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  *
42  * You should have received a copy of the GNU General Public License along
43  * with this program; if not, write to the Free Software Foundation, Inc., 675
44  * Mass Ave, Cambridge, MA 02139, USA.
45  */
46 
47 #ifndef __ASM_REGOPS_H__
48 #define __ASM_REGOPS_H__
49 
50 #include <linux/types.h>
51 
52 #include <asm/war.h>
53 
54 #ifndef R10000_LLSC_WAR
55 #define R10000_LLSC_WAR 0
56 #endif
57 
58 #if R10000_LLSC_WAR == 1
59 #define __beqz "beqzl "
60 #else
61 #define __beqz "beqz "
62 #endif
63 
64 #ifndef _LINUX_TYPES_H
65 typedef unsigned int u32;
66 #endif
67 
68 /*
69  * Sets all the masked bits to the corresponding value bits
70  */
71 static inline void set_value_reg32(volatile u32 *const addr,
72  u32 const mask,
73  u32 const value)
74 {
75  u32 temp;
76 
77  __asm__ __volatile__(
78  " .set push \n"
79  " .set mips3 \n"
80  "1: ll %0, %1 # set_value_reg32 \n"
81  " and %0, %2 \n"
82  " or %0, %3 \n"
83  " sc %0, %1 \n"
84  " "__beqz"%0, 1b \n"
85  " nop \n"
86  " .set pop \n"
87  : "=&r" (temp), "=m" (*addr)
88  : "ir" (~mask), "ir" (value), "m" (*addr));
89 }
90 
91 /*
92  * Sets all the masked bits to '1'
93  */
94 static inline void set_reg32(volatile u32 *const addr,
95  u32 const mask)
96 {
97  u32 temp;
98 
99  __asm__ __volatile__(
100  " .set push \n"
101  " .set mips3 \n"
102  "1: ll %0, %1 # set_reg32 \n"
103  " or %0, %2 \n"
104  " sc %0, %1 \n"
105  " "__beqz"%0, 1b \n"
106  " nop \n"
107  " .set pop \n"
108  : "=&r" (temp), "=m" (*addr)
109  : "ir" (mask), "m" (*addr));
110 }
111 
112 /*
113  * Sets all the masked bits to '0'
114  */
115 static inline void clear_reg32(volatile u32 *const addr,
116  u32 const mask)
117 {
118  u32 temp;
119 
120  __asm__ __volatile__(
121  " .set push \n"
122  " .set mips3 \n"
123  "1: ll %0, %1 # clear_reg32 \n"
124  " and %0, %2 \n"
125  " sc %0, %1 \n"
126  " "__beqz"%0, 1b \n"
127  " nop \n"
128  " .set pop \n"
129  : "=&r" (temp), "=m" (*addr)
130  : "ir" (~mask), "m" (*addr));
131 }
132 
133 /*
134  * Toggles all masked bits from '0' to '1' and '1' to '0'
135  */
136 static inline void toggle_reg32(volatile u32 *const addr,
137  u32 const mask)
138 {
139  u32 temp;
140 
141  __asm__ __volatile__(
142  " .set push \n"
143  " .set mips3 \n"
144  "1: ll %0, %1 # toggle_reg32 \n"
145  " xor %0, %2 \n"
146  " sc %0, %1 \n"
147  " "__beqz"%0, 1b \n"
148  " nop \n"
149  " .set pop \n"
150  : "=&r" (temp), "=m" (*addr)
151  : "ir" (mask), "m" (*addr));
152 }
153 
154 /*
155  * Read all masked bits others are returned as '0'
156  */
157 static inline u32 read_reg32(volatile u32 *const addr,
158  u32 const mask)
159 {
160  u32 temp;
161 
162  __asm__ __volatile__(
163  " .set push \n"
164  " .set noreorder \n"
165  " lw %0, %1 # read \n"
166  " and %0, %2 # mask \n"
167  " .set pop \n"
168  : "=&r" (temp)
169  : "m" (*addr), "ir" (mask));
170 
171  return temp;
172 }
173 
174 /*
175  * blocking_read_reg32 - Read address with blocking load
176  *
177  * Uncached writes need to be read back to ensure they reach RAM.
178  * The returned value must be 'used' to prevent from becoming a
179  * non-blocking load.
180  */
181 static inline u32 blocking_read_reg32(volatile u32 *const addr)
182 {
183  u32 temp;
184 
185  __asm__ __volatile__(
186  " .set push \n"
187  " .set noreorder \n"
188  " lw %0, %1 # read \n"
189  " move %0, %0 # block \n"
190  " .set pop \n"
191  : "=&r" (temp)
192  : "m" (*addr));
193 
194  return temp;
195 }
196 
197 /*
198  * For special strange cases only:
199  *
200  * If you need custom processing within a ll/sc loop, use the following macros
201  * VERY CAREFULLY:
202  *
203  * u32 tmp; <-- Define a variable to hold the data
204  *
205  * custom_read_reg32(address, tmp); <-- Reads the address and put the value
206  * in the 'tmp' variable given
207  *
208  * From here on out, you are (basically) atomic, so don't do anything too
209  * fancy!
210  * Also, this code may loop if the end of this block fails to write
211  * everything back safely due do the other CPU, so do NOT do anything
212  * with side-effects!
213  *
214  * custom_write_reg32(address, tmp); <-- Writes back 'tmp' safely.
215  */
216 #define custom_read_reg32(address, tmp) \
217  __asm__ __volatile__( \
218  " .set push \n" \
219  " .set mips3 \n" \
220  "1: ll %0, %1 #custom_read_reg32 \n" \
221  " .set pop \n" \
222  : "=r" (tmp), "=m" (*address) \
223  : "m" (*address))
224 
225 #define custom_write_reg32(address, tmp) \
226  __asm__ __volatile__( \
227  " .set push \n" \
228  " .set mips3 \n" \
229  " sc %0, %1 #custom_write_reg32 \n" \
230  " "__beqz"%0, 1b \n" \
231  " nop \n" \
232  " .set pop \n" \
233  : "=&r" (tmp), "=m" (*address) \
234  : "0" (tmp), "m" (*address))
235 
236 #endif /* __ASM_REGOPS_H__ */