1/* $NetBSD: rmixl_fmn.c,v 1.5 2023/08/11 07:05:39 mrg 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#include "opt_ddb.h" 32 33#include <sys/cdefs.h> 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/cpu.h> 37#include <mips/cpuregs.h> 38#include <mips/rmi/rmixlreg.h> 39#include <mips/rmi/rmixlvar.h> 40#include <mips/rmi/rmixl_intr.h> 41#include <mips/rmi/rmixl_fmnvar.h> 42 43#ifdef FMN_DEBUG 44# define DPRINTF(x) do { printf x ; } while(0) 45#else 46# define DPRINTF(x) 47#endif 48 49#ifdef DIAGNOSTIC 50# define DIAG_PRF(x) do { printf x ; } while(0) 51#else 52# define DIAG_PRF(x) 53#endif 54 55 56 57/* 58 * index CPU-dependent table by (global) bucket ID to obtain logical Station ID 59 * see Table 12.1 in the XLS PRM 60 */ 61/* use this table for XLS6xx, XLS4xx */ 62static const int station_xls_4xx[] = { 63 [0 ... 7] = RMIXLS_FMN_STID_CORE0, 64 [8 ... 15] = RMIXLS_FMN_STID_CORE1, 65 [16 ... 23] = RMIXLS_FMN_STID_CORE2, 66 [24 ... 31] = RMIXLS_FMN_STID_CORE3, 67 [32 ... 63] = RMIXLS_FMN_STID_RESERVED, 68 [64 ... 71] = RMIXLS_FMN_STID_PCIE, 69 [72 ... 79] = RMIXLS_FMN_STID_RESERVED, 70 [80 ... 87] = RMIXLS_FMN_STID_GMAC_Q1, 71 [88 ... 95] = RMIXLS_FMN_STID_RESERVED, 72 [96 ... 103] = RMIXLS_FMN_STID_GMAC_Q0, 73 [104 ... 107] = RMIXLS_FMN_STID_DMA, 74 [108 ... 109] = RMIXLS_FMN_STID_CDE, 75 [110 ... 119] = RMIXLS_FMN_STID_RESERVED, 76 [120 ... 127] = RMIXLS_FMN_STID_SAE, 77}; 78 79/* use this table for XLS408Lite, XLS404Lite */ 80static const int station_xls_4xx_lite[] = { 81 [0 ... 7] = RMIXLS_FMN_STID_CORE0, 82 [8 ... 15] = RMIXLS_FMN_STID_CORE1, 83 [16 ... 23] = RMIXLS_FMN_STID_CORE2, 84 [24 ... 31] = RMIXLS_FMN_STID_CORE3, 85 [32 ... 79] = RMIXLS_FMN_STID_RESERVED, 86 [80 ... 87] = RMIXLS_FMN_STID_GMAC_Q1, 87 [88 ... 95] = RMIXLS_FMN_STID_RESERVED, 88 [96 ... 103] = RMIXLS_FMN_STID_GMAC_Q0, 89 [104 ... 107] = RMIXLS_FMN_STID_DMA, 90 [108 ... 109] = RMIXLS_FMN_STID_CDE, 91 [110 ... 115] = RMIXLS_FMN_STID_RESERVED, 92 [116 ... 119] = RMIXLS_FMN_STID_PCIE, 93 [120 ... 127] = RMIXLS_FMN_STID_SAE, 94}; 95 96/* use this table for XLS2xx */ 97static const int station_xls_2xx[] = { 98 [0 ... 7] = RMIXLS_FMN_STID_CORE0, 99 [8 ... 15] = RMIXLS_FMN_STID_CORE1, 100 [16 ... 23] = RMIXLS_FMN_STID_CORE2, 101 [24 ... 31] = RMIXLS_FMN_STID_CORE3, 102 [32 ... 63] = RMIXLS_FMN_STID_RESERVED, 103 [64 ... 71] = RMIXLS_FMN_STID_PCIE, 104 [72 ... 95] = RMIXLS_FMN_STID_RESERVED, 105 [96 ... 103] = RMIXLS_FMN_STID_GMAC_Q0, 106 [104 ... 107] = RMIXLS_FMN_STID_DMA, 107 [108 ... 119] = RMIXLS_FMN_STID_RESERVED, 108 [120 ... 127] = RMIXLS_FMN_STID_SAE, 109}; 110 111/* use this table for XLS1xx */ 112static const int station_xls_1xx[] = { 113 [0 ... 7] = RMIXLS_FMN_STID_CORE0, 114 [8 ... 15] = RMIXLS_FMN_STID_CORE1, 115 [16 ... 23] = RMIXLS_FMN_STID_CORE2, 116 [24 ... 31] = RMIXLS_FMN_STID_CORE3, 117 [32 ... 63] = RMIXLS_FMN_STID_RESERVED, 118 [64 ... 71] = RMIXLS_FMN_STID_PCIE, 119 [72 ... 95] = RMIXLS_FMN_STID_RESERVED, 120 [96 ... 101] = RMIXLS_FMN_STID_GMAC_Q0, 121 [102 ... 103] = RMIXLS_FMN_STID_RESERVED, 122 [104 ... 107] = RMIXLS_FMN_STID_DMA, 123 [108 ... 119] = RMIXLS_FMN_STID_RESERVED, 124 [120 ... 127] = RMIXLS_FMN_STID_SAE, 125}; 126 127/* use this table for XLRxxx */ 128static const int station_xlr_xxx[] = { 129 [0 ... 7] = RMIXLR_FMN_STID_CORE0, 130 [8 ... 15] = RMIXLR_FMN_STID_CORE1, 131 [16 ... 23] = RMIXLR_FMN_STID_CORE2, 132 [24 ... 31] = RMIXLR_FMN_STID_CORE3, 133 [32 ... 39] = RMIXLR_FMN_STID_CORE4, 134 [40 ... 47] = RMIXLR_FMN_STID_CORE5, 135 [48 ... 55] = RMIXLR_FMN_STID_CORE6, 136 [56 ... 63] = RMIXLR_FMN_STID_CORE7, 137 [64 ... 79] = RMIXLR_FMN_STID_TXRX_0, 138 [80 ... 95] = RMIXLR_FMN_STID_TXRX_1, 139 [96 ... 103] = RMIXLR_FMN_STID_RGMII, 140 [104 ... 107] = RMIXLR_FMN_STID_DMA, 141 [108 ... 111] = RMIXLR_FMN_STID_RESERVED, 142 [112 ... 113] = RMIXLR_FMN_STID_FREE_0, 143 [114 ... 115] = RMIXLR_FMN_STID_FREE_0, 144 [116 ... 119] = RMIXLR_FMN_STID_RESERVED, 145 [120 ... 127] = RMIXLR_FMN_STID_SAE, 146}; 147 148typedef struct fmn_station_info { 149 const char *si_name; 150 const u_int si_buckets_max; 151 const u_int si_stid_first; 152 const u_int si_stid_last; 153 const u_int si_bucket_size_dflt; 154 const u_int si_credits_min; 155 const u_int si_regbase; 156} fmn_station_info_t; 157 158/* use this table for XLS6xx, XLS4xx */ 159static const fmn_station_info_t station_info_xls_4xx[RMIXLS_FMN_NSTID] = { 160 [RMIXLS_FMN_STID_CORE0] = { "core0", 8, 0, 7, 32, 4, 0 }, 161 [RMIXLS_FMN_STID_CORE1] = { "core1", 8, 8, 15, 32, 4, 0 }, 162 [RMIXLS_FMN_STID_CORE2] = { "core2", 8, 16, 23, 32, 4, 0 }, 163 [RMIXLS_FMN_STID_CORE3] = { "core3", 8, 24, 31, 32, 4, 0 }, 164 [RMIXLS_FMN_STID_GMAC_Q0] = { "gmac_q0", 3, 80, 87, 32, 0, RMIXL_IO_DEV_GMAC_0 }, 165 [RMIXLS_FMN_STID_GMAC_Q1] = { "gmac_q1", 3, 96, 103, 32, 0, RMIXL_IO_DEV_GMAC_4 }, 166 [RMIXLS_FMN_STID_DMA] = { "dma", 4, 104, 107, 64, 0, RMIXL_IO_DEV_DMA }, 167 [RMIXLS_FMN_STID_CDE] = { "cde", 4, 108, 109, 128, 0, RMIXL_IO_DEV_CDE }, 168 [RMIXLS_FMN_STID_PCIE] = { "pcie", 8, 64, 71, 32, 0, RMIXL_IO_DEV_PCIE_BE }, 169 [RMIXLS_FMN_STID_SAE] = { "sae", 2, 120, 121, 128, 0, RMIXL_IO_DEV_SAE }, 170}; 171 172/* use this table for XLS4xxLite */ 173static const fmn_station_info_t station_info_xls_4xx_lite[RMIXLS_FMN_NSTID] = { 174 [RMIXLS_FMN_STID_CORE0] = { "core0", 8, 0, 7, 32, 4, 0 }, 175 [RMIXLS_FMN_STID_CORE1] = { "core1", 8, 8, 15, 32, 4, 0 }, 176 [RMIXLS_FMN_STID_CORE2] = { "core2", 8, 16, 23, 32, 4, 0 }, 177 [RMIXLS_FMN_STID_CORE3] = { "core3", 8, 24, 31, 32, 4, 0 }, 178 [RMIXLS_FMN_STID_GMAC_Q0] = { "gmac_q0", 3, 80, 87, 32, 0, RMIXL_IO_DEV_GMAC_0 }, 179 [RMIXLS_FMN_STID_GMAC_Q1] = { "gmac_q1", 3, 96, 103, 32, 0, RMIXL_IO_DEV_GMAC_4 }, 180 [RMIXLS_FMN_STID_DMA] = { "dma", 4, 104, 107, 64, 0, RMIXL_IO_DEV_DMA }, 181 [RMIXLS_FMN_STID_CDE] = { "cde", 4, 108, 109, 128, 0, RMIXL_IO_DEV_CDE }, 182 [RMIXLS_FMN_STID_PCIE] = { "pcie", 4, 116, 119, 64, 0, RMIXL_IO_DEV_PCIE_BE }, 183 [RMIXLS_FMN_STID_SAE] = { "sae", 2, 120, 121, 128, 0, RMIXL_IO_DEV_SAE }, 184}; 185 186/* use this table for XLS2xx */ 187static const fmn_station_info_t station_info_xls_2xx[RMIXLS_FMN_NSTID] = { 188 [RMIXLS_FMN_STID_CORE0] = { "core0", 8, 0, 7, 32, 4, 0 }, 189 [RMIXLS_FMN_STID_CORE1] = { "core1", 8, 8, 15, 32, 4, 0 }, 190 [RMIXLS_FMN_STID_CORE2] = { "core2", 8, 16, 23, 32, 4, 0 }, 191 [RMIXLS_FMN_STID_CORE3] = { "core3", 8, 24, 31, 32, 4, 0 }, 192 [RMIXLS_FMN_STID_GMAC_Q0] = { "gmac_q0", 3, 96, 103, 32, 0, RMIXL_IO_DEV_GMAC_0 }, 193 [RMIXLS_FMN_STID_DMA] = { "dma", 4, 104, 107, 64, 0, RMIXL_IO_DEV_DMA }, 194 [RMIXLS_FMN_STID_PCIE] = { "pcie", 8, 64, 71, 32, 0, RMIXL_IO_DEV_PCIE_BE }, 195 [RMIXLS_FMN_STID_SAE] = { "sae", 2, 120, 121, 128, 0, RMIXL_IO_DEV_SAE }, 196}; 197 198/* use this table for XLS1xx */ 199static const fmn_station_info_t station_info_xls_1xx[RMIXLS_FMN_NSTID] = { 200 [RMIXLS_FMN_STID_CORE0] = { "core0", 8, 0, 7, 32, 4, 0 }, 201 [RMIXLS_FMN_STID_CORE1] = { "core1", 8, 8, 15, 32, 4, 0 }, 202 [RMIXLS_FMN_STID_CORE2] = { "core2", 8, 16, 23, 32, 4, 0 }, 203 [RMIXLS_FMN_STID_CORE3] = { "core3", 8, 24, 31, 32, 4, 0 }, 204 [RMIXLS_FMN_STID_GMAC_Q0] = { "gmac_q0", 3, 96, 101, 32, 0, RMIXL_IO_DEV_GMAC_0 }, 205 [RMIXLS_FMN_STID_DMA] = { "dma", 4, 104, 107, 64, 0, RMIXL_IO_DEV_PCIE_BE }, 206 [RMIXLS_FMN_STID_PCIE] = { "pcie", 4, 64, 67, 32, 0, RMIXL_IO_DEV_PCIE_BE }, 207 [RMIXLS_FMN_STID_SAE] = { "sae", 2, 120, 121, 128, 0, RMIXL_IO_DEV_SAE }, 208}; 209 210/* 211 * use this table for XLRxxx 212 * caution: 213 * - the XGMII/SPI4 stations si_regbase are 'special' 214 * - the RGMII station si_regbase is 'special' 215 */ 216static const fmn_station_info_t station_info_xlr_xxx[RMIXLR_FMN_NSTID] = { 217 [RMIXLR_FMN_STID_CORE0] = { "core0", 8, 0, 7, 32, 4, 0 }, 218 [RMIXLR_FMN_STID_CORE1] = { "core1", 8, 8, 15, 32, 4, 0 }, 219 [RMIXLR_FMN_STID_CORE2] = { "core2", 8, 16, 23, 32, 4, 0 }, 220 [RMIXLR_FMN_STID_CORE3] = { "core3", 8, 24, 31, 32, 4, 0 }, 221 [RMIXLR_FMN_STID_CORE4] = { "core4", 8, 32, 39, 32, 4, 0 }, 222 [RMIXLR_FMN_STID_CORE5] = { "core5", 8, 40, 47, 32, 4, 0 }, 223 [RMIXLR_FMN_STID_CORE6] = { "core6", 8, 48, 55, 32, 4, 0 }, 224 [RMIXLR_FMN_STID_CORE7] = { "core7", 8, 56, 63, 32, 4, 0 }, 225 [RMIXLR_FMN_STID_TXRX_0] = { "txrx0", 1, 64, 79, 16, 0, RMIXL_IO_DEV_XGMAC_A }, 226 [RMIXLR_FMN_STID_TXRX_1] = { "txrx1", 1, 80, 95, 16, 0, RMIXL_IO_DEV_XGMAC_B }, 227 [RMIXLR_FMN_STID_RGMII] = { "rgmii", 8, 96, 103, 32, 0, RMIXL_IO_DEV_GMAC_A }, 228 [RMIXLR_FMN_STID_DMA] = { "dma", 4, 104, 107, 64, 0, RMIXL_IO_DEV_DMA }, 229 [RMIXLR_FMN_STID_FREE_0] = { "free0", 2, 112, 113, 128, 0, RMIXL_IO_DEV_XGMAC_A }, 230 [RMIXLR_FMN_STID_FREE_1] = { "free1", 2, 114, 115, 128, 0, RMIXL_IO_DEV_XGMAC_B }, 231 [RMIXLR_FMN_STID_SAE] = { "sae", 5, 120, 124, 32, 0, RMIXL_IO_DEV_SAE }, 232}; 233 234 235typedef struct fmn_intrhand { 236 int (*ih_func)(void *, rmixl_fmn_rxmsg_t *); 237 void *ih_arg; 238 struct evcnt ih_count; 239} fmn_intrhand_t; 240 241/* 242 * per-core FMN structure 243 */ 244typedef struct fmn { 245 kmutex_t *fmn_lock; 246 u_int fmn_core; 247 u_int fmn_thread; 248 u_int fmn_nstid; 249 const int *fmn_stidtab; 250 const fmn_station_info_t *fmn_stinfo; 251 void *fmn_ih; 252 fmn_intrhand_t fmn_intrhand[RMIXL_FMN_NSTID]; 253} fmn_t; 254 255static fmn_t fmn_store[1 << 10]; /* index by cpuid) *//* XXX assumes 1 node */ 256#define NFMN (sizeof(fmn_store) / sizeof(fmn_store[0])) 257 258static fmn_t * 259fmn_lookup(cpuid_t cpuid) 260{ 261 KASSERT(cpuid < (cpuid_t)NFMN); 262 return &fmn_store[cpuid]; 263} 264 265static void rmixl_fmn_init_core_xlr(fmn_t *); 266static void rmixl_fmn_init_core_xls(fmn_t *); 267static void rmixl_fmn_config_noncore(fmn_t *); 268static void rmixl_fmn_config_core(fmn_t *); 269#ifdef NOTYET 270static int rmixl_fmn_intr_dispatch(void *); 271#endif /* NOTYET */ 272static int rmixl_fmn_msg_recv_subr(u_int, rmixl_fmn_rxmsg_t *); 273 274#ifdef FMN_DEBUG 275void rmixl_fmn_cp2_dump(void); 276void rmixl_fmn_cc_dump(void); 277#endif 278 279/* 280 * macros used because mtc2, mfc2, dmtc2, dmfc2 instructions 281 * must use literal values for rd and sel operands 282 * so let the compiler sort it out 283 */ 284 285/* 286 * write v to all 8 SELs for given RD 287 */ 288#define FMN_CP2_4SEL_READ(rd, sel, vp) \ 289 do { \ 290 uint32_t *rp = vp; \ 291 RMIXL_MFC2(rd, sel, rp[0]); \ 292 RMIXL_MFC2(rd, sel+1, rp[1]); \ 293 RMIXL_MFC2(rd, sel+2, rp[2]); \ 294 RMIXL_MFC2(rd, sel+3, rp[3]); \ 295 } while (0) 296 297/* 298 * write v to all 8 SELs for given RD 299 */ 300#define FMN_CP2_4SEL_WRITE(rd, sel, v) \ 301 do { \ 302 RMIXL_MTC2(rd, sel, v); \ 303 RMIXL_MTC2(rd, sel+1, v); \ 304 RMIXL_MTC2(rd, sel+2, v); \ 305 RMIXL_MTC2(rd, sel+3, v); \ 306 } while (0) 307 308#define FMN_CP2_8SEL_WRITE(rd, v) \ 309 do { \ 310 RMIXL_MTC2(rd, 0, v); \ 311 RMIXL_MTC2(rd, 1, v); \ 312 RMIXL_MTC2(rd, 2, v); \ 313 RMIXL_MTC2(rd, 3, v); \ 314 RMIXL_MTC2(rd, 4, v); \ 315 RMIXL_MTC2(rd, 5, v); \ 316 RMIXL_MTC2(rd, 6, v); \ 317 RMIXL_MTC2(rd, 7, v); \ 318 } while (0) 319 320 321#define FMN_CP2_SEL_CASE_READ(rd, sel, v) \ 322 case sel: \ 323 RMIXL_MFC2(rd, sel, v); \ 324 break 325#define FMN_CP2_SEL_CASE_WRITE(rd, sel, v) \ 326 case sel: \ 327 RMIXL_MTC2(rd, sel, v); \ 328 break 329/* 330 * read/write a single arbitrary sel for the given rd 331 */ 332#define FMN_CP2_SEL_SWITCH_RW(rw, rd, sel, val) \ 333 do { \ 334 switch (sel) { \ 335 FMN_CP2_SEL_CASE_ ## rw(rd, 0, val); \ 336 FMN_CP2_SEL_CASE_ ## rw(rd, 1, val); \ 337 FMN_CP2_SEL_CASE_ ## rw(rd, 2, val); \ 338 FMN_CP2_SEL_CASE_ ## rw(rd, 3, val); \ 339 FMN_CP2_SEL_CASE_ ## rw(rd, 4, val); \ 340 FMN_CP2_SEL_CASE_ ## rw(rd, 5, val); \ 341 FMN_CP2_SEL_CASE_ ## rw(rd, 6, val); \ 342 FMN_CP2_SEL_CASE_ ## rw(rd, 7, val); \ 343 default: \ 344 panic("%s:%d: bad sel %d\n", \ 345 __func__, __LINE__, sel); \ 346 } \ 347 } while (0) 348 349#define FMN_CP2_RD_CASE_RW(rw, rd, sel, val) \ 350 case rd: \ 351 FMN_CP2_SEL_SWITCH_RW(rw, rd, sel, val); \ 352 break 353/* 354 * read/write a single arbitrary Credit Counter at (rd, sel) 355 * eg: 356 * FMN_CP2_RD_SWITCH_RW(READ, 16, 2, val) 357 * FMN_CP2_RD_SWITCH_RW(WRITE, 18, 0, val) 358 */ 359#define FMN_CP2_RD_SWITCH_RW(rw, rd, sel, val) \ 360 do { \ 361 switch(rd) { \ 362 FMN_CP2_RD_CASE_RW(rw, 0, sel, val); \ 363 FMN_CP2_RD_CASE_RW(rw, 1, sel, val); \ 364 FMN_CP2_RD_CASE_RW(rw, 2, sel, val); \ 365 FMN_CP2_RD_CASE_RW(rw, 3, sel, val); \ 366 FMN_CP2_RD_CASE_RW(rw, 4, sel, val); \ 367 FMN_CP2_RD_CASE_RW(rw, 5, sel, val); \ 368 FMN_CP2_RD_CASE_RW(rw, 6, sel, val); \ 369 FMN_CP2_RD_CASE_RW(rw, 7, sel, val); \ 370 FMN_CP2_RD_CASE_RW(rw, 8, sel, val); \ 371 FMN_CP2_RD_CASE_RW(rw, 9, sel, val); \ 372 FMN_CP2_RD_CASE_RW(rw, 10, sel, val); \ 373 FMN_CP2_RD_CASE_RW(rw, 11, sel, val); \ 374 FMN_CP2_RD_CASE_RW(rw, 12, sel, val); \ 375 FMN_CP2_RD_CASE_RW(rw, 13, sel, val); \ 376 FMN_CP2_RD_CASE_RW(rw, 14, sel, val); \ 377 FMN_CP2_RD_CASE_RW(rw, 15, sel, val); \ 378 FMN_CP2_RD_CASE_RW(rw, 16, sel, val); \ 379 FMN_CP2_RD_CASE_RW(rw, 17, sel, val); \ 380 FMN_CP2_RD_CASE_RW(rw, 18, sel, val); \ 381 FMN_CP2_RD_CASE_RW(rw, 19, sel, val); \ 382 FMN_CP2_RD_CASE_RW(rw, 20, sel, val); \ 383 FMN_CP2_RD_CASE_RW(rw, 21, sel, val); \ 384 FMN_CP2_RD_CASE_RW(rw, 22, sel, val); \ 385 FMN_CP2_RD_CASE_RW(rw, 23, sel, val); \ 386 FMN_CP2_RD_CASE_RW(rw, 24, sel, val); \ 387 FMN_CP2_RD_CASE_RW(rw, 25, sel, val); \ 388 FMN_CP2_RD_CASE_RW(rw, 26, sel, val); \ 389 FMN_CP2_RD_CASE_RW(rw, 27, sel, val); \ 390 FMN_CP2_RD_CASE_RW(rw, 28, sel, val); \ 391 FMN_CP2_RD_CASE_RW(rw, 29, sel, val); \ 392 FMN_CP2_RD_CASE_RW(rw, 30, sel, val); \ 393 FMN_CP2_RD_CASE_RW(rw, 31, sel, val); \ 394 default: \ 395 panic("%s:%d: bad regno %d\n", \ 396 __func__, __LINE__, rd); \ 397 } \ 398 } while (0) 399 400 401void 402rmixl_fmn_init(void) 403{ 404 int cpu; 405 fmn_t *fmnp; 406 static bool once=false; 407 408 KASSERTMSG((CPU_IS_PRIMARY(curcpu())), "ci=%p, index=%d\n", 409 curcpu(), cpu_index(curcpu())); 410 fmnp = fmn_lookup(curcpu()->ci_cpuid); 411 412 if (once == true) 413 panic("%s: call only once!", __func__); 414 once = true; 415 416 for (cpu=0; cpu < NFMN; cpu++) { 417 fmnp[cpu].fmn_core = RMIXL_CPU_CORE(cpu); 418 fmnp[cpu].fmn_thread = RMIXL_CPU_THREAD(cpu); 419 } 420 421 rmixl_fmn_init_core(); /* for initial boot cpu (#0) */ 422 rmixl_fmn_config_noncore(fmnp); /* boot cpu initializes noncore */ 423} 424 425/* 426 * link to TX station ID table for RMI XLR type chip 427 */ 428static void 429rmixl_fmn_init_core_xlr(fmn_t *fmnp) 430{ 431 fmnp->fmn_nstid = RMIXLR_FMN_NSTID; 432 fmnp->fmn_stidtab = station_xlr_xxx; 433 fmnp->fmn_stinfo = station_info_xlr_xxx; 434} 435 436/* 437 * link to TX station ID table for RMI XLS type chip 438 */ 439static void 440rmixl_fmn_init_core_xls(fmn_t *fmnp) 441{ 442 const fmn_station_info_t *info = NULL; 443 const int *tab = NULL; 444 445 switch (MIPS_PRID_IMPL(mips_options.mips_cpu_id)) { 446 case MIPS_XLS104: 447 case MIPS_XLS108: 448 tab = station_xls_1xx; 449 info = station_info_xls_1xx; 450 break; 451 case MIPS_XLS204: 452 case MIPS_XLS208: 453 tab = station_xls_2xx; 454 info = station_info_xls_2xx; 455 break; 456 case MIPS_XLS404: 457 case MIPS_XLS408: 458 case MIPS_XLS416: 459 case MIPS_XLS608: 460 case MIPS_XLS616: 461 tab = station_xls_4xx; 462 info = station_info_xls_4xx; 463 break; 464 case MIPS_XLS404LITE: 465 case MIPS_XLS408LITE: 466 tab = station_xls_4xx_lite; 467 info = station_info_xls_4xx_lite; 468 break; 469 default: 470 panic("%s: unknown PRID IMPL %#x\n", __func__, 471 MIPS_PRID_IMPL(mips_options.mips_cpu_id)); 472 } 473 474 fmnp->fmn_nstid = RMIXLS_FMN_NSTID; 475 fmnp->fmn_stidtab = tab; 476 fmnp->fmn_stinfo = info; 477} 478 479void 480rmixl_fmn_init_core(void) 481{ 482 fmn_t *fmnp; 483 kmutex_t *lk; 484 485 fmnp = fmn_lookup(curcpu()->ci_cpuid); 486 KASSERT(fmnp != NULL); 487 KASSERT(fmnp->fmn_core == RMIXL_CPU_CORE(curcpu()->ci_cpuid)); 488 KASSERT(fmnp->fmn_thread == RMIXL_CPU_THREAD(curcpu()->ci_cpuid)); 489 490 lk = mutex_obj_alloc(MUTEX_DEFAULT, RMIXL_FMN_INTR_IPL); 491 if (lk == NULL) 492 panic("%s: mutex_obj_alloc failed", __func__); 493 fmnp->fmn_lock = lk; 494 495 mutex_enter(fmnp->fmn_lock); 496 497 /* 498 * do chip-dependent per-core FMN initialization 499 */ 500 switch(cpu_rmixl_chip_type(mips_options.mips_cpu)) { 501 case CIDFL_RMI_TYPE_XLR: 502 rmixl_fmn_init_core_xlr(fmnp); 503 break; 504 case CIDFL_RMI_TYPE_XLS: 505 rmixl_fmn_init_core_xls(fmnp); 506 break; 507 case CIDFL_RMI_TYPE_XLP: 508 panic("%s: RMI XLP not yet supported", __func__); 509 default: 510 panic("%s: RMI chip type %#x unknown", __func__, 511 cpu_rmixl_chip_type(mips_options.mips_cpu)); 512 } 513 514 /* 515 * thread #0 for each core owns 'global' CP2 regs 516 */ 517 if (fmnp->fmn_thread == 0) 518 rmixl_fmn_config_core(fmnp); 519 520 mutex_exit(fmnp->fmn_lock); 521} 522 523/* 524 * rmixl_fmn_config_noncore 525 * 526 * initialize bucket sizes and (minimum) credits for non-core stations to ZERO 527 * configured through memory write operations instead of CP2 528 */ 529static void 530rmixl_fmn_config_noncore(fmn_t *fmnp) 531{ 532 for (u_int sid=0; sid < fmnp->fmn_nstid; sid++) { 533 u_int regoff = fmnp->fmn_stinfo[sid].si_regbase; 534 if (regoff != 0) { 535 u_int buckets_max = fmnp->fmn_stinfo[sid].si_buckets_max; 536 regoff += RMIXL_FMN_BS_FIRST; 537 for (u_int bucket=0; bucket < buckets_max; bucket++) { 538 RMIXL_IOREG_WRITE(regoff, 0); 539 regoff += sizeof(uint32_t); 540 } 541 } 542 } 543} 544 545/* 546 * rmixl_fmn_config_core 547 * 548 * - assumes fmn_mutex is owned 549 * - configure FMN 550 * - initialize bucket sizes and (minimum) credits for a core 551 */ 552static void 553rmixl_fmn_config_core(fmn_t *fmnp) 554{ 555 const fmn_station_info_t *info = fmnp->fmn_stinfo; 556 uint32_t sts1; 557 uint32_t cfg; 558 uint32_t cp0_status; 559 560 KASSERT(mutex_owned(fmnp->fmn_lock) != 0); 561 KASSERT(fmnp->fmn_thread == 0); 562 cp0_status = rmixl_cp2_enable(); 563 564 /* check/clear any pre-existing status1 error(s) */ 565 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 1, sts1); 566 if ((sts1 & RMIXL_MSG_STS1_ERRS) != 0) 567 RMIXL_MTC2(RMIXL_COP_2_MSG_STS, 1, sts1); 568 569 /* set up MsgConfig reg */ 570 cfg = ((1 << RMIXL_MSG_CFG0_WMSHIFT) /* watermark */ 571 | (RMIXL_INTRVEC_FMN << RMIXL_MSG_CFG0_IV_SHIFT) /* irq */ 572 | (1 << RMIXL_MSG_CFG0_ITM_SHIFT) /* thread mask */ 573 | RMIXL_MSG_CFG0_WIE /* watermark intr enb */ 574 | RMIXL_MSG_CFG0_EIE); /* rx not empty intr enb */ 575 RMIXL_DMTC2(RMIXL_COP_2_MSG_CFG, 0, cfg); 576 577 /* disable trace mode, credit overrun intr, messaging errors intr */ 578 RMIXL_DMTC2(RMIXL_COP_2_MSG_CFG, 0, 0); 579 580 /* XXX using 4 buckets per core */ 581 KASSERT(4 <= info->si_buckets_max); 582 583 /* 584 * initialize default sizes for core buckets 585 * zero sizes for unused buckets 586 */ 587 KASSERT(info->si_buckets_max == 8); 588 uint32_t sz = info->si_bucket_size_dflt; 589 KASSERT((sz & ~RMIXL_MSG_BSZ_SIZE) == 0); 590 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 0, sz); 591 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 1, sz); 592 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 2, sz); 593 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 3, sz); 594 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 4, 0); 595 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 5, 0); 596 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 6, 0); 597 RMIXL_MTC2(RMIXL_COP_2_MSG_BSZ, 7, 0); 598 599 /* 600 * configure minimum credits for each core, 4 buckets 601 * zero all unused credit counters for this core 602 */ 603 uint32_t cr = info->si_credits_min; 604 605 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS, 0, cr); 606 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS, 4, 0); 607 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS+1, 0, cr); 608 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS+1, 4, 0); 609 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS+2, 0, cr); 610 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS+2, 4, 0); 611 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS+3, 0, cr); 612 FMN_CP2_4SEL_WRITE(RMIXL_COP_2_CREDITS+3, 4, 0); 613 614 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+4, 0); 615 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+5, 0); 616 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+6, 0); 617 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+7, 0); 618 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+8, 0); 619 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+9, 0); 620 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+10, 0); 621 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+11, 0); 622 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+12, 0); 623 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+13, 0); 624 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+14, 0); 625 FMN_CP2_8SEL_WRITE(RMIXL_COP_2_CREDITS+15, 0); 626 627 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 1, sts1); 628 KASSERT((sts1 & RMIXL_MSG_STS1_ERRS) == 0); 629 630 rmixl_cp2_restore(cp0_status); 631} 632 633void 634rmixl_fmn_init_cpu_intr(void) 635{ 636 fmn_t *fmnp; 637 638 fmnp = fmn_lookup(curcpu()->ci_cpuid); 639 mutex_enter(fmnp->fmn_lock); 640 641 for (int i=0; i < fmnp->fmn_nstid; i++) 642 evcnt_attach_dynamic(&fmnp->fmn_intrhand[i].ih_count, 643 EVCNT_TYPE_INTR, NULL, "rmixl_fmn", fmnp->fmn_stinfo[i].si_name); 644 645#ifdef NOTYET 646 /* 647 * establish dispatcher for FMN interrupt 648 */ 649 extern kmutex_t rmixl_intr_lock; 650 void *ih; 651 652 mutex_enter(&rmixl_intr_lock); 653 ih = rmixl_vec_establish(RMIXL_INTRVEC_FMN, -1, RMIXL_FMN_INTR_IPL, 654 rmixl_fmn_intr_dispatch, fmnp, "fmn"); 655 if (ih == NULL) 656 panic("%s: rmixl_vec_establish failed", __func__); 657 mutex_exit(&rmixl_intr_lock); 658 fmnp->fmn_ih = ih; 659#endif 660 661 mutex_exit(fmnp->fmn_lock); 662} 663 664void * 665rmixl_fmn_intr_establish(int txstid, int (*func)(void *, rmixl_fmn_rxmsg_t *), void *arg) 666{ 667 fmn_t *fmnp; 668 fmn_intrhand_t *ih; 669 670 fmnp = fmn_lookup(curcpu()->ci_cpuid); 671 672 mutex_enter(fmnp->fmn_lock); 673 674 ih = &fmnp->fmn_intrhand[txstid]; 675 676 if (ih->ih_func != NULL) { 677#ifdef DEBUG 678 panic("%s: intrhand[%d] busy", __func__, txstid); 679#endif 680 ih = NULL; 681 } else { 682 ih->ih_func = func; 683 ih->ih_arg = arg; 684 } 685 686 mutex_exit(fmnp->fmn_lock); 687 688 return ih; 689} 690 691void 692rmixl_fmn_intr_disestablish(void *cookie) 693{ 694 fmn_t *fmnp; 695 fmn_intrhand_t *ih = cookie; 696 697 fmnp = fmn_lookup(curcpu()->ci_cpuid); 698 mutex_enter(fmnp->fmn_lock); 699 700 if (ih->ih_func != NULL) { 701 ih->ih_func = NULL; 702 ih->ih_arg = NULL; 703 } 704#ifdef DEBUG 705 else { 706 panic("%s: intrhand[%ld] not in use", 707 __func__, ih - &fmnp->fmn_intrhand[0]); 708 } 709#endif 710 711 mutex_exit(fmnp->fmn_lock); 712} 713 714void 715rmixl_fmn_intr_poll(u_int bucket, rmixl_fmn_rxmsg_t *rxmsg) 716{ 717 uint32_t bit = 1 << bucket; 718 uint32_t cp0_status; 719 720 KASSERT(bucket < 8); 721 722 cp0_status = rmixl_cp2_enable(); 723 724 for(;;) { 725 rmixl_fmn_msgwait(bit); 726 if (rmixl_fmn_msg_recv(bucket, rxmsg) == 0) 727 break; 728 DELAY(10); /* XXX */ 729 } 730 731 rmixl_cp2_restore(cp0_status); 732} 733 734#ifdef NOTYET 735static int 736rmixl_fmn_intr_dispatch(void *arg) 737{ 738 fmn_t *fmnp = arg; 739 uint32_t msg_status; 740 uint32_t cp0_status; 741 uint32_t rfbne; 742 int txstid; 743 int rv = 0; 744 745 mutex_enter(fmnp->fmn_lock); 746 cp0_status = rmixl_cp2_enable(); 747 748 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 0, msg_status); 749 rfbne = (~msg_status) >> RMIXL_MSG_STS0_RFBE_SHIFT; 750 751 if (rfbne != 0) { 752 DPRINTF(("%s: rfbne %#x\n", __func__, rfbne)); 753 for (u_int bucket=0; bucket < 8; bucket++) { 754 rmixl_fmn_rxmsg_t rxmsg; 755 fmn_intrhand_t *ih; 756 757 if ((rfbne & (1 << bucket)) == 0) 758 continue; 759 if (rmixl_fmn_msg_recv_subr(bucket, &rxmsg) != 0) 760 continue; 761 rv = 1; 762 txstid = fmnp->fmn_stidtab[rxmsg.rxsid]; 763 ih = &fmnp->fmn_intrhand[txstid]; 764 if (ih->ih_func != NULL) 765 if ((ih->ih_func)(ih->ih_arg, &rxmsg) != 0) 766 ih->ih_count.ev_count++; 767 } 768 769 } 770 rmixl_cp2_restore(cp0_status); 771 mutex_exit(fmnp->fmn_lock); 772 773 return rv; 774} 775#endif /* NOTYET */ 776 777int 778rmixl_fmn_msg_send(u_int size, u_int code, u_int dest_id, rmixl_fmn_msg_t *msg) 779{ 780 fmn_t *fmnp; 781 uint32_t cp0_status; 782 uint32_t msg_status; 783 uint32_t msg_status1; 784 uint32_t desc; 785 int rv = 0; 786 787 KASSERT((size >= 1) && size <= 4); 788 KASSERT(code <= 0xff); 789 KASSERT(dest_id <= 0xff); 790 791 fmnp = fmn_lookup(curcpu()->ci_cpuid); 792 mutex_enter(fmnp->fmn_lock); 793 cp0_status = rmixl_cp2_enable(); 794 795 switch(size) { 796 case 1: 797 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 0, msg->data[0]); 798 break; 799 case 2: 800 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 0, msg->data[0]); 801 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 1, msg->data[1]); 802 break; 803 case 3: 804 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 0, msg->data[0]); 805 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 1, msg->data[1]); 806 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 2, msg->data[2]); 807 break; 808 case 4: 809 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 0, msg->data[0]); 810 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 1, msg->data[1]); 811 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 2, msg->data[2]); 812 RMIXL_DMTC2(RMIXL_COP_2_TXBUF, 3, msg->data[3]); 813 break; 814 default: 815 DIAG_PRF(("%s: bad size %d", __func__, size)); 816 rv = -1; 817 goto out; 818 } 819 820 for (int try=16; try--; ) { 821 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 0, msg_status); 822 if ((msg_status & (RMIXL_MSG_STS0_LPF|RMIXL_MSG_STS0_SPF|RMIXL_MSG_STS0_SMP)) == 0) 823 goto send; 824 DELAY(10); /* XXX ??? */ 825 } 826 DIAG_PRF(("%s: cpu%u, msg %p, dst_id=%d, sts=%#x: can't send\n", 827 __func__, cpu_number(), msg, dest_id, msg_status)); 828 rv = -1; 829 goto out; 830 send: 831 desc = RMIXL_MSGSND_DESC(size, code, dest_id); 832 DPRINTF(("%s: cpu%u, desc %#x\n", __func__, cpu_number(), desc)); 833 for (int try=16; try--; ) { 834 rmixl_msgsnd(desc); 835 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 0, msg_status); 836 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 1, msg_status1); 837 if (((msg_status & RMIXL_MSG_STS0_SCF) == 0) 838 && ((msg_status1 & RMIXL_MSG_STS1_ERRS) == 0)) 839 goto out; 840#if 0 841#ifdef DEBUG 842 if ((msg_status & RMIXL_MSG_STS0_SCF) != 0) { 843 uint32_t r; 844 u_int regno = RMIXL_COP_2_CREDITS+fmnp->fmn_core; 845 u_int sel = fmnp->fmn_thread; 846 printf("%s: CC[%d,%d]=", __func__, regno, sel); 847 FMN_CP2_RD_SWITCH_RW(READ, regno, sel, r); 848 printf("%s: CC[%d,%d]=%d\n", __func__, regno, sel, r); 849 } 850#endif /* DEBUG */ 851#endif /* 0 */ 852 /* clear status1 error(s) */ 853 if ((msg_status1 & RMIXL_MSG_STS1_ERRS) != 0) { 854 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 1, msg_status1); 855 RMIXL_MTC2(RMIXL_COP_2_MSG_STS, 1, msg_status1); 856 } 857 DIAG_PRF(("%s: src=%ld, dst=%d, sts=%#x, %#x: send error, try %d\n", 858 __func__, curcpu()->ci_cpuid, dest_id, msg_status, msg_status1, try)); 859 DELAY(10); 860 } 861 rv = -1; 862 out: 863 rmixl_cp2_restore(cp0_status); 864 mutex_exit(fmnp->fmn_lock); 865 866 return rv; 867} 868 869/* 870 * rmixl_fmn_msg_recv 871 * 872 * - grab fmn_lock and call rmixl_fmn_msg_recv_subr to do the real work 873 * - assume cp2 access is already enabled 874 */ 875int 876rmixl_fmn_msg_recv(u_int bucket, rmixl_fmn_rxmsg_t *rxmsg) 877{ 878 fmn_t *fmnp; 879 int rv; 880 881 fmnp = fmn_lookup(curcpu()->ci_cpuid); 882 mutex_enter(fmnp->fmn_lock); 883 rv = rmixl_fmn_msg_recv_subr(bucket, rxmsg); 884 mutex_exit(fmnp->fmn_lock); 885 886 return rv; 887} 888 889/* 890 * rmixl_fmn_msg_recv_subr 891 * 892 * - assume fmn_lock is owned 893 * - assume cp2 access is already enabled 894 */ 895static int 896rmixl_fmn_msg_recv_subr(u_int bucket, rmixl_fmn_rxmsg_t *rxmsg) 897{ 898 fmn_t *fmnp; 899 uint32_t msg_status = 0 /* XXXGCC12 */; 900 int rv; 901 902 fmnp = fmn_lookup(curcpu()->ci_cpuid); 903 KASSERT(mutex_owned(fmnp->fmn_lock) != 0); 904 905 for (int try=16; try--; ) { 906 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 0, msg_status); 907 if ((msg_status & (RMIXL_MSG_STS0_LPF)) == 0) 908 goto recv; 909 } 910 DIAG_PRF(("%s: cpu%u, bucket=%d, sts=%#x: Load Pending Fail\n", 911 __func__, cpu_number(), bucket, msg_status)); 912 rv = -1; 913 goto out; 914 recv: 915 rmixl_msgld(bucket); 916 RMIXL_MFC2(RMIXL_COP_2_MSG_STS, 0, msg_status); 917 DPRINTF(("%s: cpu%u, bucket=%d, sts=%#x\n", 918 __func__, cpu_number(), bucket, msg_status)); 919 rv = msg_status & (RMIXL_MSG_STS0_LEF|RMIXL_MSG_STS0_LPF); 920 if (rv == 0) { 921 rxmsg->rxsid = (msg_status & RMIXL_MSG_STS0_RMSID) 922 >> RMIXL_MSG_STS0_RMSID_SHIFT; 923 rxmsg->code = (msg_status & RMIXL_MSG_STS0_RMSC) 924 >> RMIXL_MSG_STS0_RMSC_SHIFT; 925 rxmsg->size = ((msg_status & RMIXL_MSG_STS0_RMS) 926 >> RMIXL_MSG_STS0_RMS_SHIFT) + 1; 927 switch(rxmsg->size) { 928 case 1: 929 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 0, rxmsg->msg.data[0]); 930 break; 931 case 2: 932 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 0, rxmsg->msg.data[0]); 933 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 1, rxmsg->msg.data[1]); 934 break; 935 case 3: 936 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 0, rxmsg->msg.data[0]); 937 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 1, rxmsg->msg.data[1]); 938 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 2, rxmsg->msg.data[2]); 939 break; 940 case 4: 941 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 0, rxmsg->msg.data[0]); 942 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 1, rxmsg->msg.data[1]); 943 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 2, rxmsg->msg.data[2]); 944 RMIXL_DMFC2(RMIXL_COP_2_RXBUF, 3, rxmsg->msg.data[3]); 945 break; 946 default: 947 /* "impossible" due to bitfield width */ 948 panic("%s: bad size %d", __func__, rxmsg->size); 949 } 950 } 951 out: 952 953 return rv; 954} 955 956#ifdef FMN_DEBUG 957void 958rmixl_fmn_cp2_dump(void) 959{ 960 uint32_t cp0_status; 961 962 cp0_status = rmixl_cp2_enable(); 963 964 CPU2_PRINT_8(RMIXL_COP_2_TXBUF, 0); 965 CPU2_PRINT_8(RMIXL_COP_2_TXBUF, 1); 966 CPU2_PRINT_8(RMIXL_COP_2_TXBUF, 2); 967 CPU2_PRINT_8(RMIXL_COP_2_TXBUF, 3); 968 969 CPU2_PRINT_8(RMIXL_COP_2_RXBUF, 0); 970 CPU2_PRINT_8(RMIXL_COP_2_RXBUF, 1); 971 CPU2_PRINT_8(RMIXL_COP_2_RXBUF, 2); 972 CPU2_PRINT_8(RMIXL_COP_2_RXBUF, 3); 973 974 CPU2_PRINT_4(RMIXL_COP_2_MSG_STS, 0); 975 CPU2_PRINT_4(RMIXL_COP_2_MSG_STS, 1); 976 977 CPU2_PRINT_4(RMIXL_COP_2_MSG_CFG, 0); 978 CPU2_PRINT_4(RMIXL_COP_2_MSG_CFG, 1); 979 980 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 0); 981 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 1); 982 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 2); 983 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 3); 984 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 4); 985 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 5); 986 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 6); 987 CPU2_PRINT_4(RMIXL_COP_2_MSG_BSZ, 7); 988 989 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 0); 990 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 1); 991 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 2); 992 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 3); 993 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 4); 994 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 5); 995 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 6); 996 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 0, 7); 997 998 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 0); 999 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 1); 1000 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 2); 1001 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 3); 1002 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 4); 1003 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 5); 1004 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 6); 1005 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 1, 7); 1006 1007 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 0); 1008 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 1); 1009 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 2); 1010 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 3); 1011 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 4); 1012 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 5); 1013 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 6); 1014 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 2, 7); 1015 1016 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 0); 1017 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 1); 1018 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 2); 1019 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 3); 1020 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 4); 1021 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 5); 1022 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 6); 1023 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 3, 7); 1024 1025 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 0); 1026 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 1); 1027 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 2); 1028 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 3); 1029 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 4); 1030 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 5); 1031 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 6); 1032 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 4, 7); 1033 1034 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 0); 1035 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 1); 1036 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 2); 1037 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 3); 1038 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 4); 1039 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 5); 1040 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 6); 1041 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 5, 7); 1042 1043 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 0); 1044 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 1); 1045 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 2); 1046 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 3); 1047 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 4); 1048 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 5); 1049 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 6); 1050 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 6, 7); 1051 1052 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 0); 1053 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 1); 1054 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 2); 1055 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 3); 1056 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 4); 1057 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 5); 1058 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 6); 1059 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 7, 7); 1060 1061 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 0); 1062 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 1); 1063 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 2); 1064 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 3); 1065 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 4); 1066 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 5); 1067 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 6); 1068 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 8, 7); 1069 1070 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 0); 1071 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 1); 1072 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 2); 1073 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 3); 1074 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 4); 1075 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 5); 1076 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 6); 1077 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 9, 7); 1078 1079 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 0); 1080 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 1); 1081 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 2); 1082 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 3); 1083 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 4); 1084 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 5); 1085 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 6); 1086 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 10, 7); 1087 1088 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 0); 1089 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 1); 1090 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 2); 1091 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 3); 1092 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 4); 1093 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 5); 1094 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 6); 1095 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 11, 7); 1096 1097 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 0); 1098 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 1); 1099 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 2); 1100 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 3); 1101 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 4); 1102 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 5); 1103 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 6); 1104 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 12, 7); 1105 1106 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 0); 1107 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 1); 1108 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 2); 1109 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 3); 1110 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 4); 1111 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 5); 1112 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 6); 1113 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 13, 7); 1114 1115 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 0); 1116 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 1); 1117 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 2); 1118 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 3); 1119 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 4); 1120 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 5); 1121 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 6); 1122 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 14, 7); 1123 1124 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 0); 1125 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 1); 1126 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 2); 1127 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 3); 1128 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 4); 1129 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 5); 1130 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 6); 1131 CPU2_PRINT_4(RMIXL_COP_2_CREDITS + 15, 7); 1132 1133 rmixl_cp2_restore(cp0_status); 1134} 1135 1136 1137void 1138rmixl_fmn_cc_dump(void) 1139{ 1140 uint32_t cc[4][8]; 1141 1142 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS, 0, &cc[0][0]); 1143 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS, 4, &cc[0][4]); 1144 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS+1, 0, &cc[1][0]); 1145 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS+1, 4, &cc[1][4]); 1146 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS+2, 0, &cc[2][0]); 1147 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS+2, 4, &cc[2][4]); 1148 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS+3, 0, &cc[3][0]); 1149 FMN_CP2_4SEL_READ(RMIXL_COP_2_CREDITS+3, 4, &cc[3][4]); 1150 1151 printf("%s: cpu%u\n", __func__, cpu_number()); 1152 for (int i=0; i < 4; i++) { 1153 for (int j=0; j < 8; j++) 1154 printf(" %#x,", cc[i][j]); 1155 printf("\n"); 1156 } 1157} 1158 1159#endif /* FMN_DEBUG */ 1160