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 51struct nlm_fmn_msg { 52 uint64_t msg[4]; 53}; 54 55#define NLM_DEFINE_COP2_ACCESSORS32(name, reg, sel) \ 56static 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 \ 70static 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) \ 83static 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 \ 97static 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) \ 111static 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 \ 129static 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 149NLM_DEFINE_COP2_ACCESSORS64(txbuf0, COP2_TX_BUF, 0); 150NLM_DEFINE_COP2_ACCESSORS64(txbuf1, COP2_TX_BUF, 1); 151NLM_DEFINE_COP2_ACCESSORS64(txbuf2, COP2_TX_BUF, 2); 152NLM_DEFINE_COP2_ACCESSORS64(txbuf3, COP2_TX_BUF, 3); 153 154NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, COP2_RX_BUF, 0); 155NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, COP2_RX_BUF, 1); 156NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, COP2_RX_BUF, 2); 157NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, COP2_RX_BUF, 3); 158 159NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, COP2_TXMSGSTATUS, 0); 160NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, COP2_RXMSGSTATUS, 0); 161NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, COP2_MSGSTATUS1, 0); 162NLM_DEFINE_COP2_ACCESSORS32(msgconfig, COP2_MSGCONFIG, 0); 163NLM_DEFINE_COP2_ACCESSORS32(msgerror0, COP2_MSGERROR, 0); 164NLM_DEFINE_COP2_ACCESSORS32(msgerror1, COP2_MSGERROR, 1); 165NLM_DEFINE_COP2_ACCESSORS32(msgerror2, COP2_MSGERROR, 2); 166NLM_DEFINE_COP2_ACCESSORS32(msgerror3, COP2_MSGERROR, 3); 167 168/* successful completion returns 1, else 0 */ 169static inline int 170nlm_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 189static inline int 190nlm_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 208static inline void 209nlm_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 223static inline int 224nlm_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 252static inline int 253nlm_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 284static inline void 285nlm_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