1 /* $Id: rmixl_fmnvar.h,v 1.5 2024/06/06 21:18:41 andvar Exp $ */ 2 /*- 3 * Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Cliff Neighbors. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE 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 THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef _ARCH_MIPS_RMIXL_RMIXL_FMNVAR_H_ 32 #define _ARCH_MIPS_RMIXL_RMIXL_FMNVAR_H_ 33 34 #include <mips/cpuregs.h> 35 36 #define RMIXL_FMN_CODE_PSB_WAKEUP 200 /* firmware MSGRNG_CODE_BOOT_WAKEUP */ 37 #define RMIXL_FMN_CODE_HELLO_REQ 201 38 #define RMIXL_FMN_CODE_HELLO_ACK 202 39 40 #define RMIXL_FMN_HELLO_REQ_SZ 4 41 #define RMIXL_FMN_HELLO_ACK_SZ 4 42 43 typedef struct rmixl_fmn_msg { 44 uint64_t data[4]; 45 } rmixl_fmn_msg_t; 46 47 typedef struct rmixl_fmn_rxmsg { 48 u_int rxsid; 49 u_int code; 50 u_int size; 51 rmixl_fmn_msg_t msg; 52 } rmixl_fmn_rxmsg_t; 53 54 55 /* 56 * compute FMN dest_id from MIPS cpuid 57 * - each Core FMN station has 8 buckets 58 * - each Core has 4 threads 59 * - here we use 1 bucket per thread 60 * (the first four buckets) 61 * - if we need { hi, lo } priority buckets per thread 62 * need to adjust the RMIXL_FMN_DESTID macro 63 * and use the 'pri' parameter 64 * - i.e. for now there is only one priority 65 */ 66 #define RMIXL_CPU_CORE(cpuid) ((uint32_t)((cpuid) & __BITS(9,0)) >> 2) 67 #define RMIXL_CPU_THREAD(cpuid) ((uint32_t)((cpuid) & __BITS(1,0))) 68 #define RMIXL_FMN_CORE_DESTID(core, bucket) \ 69 (((core) << 3) | (bucket)) 70 71 72 #define RMIXL_DMFC2(regnum, sel, rv) \ 73 do { \ 74 uint64_t __val; \ 75 \ 76 __asm volatile( \ 77 ".set push" "\n\t" \ 78 ".set mips64" "\n\t" \ 79 ".set noat" "\n\t" \ 80 "dmfc2 %0,$%1,%2" "\n\t" \ 81 ".set pop" "\n\t" \ 82 : "=r"(__val) : "n"(regnum), "n"(sel)); \ 83 rv = __val; \ 84 } while (0) 85 86 #define RMIXL_DMTC2(regnum, sel, val) \ 87 do { \ 88 uint64_t __val = val; \ 89 \ 90 __asm volatile( \ 91 ".set push" "\n\t" \ 92 ".set mips64" "\n\t" \ 93 ".set noat" "\n\t" \ 94 "dmtc2 %0,$%1,%2" "\n\t" \ 95 ".set pop" "\n\t" \ 96 :: "r"(__val), "n"(regnum), "n"(sel)); \ 97 } while (0) 98 99 #define RMIXL_MFC2(regnum, sel, rv) \ 100 do { \ 101 uint32_t __val; \ 102 \ 103 __asm volatile( \ 104 ".set push" "\n\t" \ 105 ".set mips64" "\n\t" \ 106 "mfc2 %0,$%1,%2" "\n\t" \ 107 ".set pop" "\n\t" \ 108 : "=r"(__val) : "n"(regnum), "n"(sel)); \ 109 rv = __val; \ 110 } while (0) 111 112 #define RMIXL_MTC2(regnum, sel, val) \ 113 do { \ 114 uint32_t __val = val; \ 115 \ 116 __asm volatile( \ 117 ".set push" "\n\t" \ 118 ".set mips64" "\n\t" \ 119 "mtc2 %0,$%1,%2" "\n\t" \ 120 ".set pop" "\n\t" \ 121 :: "r"(__val), "n"(regnum), "n"(sel)); \ 122 } while (0) 123 124 #define CPU2_PRINT_8(regno, sel) \ 125 do { \ 126 uint64_t r; \ 127 RMIXL_DMFC2(regno, sel, r); \ 128 printf("%s: CP2(%d,%d) = %#"PRIx64"\n", \ 129 __func__, regno, sel, r); \ 130 } while (0) 131 132 #define CPU2_PRINT_4(regno, sel) \ 133 do { \ 134 uint32_t r; \ 135 RMIXL_MFC2(regno, sel, r); \ 136 printf("%s: CP2(%d,%d) = %#x\n", \ 137 __func__, regno, sel, r); \ 138 } while (0) 139 140 141 /* 142 * encode 'dest' for msgsnd op 'rt' 143 */ 144 #define RMIXL_MSGSND_DESC(size, code, dest_id) \ 145 ((((size) - 1) << 16) | ((code) << 8) | (dest_id)) 146 147 static inline void 148 rmixl_msgsnd(uint32_t desc) 149 { 150 __asm__ volatile ( 151 ".set push" "\n\t" 152 ".set noreorder" "\n\t" 153 ".set arch=xlr" "\n\t" 154 "sync" "\n\t" 155 "msgsnd %0" "\n\t" 156 ".set pop" "\n\t" 157 :: "r"(desc)); 158 } 159 160 static inline void 161 rmixl_msgld(uint32_t bucket) 162 { 163 __asm__ volatile ( 164 ".set push" "\n\t" 165 ".set noreorder" "\n\t" 166 ".set arch=xlr" "\n\t" 167 "msgld %0" "\n\t" 168 ".set pop" "\n\t" 169 :: "r"(bucket)); 170 } 171 172 /* 173 * the seemingly-spurious add is recommended by RMI 174 * see XLS PRM (rev. 3.21) 5.3.9 175 */ 176 static inline void 177 rmixl_fmn_msgwait(u_int mask) 178 { 179 __asm__ volatile ( 180 ".set push" "\n\t" 181 ".set noreorder" "\n\t" 182 ".set arch=xlr" "\n\t" 183 "addu %0,%0,0" "\n\t" 184 "msgwait %0" "\n\t" 185 ".set pop" "\n\t" 186 :: "r"(mask)); 187 } 188 189 static inline uint32_t 190 rmixl_cp2_enable(void) 191 { 192 uint32_t rv; 193 uint32_t cu2; 194 195 KASSERT(curcpu()->ci_cpl == IPL_HIGH); 196 __asm volatile( 197 ".set push" "\n\t" 198 ".set noreorder" "\n\t" 199 "li %1,%3" "\n\t" 200 "mfc0 %0,$%2" "\n\t" 201 "or %1,%1,%0" "\n\t" 202 "mtc0 %1,$%2" "\n\t" 203 ".set pop" "\n\t" 204 : "=r"(rv), "=r"(cu2) 205 : "n"(MIPS_COP_0_STATUS), "n"(1 << 30)); 206 207 return (rv & (1 << 30)); 208 } 209 210 static inline void 211 rmixl_cp2_restore(uint32_t ocu) 212 { 213 uint32_t cu2; 214 uint32_t mask = ~(1 << 30); 215 216 KASSERT(curcpu()->ci_cpl == IPL_HIGH); 217 __asm volatile( 218 ".set push" "\n\t" 219 ".set noreorder" "\n\t" 220 "mfc0 %0,$%1" "\n\t" 221 "and %0,%2,%0" "\n\t" 222 "or %0,%3,%0" "\n\t" 223 "mtc0 %0,$%1" "\n\t" 224 ".set pop" "\n\t" 225 : "=r"(cu2) 226 : "n"(MIPS_COP_0_STATUS), "r"(mask), "r"(ocu)); 227 } 228 229 /* 230 * logical station IDs for RMI XLR 231 * see Table 13.2 "Addressable Buckets" in the XLR PRM 232 */ 233 #define RMIXLR_FMN_STID_CORE0 0 234 #define RMIXLR_FMN_STID_CORE1 1 235 #define RMIXLR_FMN_STID_CORE2 2 236 #define RMIXLR_FMN_STID_CORE3 3 237 #define RMIXLR_FMN_STID_CORE4 4 238 #define RMIXLR_FMN_STID_CORE5 5 239 #define RMIXLR_FMN_STID_CORE6 6 240 #define RMIXLR_FMN_STID_CORE7 7 241 #define RMIXLR_FMN_STID_TXRX_0 8 242 #define RMIXLR_FMN_STID_TXRX_1 9 243 #define RMIXLR_FMN_STID_RGMII 10 244 #define RMIXLR_FMN_STID_DMA 11 245 #define RMIXLR_FMN_STID_FREE_0 12 246 #define RMIXLR_FMN_STID_FREE_1 13 247 #define RMIXLR_FMN_STID_SAE 14 248 #define RMIXLR_FMN_NSTID (RMIXLR_FMN_STID_SAE+1) 249 #define RMIXLR_FMN_STID_RESERVED -1 250 251 /* 252 * logical station IDs for RMI XLS 253 * see Table 12.1 "Stations and Addressable Buckets ..." in the XLS PRM 254 */ 255 #define RMIXLS_FMN_STID_CORE0 0 256 #define RMIXLS_FMN_STID_CORE1 1 257 #define RMIXLS_FMN_STID_CORE2 2 258 #define RMIXLS_FMN_STID_CORE3 3 259 #define RMIXLS_FMN_STID_GMAC_Q0 4 260 #define RMIXLS_FMN_STID_GMAC_Q1 5 261 #define RMIXLS_FMN_STID_DMA 6 262 #define RMIXLS_FMN_STID_CDE 7 263 #define RMIXLS_FMN_STID_PCIE 8 264 #define RMIXLS_FMN_STID_SAE 9 265 #define RMIXLS_FMN_NSTID (RMIXLS_FMN_STID_SAE+1) 266 #define RMIXLS_FMN_STID_RESERVED -1 267 268 /* 269 * logical station IDs for RMI XLP 270 * TBD! 271 */ 272 #define RMIXLP_FMN_NSTID 0 /* XXX */ 273 274 275 #define RMIXL_FMN_NSTID \ 276 MAX(MAX(RMIXLR_FMN_NSTID, RMIXLS_FMN_NSTID), RMIXLP_FMN_NSTID) 277 278 279 #define RMIXL_FMN_INTR_IPL IPL_HIGH 280 281 void rmixl_fmn_init(void); 282 void rmixl_fmn_init_core(void); 283 void rmixl_fmn_init_cpu_intr(void); 284 void *rmixl_fmn_intr_establish(int, int (*)(void *, rmixl_fmn_rxmsg_t *), void *); 285 void rmixl_fmn_intr_disestablish(void *); 286 void rmixl_fmn_intr_poll(u_int, rmixl_fmn_rxmsg_t *); 287 int rmixl_fmn_msg_send(u_int, u_int, u_int, rmixl_fmn_msg_t *); 288 int rmixl_fmn_msg_recv(u_int, rmixl_fmn_rxmsg_t *); 289 290 291 292 #endif /* _ARCH_MIPS_RMIXL_RMIXL_FMNVAR_H_ */ 293