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