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 53struct nlm_fmn_msg { 54 uint64_t msg[4]; 55}; 56 57#define NLM_DEFINE_COP2_ACCESSORS32(name, reg, sel) \ 58static 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 \ 72static 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) \ 85static 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 \ 99static 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) \ 113static 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 \ 131static 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 151NLM_DEFINE_COP2_ACCESSORS64(txbuf0, COP2_TX_BUF, 0); 152NLM_DEFINE_COP2_ACCESSORS64(txbuf1, COP2_TX_BUF, 1); 153NLM_DEFINE_COP2_ACCESSORS64(txbuf2, COP2_TX_BUF, 2); 154NLM_DEFINE_COP2_ACCESSORS64(txbuf3, COP2_TX_BUF, 3); 155 156NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, COP2_RX_BUF, 0); 157NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, COP2_RX_BUF, 1); 158NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, COP2_RX_BUF, 2); 159NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, COP2_RX_BUF, 3); 160 161NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, COP2_TXMSGSTATUS, 0); 162NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, COP2_RXMSGSTATUS, 0); 163NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, COP2_MSGSTATUS1, 0); 164NLM_DEFINE_COP2_ACCESSORS32(msgconfig, COP2_MSGCONFIG, 0); 165NLM_DEFINE_COP2_ACCESSORS32(msgerror0, COP2_MSGERROR, 0); 166NLM_DEFINE_COP2_ACCESSORS32(msgerror1, COP2_MSGERROR, 1); 167NLM_DEFINE_COP2_ACCESSORS32(msgerror2, COP2_MSGERROR, 2); 168NLM_DEFINE_COP2_ACCESSORS32(msgerror3, COP2_MSGERROR, 3); 169 170/* successful completion returns 1, else 0 */ 171static inline int 172nlm_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 191static inline int 192nlm_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 210static inline void 211nlm_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 225static inline int 226nlm_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 254static inline int 255nlm_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 286static inline void 287nlm_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