1 /*
2  * Copyright (C) 2000, 2001 Broadcom Corporation
3  * Copyright (C) 2002 Ralf Baechle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19 
20 #ifndef __ASM_SIBYTE_64BIT_H
21 #define __ASM_SIBYTE_64BIT_H
22 
23 #include <linux/config.h>
24 #include <linux/types.h>
25 
26 #ifdef CONFIG_MIPS32
27 
28 #include <asm/system.h>
29 
30 /*
31  * This is annoying...we can't actually write the 64-bit IO register properly
32  * without having access to 64-bit registers...  which doesn't work by default
33  * in o32 format...grrr...
34  */
__out64(u64 val,unsigned long addr)35 static inline void __out64(u64 val, unsigned long addr)
36 {
37 	u64 tmp;
38 
39 	__asm__ __volatile__ (
40 		"	.set	mips3				\n"
41 		"	dsll32	%L0, %L0, 0	# __out64	\n"
42 		"	dsrl32	%L0, %L0, 0			\n"
43 		"	dsll32	%M0, %M0, 0			\n"
44 		"	or	%L0, %L0, %M0			\n"
45 		"	sd	%L0, (%2)			\n"
46 		"	.set	mips0				\n"
47 		: "=r" (tmp)
48 		: "0" (val), "r" (addr));
49 }
50 
out64(u64 val,unsigned long addr)51 static inline void out64(u64 val, unsigned long addr)
52 {
53 	unsigned long flags;
54 
55 	local_irq_save(flags);
56 	__out64(val, addr);
57 	local_irq_restore(flags);
58 }
59 
__in64(unsigned long addr)60 static inline u64 __in64(unsigned long addr)
61 {
62 	u64 res;
63 
64 	__asm__ __volatile__ (
65 		"	.set	mips3		# __in64	\n"
66 		"	ld	%L0, (%1)			\n"
67 		"	dsra32	%M0, %L0, 0			\n"
68 		"	sll	%L0, %L0, 0			\n"
69 		"	.set	mips0				\n"
70 		: "=r" (res)
71 		: "r" (addr));
72 
73 	return res;
74 }
75 
in64(unsigned long addr)76 static inline u64 in64(unsigned long addr)
77 {
78 	unsigned long flags;
79 	u64 res;
80 
81 	local_irq_save(flags);
82 	res = __in64(addr);
83 	local_irq_restore(flags);
84 
85 	return res;
86 }
87 
88 #endif /* CONFIG_MIPS32 */
89 
90 #ifdef CONFIG_MIPS64
91 
92 /*
93  * These are provided so as to be able to use common
94  * driver code for the 32-bit and 64-bit trees
95  */
out64(u64 val,unsigned long addr)96 static inline void out64(u64 val, unsigned long addr)
97 {
98 	*(volatile unsigned long *)addr = val;
99 }
100 
in64(unsigned long addr)101 static inline u64 in64(unsigned long addr)
102 {
103 	return *(volatile unsigned long *)addr;
104 }
105 
106 #define __in64(a)	in64(a)
107 #define __out64(v,a)	out64(v,a)
108 
109 #endif /* CONFIG_MIPS64 */
110 
111 /*
112  * Avoid interrupt mucking, just adjust the address for 4-byte access.
113  * Assume the addresses are 8-byte aligned.
114  */
115 
116 #ifdef __MIPSEB__
117 #define __CSR_32_ADJUST 4
118 #else
119 #define __CSR_32_ADJUST 0
120 #endif
121 
122 #define csr_out32(v,a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST) = (v))
123 #define csr_in32(a)    (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST))
124 
125 #endif /* __ASM_SIBYTE_64BIT_H */
126