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