xref: /NextBSD/sys/mips/nlm/hal/cop2.h (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /*-
2  * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * NETLOGIC_BSD
29  * $FreeBSD$
30  */
31 
32 #ifndef __NLM_HAL_COP2_H__
33 #define	__NLM_HAL_COP2_H__
34 
35 #define	COP2_TX_BUF		0
36 #define	COP2_RX_BUF		1
37 #define	COP2_TXMSGSTATUS	2
38 #define	COP2_RXMSGSTATUS	3
39 #define	COP2_MSGSTATUS1		4
40 #define	COP2_MSGCONFIG		5
41 #define	COP2_MSGERROR		6
42 
43 #define	CROSSTHR_POPQ_EN	0x01
44 #define	VC0_POPQ_EN		0x02
45 #define	VC1_POPQ_EN		0x04
46 #define	VC2_POPQ_EN		0x08
47 #define	VC3_POPQ_EN		0x10
48 #define	ALL_VC_POPQ_EN		0x1E
49 #define	ALL_VC_CT_POPQ_EN	0x1F
50 
51 struct nlm_fmn_msg {
52 	uint64_t msg[4];
53 };
54 
55 #define	NLM_DEFINE_COP2_ACCESSORS32(name, reg, sel)		\
56 static inline uint32_t nlm_read_c2_##name(void)			\
57 {								\
58 	uint32_t __rv;						\
59 	__asm__ __volatile__ (					\
60 	".set	push\n"						\
61 	".set	noreorder\n"					\
62 	".set	mips64\n"					\
63 	"mfc2	%0, $%1, %2\n"					\
64 	".set	pop\n"						\
65 	: "=r" (__rv)						\
66 	: "i" (reg), "i" (sel));				\
67 	return __rv;						\
68 }								\
69 								\
70 static inline void nlm_write_c2_##name(uint32_t val)		\
71 {								\
72 	__asm__ __volatile__(					\
73 	".set	push\n"						\
74 	".set	noreorder\n"					\
75 	".set	mips64\n"					\
76 	"mtc2	%0, $%1, %2\n"					\
77 	".set	pop\n"						\
78 	: : "r" (val), "i" (reg), "i" (sel));			\
79 } struct __hack
80 
81 #if (__mips == 64)
82 #define	NLM_DEFINE_COP2_ACCESSORS64(name, reg, sel)		\
83 static inline uint64_t nlm_read_c2_##name(void)			\
84 {								\
85 	uint64_t __rv;						\
86 	__asm__ __volatile__ (					\
87 	".set	push\n"						\
88 	".set	noreorder\n"					\
89 	".set	mips64\n"					\
90 	"dmfc2	%0, $%1, %2\n"					\
91 	".set	pop\n"						\
92 	: "=r" (__rv)						\
93 	: "i" (reg), "i" (sel));				\
94 	return __rv;						\
95 }								\
96 								\
97 static inline void nlm_write_c2_##name(uint64_t val)		\
98 {								\
99 	__asm__ __volatile__ (					\
100 	".set	push\n"						\
101 	".set	noreorder\n"					\
102 	".set	mips64\n"					\
103 	"dmtc2	%0, $%1, %2\n"					\
104 	".set	pop\n"						\
105 	: : "r" (val), "i" (reg), "i" (sel));			\
106 } struct __hack
107 
108 #else
109 
110 #define	NLM_DEFINE_COP2_ACCESSORS64(name, reg, sel)		\
111 static inline uint64_t nlm_read_c2_##name(void)			\
112 {								\
113 	uint32_t __high, __low;					\
114 	__asm__ __volatile__ (					\
115 	".set	push\n"						\
116 	".set	noreorder\n"					\
117 	".set	mips64\n"					\
118 	"dmfc2	$8, $%2, %3\n"					\
119 	"dsra32	%0, $8, 0\n"					\
120 	"sll	%1, $8, 0\n"					\
121 	".set	pop\n"						\
122 	: "=r"(__high), "=r"(__low)				\
123 	: "i"(reg), "i"(sel)					\
124 	: "$8");						\
125 								\
126 	return ((uint64_t)__high << 32) | __low;		\
127 }								\
128 								\
129 static inline void nlm_write_c2_##name(uint64_t val)		\
130 {								\
131 	uint32_t __high = val >> 32;				\
132 	uint32_t __low = val & 0xffffffff;			\
133 	__asm__ __volatile__ (					\
134 	".set	push\n"						\
135 	".set	noreorder\n"					\
136 	".set	mips64\n"					\
137 	"dsll32	$8, %1, 0\n"					\
138 	"dsll32	$9, %0, 0\n"					\
139 	"dsrl32	$8, $8, 0\n"					\
140 	"or	$8, $8, $9\n"					\
141 	"dmtc2	$8, $%2, %3\n"					\
142 	".set	pop\n"						\
143 	: : "r"(__high), "r"(__low),  "i"(reg), "i"(sel)	\
144 	: "$8", "$9");						\
145 } struct __hack
146 
147 #endif
148 
149 NLM_DEFINE_COP2_ACCESSORS64(txbuf0, COP2_TX_BUF, 0);
150 NLM_DEFINE_COP2_ACCESSORS64(txbuf1, COP2_TX_BUF, 1);
151 NLM_DEFINE_COP2_ACCESSORS64(txbuf2, COP2_TX_BUF, 2);
152 NLM_DEFINE_COP2_ACCESSORS64(txbuf3, COP2_TX_BUF, 3);
153 
154 NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, COP2_RX_BUF, 0);
155 NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, COP2_RX_BUF, 1);
156 NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, COP2_RX_BUF, 2);
157 NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, COP2_RX_BUF, 3);
158 
159 NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, COP2_TXMSGSTATUS, 0);
160 NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, COP2_RXMSGSTATUS, 0);
161 NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, COP2_MSGSTATUS1, 0);
162 NLM_DEFINE_COP2_ACCESSORS32(msgconfig, COP2_MSGCONFIG, 0);
163 NLM_DEFINE_COP2_ACCESSORS32(msgerror0, COP2_MSGERROR, 0);
164 NLM_DEFINE_COP2_ACCESSORS32(msgerror1, COP2_MSGERROR, 1);
165 NLM_DEFINE_COP2_ACCESSORS32(msgerror2, COP2_MSGERROR, 2);
166 NLM_DEFINE_COP2_ACCESSORS32(msgerror3, COP2_MSGERROR, 3);
167 
168 /* successful completion returns 1, else 0 */
169 static inline int
nlm_msgsend(int val)170 nlm_msgsend(int val)
171 {
172 	int result;
173 	__asm__ volatile (
174 		".set push\n"
175 		".set noreorder\n"
176 		".set mips64\n"
177 		"move	$8, %1\n"
178 		"sync\n"
179 		"/* msgsnds	$9, $8 */\n"
180 		".word	0x4a084801\n"
181 		"move	%0, $9\n"
182 		".set pop\n"
183 		: "=r" (result)
184 		: "r" (val)
185 		: "$8", "$9");
186 	return result;
187 }
188 
189 static inline int
nlm_msgld(int vc)190 nlm_msgld(int vc)
191 {
192 	int val;
193 	__asm__ volatile (
194 		".set push\n"
195 		".set noreorder\n"
196 		".set mips64\n"
197 		"move	$8, %1\n"
198 		"/* msgld	$9, $8 */\n"
199 		".word 0x4a084802\n"
200 		"move	%0, $9\n"
201 		".set pop\n"
202 		: "=r" (val)
203 		: "r" (vc)
204 		: "$8", "$9");
205 	return val;
206 }
207 
208 static inline void
nlm_msgwait(int vc)209 nlm_msgwait(int vc)
210 {
211 	__asm__ volatile (
212 		".set push\n"
213 		".set noreorder\n"
214 		".set mips64\n"
215 		"move	$8, %0\n"
216 		"/* msgwait	$8 */\n"
217 		".word 0x4a080003\n"
218 		".set pop\n"
219 		: : "r" (vc)
220 		: "$8");
221 }
222 
223 static inline int
nlm_fmn_msgsend(int dstid,int size,int swcode,struct nlm_fmn_msg * m)224 nlm_fmn_msgsend(int dstid, int size, int swcode, struct nlm_fmn_msg *m)
225 {
226 	uint32_t flags, status;
227 	int rv;
228 
229 	size -= 1;
230 	flags = nlm_save_flags_cop2();
231 	switch (size) {
232 	case 3:
233 		nlm_write_c2_txbuf3(m->msg[3]);
234 	case 2:
235 		nlm_write_c2_txbuf2(m->msg[2]);
236 	case 1:
237 		nlm_write_c2_txbuf1(m->msg[1]);
238 	case 0:
239 		nlm_write_c2_txbuf0(m->msg[0]);
240 	}
241 
242 	dstid |= ((swcode << 24) | (size << 16));
243 	status = nlm_msgsend(dstid);
244 	rv = !status;
245 	if (rv != 0)
246 		rv = nlm_read_c2_txmsgstatus();
247 	nlm_restore_flags(flags);
248 
249 	return rv;
250 }
251 
252 static inline int
nlm_fmn_msgrcv(int vc,int * srcid,int * size,int * code,struct nlm_fmn_msg * m)253 nlm_fmn_msgrcv(int vc, int *srcid, int *size, int *code, struct nlm_fmn_msg *m)
254 {
255 	uint32_t status;
256 	uint32_t msg_status, flags;
257 	int tmp_sz, rv;
258 
259 	flags = nlm_save_flags_cop2();
260 	status = nlm_msgld(vc); /* will return 0, if error */
261 	rv = !status;
262 	if (rv == 0) {
263 		msg_status = nlm_read_c2_rxmsgstatus();
264 		*size = ((msg_status >> 26) & 0x3) + 1;
265 		*code = (msg_status >> 18) & 0xff;
266 		*srcid = (msg_status >> 4) & 0xfff;
267 		tmp_sz = *size - 1;
268 		switch (tmp_sz) {
269 		case 3:
270 			m->msg[3] = nlm_read_c2_rxbuf3();
271 		case 2:
272 			m->msg[2] = nlm_read_c2_rxbuf2();
273 		case 1:
274 			m->msg[1] = nlm_read_c2_rxbuf1();
275 		case 0:
276 			m->msg[0] = nlm_read_c2_rxbuf0();
277 		}
278 	}
279 	nlm_restore_flags(flags);
280 
281 	return rv;
282 }
283 
284 static inline void
nlm_fmn_cpu_init(int int_vec,int ecc_en,int v0pe,int v1pe,int v2pe,int v3pe)285 nlm_fmn_cpu_init(int int_vec, int ecc_en, int v0pe, int v1pe, int v2pe, int v3pe)
286 {
287 	uint32_t val = nlm_read_c2_msgconfig();
288 
289 	/* Note: in XLP PRM 0.8.1, the int_vec bits are un-documented
290 	 * in msgconfig register of cop2.
291 	 * As per chip/cpu RTL, [16:20] bits consist of int_vec.
292 	 */
293 	val |= (((int_vec & 0x1f) << 16) |
294 		((ecc_en & 0x1) << 8) |
295 		((v3pe & 0x1) << 4) |
296 		((v2pe & 0x1) << 3) |
297 		((v1pe & 0x1) << 2) |
298 		((v0pe & 0x1) << 1));
299 
300 	nlm_write_c2_msgconfig(val);
301 }
302 #endif
303