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