1 /* 2 * Copyright (c) 2026 Justin Hibbits 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <sys/param.h> 8 #include <sys/bus.h> 9 #include <sys/kernel.h> 10 #include <sys/module.h> 11 #include <dev/ofw/ofw_bus_subr.h> 12 #include <machine/bus.h> 13 #include "fman.h" 14 #include "fman_parser.h" 15 #include "fman_port.h" 16 #include "fman_if.h" 17 #include "fman_port_if.h" 18 19 struct fman_port_rsrc { 20 uint32_t num; 21 uint32_t extra; 22 }; 23 24 #define MAX_BM_POOLS 64 25 struct fman_port_softc { 26 device_t sc_dev; 27 struct resource *sc_mem; 28 int sc_port_id; 29 int sc_port_speed; 30 int sc_port_type; 31 32 int sc_revision_major; 33 int sc_revision_minor; 34 35 int sc_max_frame_length; 36 int sc_bm_max_pools; 37 int sc_max_port_fifo_size; 38 int sc_qman_channel_id; 39 40 int sc_deq_byte_count; 41 int sc_deq_high_priority; 42 int sc_tx_deq_pipeline_depth; 43 44 int sc_default_fqid; 45 int sc_err_fqid; 46 int pcd_base_fqid; 47 int pcd_fqs_count; 48 49 int sc_max_ext_portals; 50 int sc_max_sub_portals; 51 52 struct fman_port_rsrc sc_open_dmas; 53 struct fman_port_rsrc sc_tasks; 54 struct fman_port_rsrc sc_fifo_bufs; 55 56 struct fman_port_buffer_pool sc_bpools[FMAN_PORT_MAX_POOLS]; 57 }; 58 59 #define TX_10G_PORT_BASE 0x30 60 #define RX_10G_PORT_BASE 0x10 61 62 #define FMAN_PORT_TYPE_TX 0 63 #define FMAN_PORT_TYPE_RX 1 64 65 #define PORT_RX 0x01 66 #define PORT_TX 0x02 67 #define PORT_V3 0x04 68 69 #define FMBM_RCFG 0x000 70 #define BMI_PORT_CFG_EN 0x80000000 71 #define FMBM_RST 0x004 72 #define FMBM_RDA 0x008 73 #define RDA_WOPT 0x00100000 74 #define FMBM_RFP 0x00c 75 #define FMBM_RFED 0x010 76 #define BMI_RX_FRAME_END_CUT_SHIFT 16 77 #define FMBM_RICP 0x014 /* Counts are units of 16 bytes */ 78 #define RICP_ICEOF_M 0x001f0000 79 #define RICP_ICEOF_S 16 80 #define RICP_ICIOF_M 0x00000f00 81 #define RICP_ICIOF_S 8 82 #define RICP_ICSZ_S 0x0000001f 83 #define FMBM_RIM 0x018 84 #define FMBM_REBM 0x01c 85 #define REBM_BSM_M 0x01ff0000 86 #define REBM_BSM_S 16 87 #define REBM_BEM_M 0x000001ff 88 #define FMBM_RFNE 0x020 89 #define FMBM_RFCA 0x024 90 #define RFCA_OR 0x80000000 91 #define RFCA_COLOR 0x0c000000 92 #define RFCA_SYNC 0x03000000 93 #define RFCA_SYNC_REQ 0x02000000 94 #define RFCA_MR 0x003f0000 95 #define RFCA_MR_DEF 0x003c0000 96 #define FMBM_RFPNE 0x028 97 #define FMBM_RETH 0x038 98 #define RETH_ETHE 0x80000000 /* Excessive Threshold Enable */ 99 #define FMBM_RFQID 0x060 100 #define FMBM_REFQID 0x064 101 #define FMBM_RFSDM 0x068 102 #define FMBM_RFSEM 0x06c 103 #define FMBM_RFENE 0x070 104 #define FMBM_REBMPI(i) (0x100 + (4 * (i))) 105 #define REBMPI_VAL 0x80000000 106 #define REBMPI_ACE 0x40000000 107 #define REBMPI_BPID_S 16 108 #define FMBM_RSTC 0x0200 109 #define RSTC_EN 0x80000000 110 111 #define FMBM_TCFG 0x000 112 #define FMBM_TST 0x004 113 #define FMBM_TDA 0x008 114 #define FMBM_TFP 0x00c 115 #define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12 116 #define FMBM_TFED 0x010 117 #define FMBM_TICP 0x014 118 #define TICP_ICEOF_M 0x001f0000 119 #define TICP_ICEOF_S 16 120 #define TICP_ICIOF_M 0x00000f00 121 #define TICP_ICIOF_S 8 122 #define TICP_ICSZ_S 0x0000001f 123 #define FMBM_TFDNE 0x018 124 #define FMBM_TFCA 0x01c 125 #define TFCA_MR_DEF 0 126 #define TFCA_ATTR_ORDER 0x80000000 127 #define FMBM_TCFQID 0x020 128 #define FMBM_TEFQID 0x024 129 #define FMBM_TFENE 0x028 130 #define FMBM_TFNE 0x070 131 #define TFNE_EBD 0x80000000 132 133 #define FMQM_PNC 0x400 134 #define PNC_EN 0x80000000 135 #define PNC_STEN 0x80000000 136 #define FMQM_PNS 0x404 137 #define PNS_DEQ_FD_BSY 0x20000000 138 #define FMQM_PNEN 0x41c 139 #define FMQM_PNDN 0x42c 140 #define FMQM_PNDC 0x430 141 #define QMI_DEQ_CFG_PRI 0x80000000 142 #define QMI_DEQ_CFG_TYPE1 0x10000000 143 #define QMI_DEQ_CFG_TYPE2 0x20000000 144 #define QMI_DEQ_CFG_TYPE3 0x30000000 145 #define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000 146 #define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000 147 #define QMI_DEQ_CFG_SP_MASK 0xf 148 #define QMI_DEQ_CFG_SP_SHIFT 20 149 150 #define HWP_PCAC 0xbf8 151 #define HWP_PCAC_PSTOP 0x00000001 152 #define HWP_HXS_PCAC_PSTAT 0x00000100 153 #define HWP_HXS_SSA(x) (0x800 + x * 2 * sizeof(uint32_t)) 154 #define HWP_HXS_LCV(x) (0x800 + (x * 2 + 1) * sizeof(uint32_t)) 155 #define HWP_HXS_TCP 0xA 156 #define HWP_HXS_UDP 0xB 157 #define HXS_SH_PAD_REM 0x80000000 158 #define HWP_HXS_COUNT 16 159 160 #define PORT_MAX_FRAME_LENGTH 9600 161 162 #define NIA_ORDER_RESTORE 0x00800000 163 #define NIA_ENG_BMI 0x00500000 164 #define NIA_ENG_QMI_DEQ 0x00580000 165 #define NIA_ENG_QMI_ENQ 0x00540000 166 #define NIA_ENG_HWP 0x00440000 167 #define NIA_ENG_HWK 0x00480000 168 #define NIA_BMI_AC_TX_RELEASE 0x000002c0 169 #define NIA_BMI_AC_TX 0x00000274 170 #define NIA_BMI_AC_RELEASE 0x000000c0 171 #define NIA_BMI_AC_ENQ_FRAME 0x00000002 172 #define NIA_BMI_AC_FETCH_ALLFRAME 0x0000020c 173 174 #define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \ 175 FM_FD_ERR_FSE | FM_FD_ERR_DIS | \ 176 FM_FD_ERR_EOF | FM_FD_ERR_NSS | \ 177 FM_FD_ERR_KSO | FM_FD_ERR_IPP | \ 178 FM_FD_ERR_PTE | FM_FD_ERR_PHE | \ 179 FM_FD_ERR_BLE) 180 181 /* Default configurations */ 182 #define DEFAULT_RX_CUT_END_BYTES 4 183 184 static struct ofw_compat_data compats[] = { 185 { "fsl,fman-v2-port-rx", PORT_RX }, 186 { "fsl,fman-v2-port-tx", PORT_TX }, 187 { "fsl,fman-v3-port-rx", PORT_V3 | PORT_RX }, 188 { "fsl,fman-v3-port-tx", PORT_V3 | PORT_TX }, 189 { NULL, 0 } 190 }; 191 192 static int 193 fman_port_probe(device_t dev) 194 { 195 if (ofw_bus_search_compatible(dev, compats)->ocd_str == NULL) 196 return (ENXIO); 197 198 device_set_desc(dev, "FMan port"); 199 200 return (BUS_PROBE_DEFAULT); 201 } 202 203 static int 204 fman_port_attach(device_t dev) 205 { 206 struct fman_port_softc *sc; 207 phandle_t node; 208 pcell_t cell; 209 uintptr_t compat_data = 210 ofw_bus_search_compatible(dev, compats)->ocd_data; 211 int port_speed = 1000; 212 int port_type; 213 214 sc = device_get_softc(dev); 215 sc->sc_dev = dev; 216 217 node = ofw_bus_get_node(dev); 218 if (OF_getencprop(node, "cell-index", &cell, sizeof(cell)) < 0) { 219 device_printf(dev, "No cell-index property"); 220 return (ENXIO); 221 } 222 223 sc->sc_port_id = cell; 224 225 sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, 226 RF_ACTIVE | RF_SHAREABLE); 227 228 if (sc->sc_mem == NULL) { 229 device_printf(dev, "failed to allocate MMIO"); 230 return (ENXIO); 231 } 232 233 FMAN_GET_REVISION(device_get_parent(dev), 234 &sc->sc_revision_major, &sc->sc_revision_minor); 235 236 if ((compat_data & PORT_TX) == PORT_TX) 237 port_type = FMAN_PORT_TYPE_TX; 238 else 239 port_type = FMAN_PORT_TYPE_RX; 240 241 if ((compat_data & PORT_V3) == PORT_V3) { 242 if (OF_hasprop(node, "fsl,fman-10g-port")) 243 port_speed = 10000; 244 } else { 245 if ((compat_data & PORT_TX) && 246 sc->sc_port_id > TX_10G_PORT_BASE) 247 port_speed = 10000; 248 else if ((compat_data & PORT_RX) && 249 sc->sc_port_id > RX_10G_PORT_BASE) 250 port_speed = 10000; 251 } 252 253 if (sc->sc_port_speed == 10000) { 254 sc->sc_deq_high_priority = true; 255 sc->sc_deq_byte_count = 0x1400; 256 } else { 257 sc->sc_deq_high_priority = false; 258 sc->sc_deq_byte_count = 0x0400; 259 } 260 261 sc->sc_port_type = port_type; 262 sc->sc_port_speed = port_speed; 263 264 sc->sc_bm_max_pools = MAX_BM_POOLS; 265 sc->sc_max_frame_length = PORT_MAX_FRAME_LENGTH; 266 267 if (port_type == FMAN_PORT_TYPE_TX) 268 sc->sc_qman_channel_id = 269 FMAN_GET_QMAN_CHANNEL_ID(device_get_parent(dev), 270 sc->sc_port_id); 271 272 OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev); 273 274 return (0); 275 } 276 277 static int 278 fman_port_detach(device_t dev) 279 { 280 struct fman_port_softc *sc = device_get_softc(dev); 281 282 if (sc->sc_mem != NULL) 283 bus_release_resource(dev, sc->sc_mem); 284 285 return (0); 286 } 287 288 static int 289 fman_port_config(device_t dev, struct fman_port_params *params) 290 { 291 struct fman_port_softc *sc = device_get_softc(dev); 292 293 sc->sc_default_fqid = params->dflt_fqid; 294 sc->sc_err_fqid = params->err_fqid; 295 296 sc->sc_max_port_fifo_size = 297 FMAN_GET_BMI_MAX_FIFO_SIZE(device_get_parent(dev)); 298 switch (sc->sc_revision_major) { 299 case 2: 300 case 3: 301 sc->sc_max_ext_portals = 4; 302 sc->sc_max_sub_portals = 12; 303 break; 304 case 6: 305 sc->sc_max_ext_portals = 8; 306 sc->sc_max_sub_portals = 16; 307 break; 308 } 309 if (sc->sc_revision_major >= 6 && 310 sc->sc_port_type == FMAN_PORT_TYPE_TX && sc->sc_port_speed == 1000) 311 /* Errata A005127 workaround */ 312 bus_write_4(sc->sc_mem, FMBM_TFP, 0x00001013); 313 314 sc->sc_tasks.extra = 0; 315 316 switch (sc->sc_port_speed) { 317 case 10000: 318 if (sc->sc_revision_major < 6) { 319 sc->sc_tasks.num = 16; 320 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) 321 sc->sc_tasks.extra = 8; 322 } else 323 sc->sc_tasks.num = 14; 324 break; 325 case 1000: 326 if (sc->sc_revision_major >= 6) 327 sc->sc_tasks.num = 4; 328 else { 329 sc->sc_tasks.num = 3; 330 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) 331 sc->sc_tasks.extra = 2; 332 } 333 break; 334 default: 335 sc->sc_tasks.num = 0; 336 break; 337 } 338 339 /* Open DMAs */ 340 if (sc->sc_revision_major >= 6) { 341 sc->sc_open_dmas.extra = 0; 342 if (sc->sc_port_speed == 10000) { 343 if (sc->sc_port_type == FMAN_PORT_TYPE_TX) 344 sc->sc_open_dmas.num = 12; 345 else 346 sc->sc_open_dmas.num = 8; 347 } else { 348 if (sc->sc_port_type == FMAN_PORT_TYPE_TX) 349 sc->sc_open_dmas.num = 3; 350 else 351 sc->sc_open_dmas.num = 2; 352 } 353 } else { 354 if (sc->sc_port_speed == 10000) { 355 sc->sc_open_dmas.num = 8; 356 sc->sc_open_dmas.num = 8; 357 } else { 358 sc->sc_open_dmas.num = 1; 359 sc->sc_open_dmas.extra = 1; 360 } 361 } 362 363 /* FIFO bufs */ 364 if (sc->sc_revision_major >= 6) { 365 if (sc->sc_port_type == FMAN_PORT_TYPE_TX) 366 if (sc->sc_port_speed == 10000) 367 sc->sc_fifo_bufs.num = 64; 368 else 369 sc->sc_fifo_bufs.num = 50; 370 else 371 if (sc->sc_port_speed == 10000) 372 sc->sc_fifo_bufs.num = 96; 373 else 374 sc->sc_fifo_bufs.num = 50; 375 } else { 376 if (sc->sc_port_type == FMAN_PORT_TYPE_TX) 377 if (sc->sc_port_speed == 10000) 378 sc->sc_fifo_bufs.num = 48; 379 else 380 sc->sc_fifo_bufs.num = 44; 381 else 382 if (sc->sc_port_speed == 10000) 383 sc->sc_fifo_bufs.num = 48; 384 else 385 sc->sc_fifo_bufs.num = 45; 386 } 387 388 sc->sc_fifo_bufs.extra = 0; 389 sc->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS; 390 391 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) 392 for (int i = 0; i < params->rx_params.num_pools; i++) 393 sc->sc_bpools[i] = params->rx_params.bpools[i]; 394 395 /* TODO: buf_margins? See fman_sp_build_buffer_struct */ 396 397 return (0); 398 } 399 400 static int 401 fman_port_init_bmi_rx(struct fman_port_softc *sc) 402 { 403 uint32_t reg; 404 405 /* TODO: Sort the buffer pool list. */ 406 /* TODO: Backup pools */ 407 /* TODO: Depletion mode */ 408 for (int i = 0; i < FMAN_PORT_MAX_POOLS; i++) { 409 /* Initialize the external pool info */ 410 if (sc->sc_bpools[i].size != 0) { 411 bus_write_4(sc->sc_mem, FMBM_REBMPI(i), 412 REBMPI_VAL | REBMPI_ACE | 413 (sc->sc_bpools[i].bpid << REBMPI_BPID_S) | 414 sc->sc_bpools[i].size); 415 } else 416 /* Mark invalid if zero */ 417 bus_write_4(sc->sc_mem, FMBM_REBMPI(i), 0); 418 } 419 420 bus_write_4(sc->sc_mem, FMBM_RDA, RDA_WOPT); 421 422 bus_write_4(sc->sc_mem, FMBM_RFCA, 423 RFCA_OR | RFCA_SYNC_REQ | RFCA_MR_DEF); 424 425 bus_write_4(sc->sc_mem, FMBM_RFPNE, 426 NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME); 427 bus_write_4(sc->sc_mem, FMBM_RFENE, 428 NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE); 429 430 bus_write_4(sc->sc_mem, FMBM_RFQID, sc->sc_default_fqid); 431 bus_write_4(sc->sc_mem, FMBM_REFQID, sc->sc_err_fqid); 432 433 if (sc->sc_revision_major < 6) 434 bus_write_4(sc->sc_mem, FMBM_RETH, RETH_ETHE); 435 436 /* Errata A006320 makes CFED field bad */ 437 if (sc->sc_revision_major == 6 && (sc->sc_revision_minor == 0)) 438 /* These are under errata A006320 */; 439 else 440 bus_write_4(sc->sc_mem, FMBM_RFED, 441 DEFAULT_RX_CUT_END_BYTES << BMI_RX_FRAME_END_CUT_SHIFT); 442 443 /* Insert internal context ahead of the frame */ 444 reg = sizeof(struct fman_internal_context) << REBM_BSM_S; 445 bus_write_4(sc->sc_mem, FMBM_REBM, reg); 446 reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << RICP_ICIOF_S; 447 reg |= howmany(sizeof(struct fman_internal_context), 0x10); 448 bus_write_4(sc->sc_mem, FMBM_RICP, reg); 449 450 bus_write_4(sc->sc_mem, FMBM_RFNE, NIA_ENG_HWP); 451 bus_write_4(sc->sc_mem, FMBM_RFSDM, FM_FD_ERR_DIS); 452 bus_write_4(sc->sc_mem, FMBM_RFSEM, BMI_RX_ERR & ~FM_FD_ERR_DIS); 453 454 return (0); 455 } 456 457 static int 458 fman_port_init_bmi_tx(struct fman_port_softc *sc) 459 { 460 uint32_t reg; 461 int depth; 462 463 bus_write_4(sc->sc_mem, FMBM_TCFG, 0); 464 bus_write_4(sc->sc_mem, FMBM_TDA, 0); 465 bus_write_4(sc->sc_mem, FMBM_TFED, 0); 466 if (sc->sc_port_speed == 10000) 467 depth = 4; 468 else if (sc->sc_revision_major >= 6) 469 depth = 2; 470 else 471 depth = 1; 472 sc->sc_tx_deq_pipeline_depth = depth; 473 reg = ((depth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT) | 0x13; 474 bus_write_4(sc->sc_mem, FMBM_TFP, reg); 475 476 /* Default color: green */ 477 bus_write_4(sc->sc_mem, FMBM_TFCA, 478 TFCA_MR_DEF | TFCA_ATTR_ORDER); 479 480 bus_write_4(sc->sc_mem, FMBM_TFDNE, NIA_ENG_QMI_DEQ); 481 bus_write_4(sc->sc_mem, FMBM_TFENE, 482 NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE); 483 484 /* Insert internal context ahead of the frame */ 485 reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << TICP_ICIOF_S; 486 reg |= howmany(sizeof(struct fman_internal_context), 0x10); 487 bus_write_4(sc->sc_mem, FMBM_TICP, reg); 488 489 if (sc->sc_revision_major >= 6) 490 bus_write_4(sc->sc_mem, FMBM_TFNE, 491 (sc->sc_default_fqid == 0 ? TFNE_EBD : 0) | 492 NIA_BMI_AC_FETCH_ALLFRAME); 493 bus_write_4(sc->sc_mem, FMBM_TCFQID, sc->sc_default_fqid); 494 bus_write_4(sc->sc_mem, FMBM_TEFQID, sc->sc_err_fqid); 495 496 return (0); 497 } 498 499 static int 500 fman_port_init_hwp(struct fman_port_softc *sc) 501 { 502 int i; 503 504 /* Stop the parser so we can initialize it for our uses */ 505 bus_write_4(sc->sc_mem, HWP_PCAC, HWP_PCAC_PSTOP); 506 507 for (i = 0; i < 100 && 508 (bus_read_4(sc->sc_mem, HWP_PCAC) & HWP_HXS_PCAC_PSTAT) != 0; i++) { 509 DELAY(10); 510 } 511 if (i == 100) { 512 device_printf(sc->sc_dev, "Timeout stopping HW parser\n"); 513 return (ENXIO); 514 } 515 516 /* set the parser examination config */ 517 for (i = 0; i < HWP_HXS_COUNT; i++) { 518 bus_write_4(sc->sc_mem, HWP_HXS_SSA(i), 0); 519 bus_write_4(sc->sc_mem, HWP_HXS_LCV(i), 0xffffffff); 520 } 521 bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_TCP), HXS_SH_PAD_REM); 522 bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_UDP), HXS_SH_PAD_REM); 523 524 /* Re-enable the parser */ 525 bus_write_4(sc->sc_mem, HWP_PCAC, 0); 526 527 return (0); 528 } 529 530 static int 531 fman_port_init_qmi(struct fman_port_softc *sc) 532 { 533 uint32_t reg; 534 535 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) { 536 bus_write_4(sc->sc_mem, FMQM_PNEN, 537 NIA_ENG_BMI | NIA_BMI_AC_RELEASE); 538 return (0); 539 } 540 541 /* TX port */ 542 bus_write_4(sc->sc_mem, FMQM_PNDN, 543 NIA_ENG_BMI | NIA_BMI_AC_TX); 544 /* TX port */ 545 bus_write_4(sc->sc_mem, FMQM_PNEN, 546 NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE); 547 548 reg = 0; 549 550 if (sc->sc_deq_high_priority) 551 reg |= QMI_DEQ_CFG_PRI; 552 553 reg |= QMI_DEQ_CFG_TYPE1; 554 reg |= QMI_DEQ_CFG_PREFETCH_FULL; 555 reg |= (sc->sc_qman_channel_id & QMI_DEQ_CFG_SP_MASK) << QMI_DEQ_CFG_SP_SHIFT; 556 reg |= sc->sc_deq_byte_count; 557 bus_write_4(sc->sc_mem, FMQM_PNDC, reg); 558 559 return (0); 560 } 561 562 static int 563 fman_port_init(device_t dev) 564 { 565 struct fman_port_init_params params; 566 struct fman_port_softc *sc = device_get_softc(dev); 567 int err; 568 569 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) { 570 /* Set up RX buffers and fifo */ 571 } 572 params.port_id = sc->sc_port_id; 573 params.is_rx_port = (sc->sc_port_type == FMAN_PORT_TYPE_RX); 574 params.num_tasks = sc->sc_tasks.num; 575 params.extra_tasks = sc->sc_tasks.extra; 576 params.open_dmas = sc->sc_open_dmas.num; 577 params.extra_dmas = sc->sc_open_dmas.extra; 578 params.fifo_size = sc->sc_fifo_bufs.num; 579 params.extra_fifo_size = sc->sc_fifo_bufs.extra; 580 params.max_frame_length = sc->sc_max_frame_length; 581 params.deq_pipeline_size = sc->sc_tx_deq_pipeline_depth; 582 583 /* TODO: verify_size_of_fifo() from Linux driver */ 584 err = FMAN_SET_PORT_PARAMS(device_get_parent(dev), ¶ms); 585 586 if (err != 0) 587 return (err); 588 589 if (sc->sc_port_type == FMAN_PORT_TYPE_TX) 590 err = fman_port_init_bmi_tx(sc); 591 else { 592 err = fman_port_init_bmi_rx(sc); 593 if (err == 0) 594 fman_port_init_hwp(sc); 595 } 596 597 if (err != 0) 598 return (err); 599 600 err = fman_port_init_qmi(sc); 601 602 /* TODO: keygen here */ 603 604 return (err); 605 } 606 607 static int 608 fman_port_disable(device_t dev) 609 { 610 struct fman_port_softc *sc; 611 uint32_t reg; 612 int count; 613 614 sc = device_get_softc(dev); 615 616 switch (sc->sc_port_type) { 617 case FMAN_PORT_TYPE_TX: 618 reg = bus_read_4(sc->sc_mem, FMQM_PNC); 619 bus_write_4(sc->sc_mem, FMQM_PNC, reg & ~PNC_EN); 620 for (count = 0; count < 100; count++) { 621 DELAY(10); 622 reg = bus_read_4(sc->sc_mem, FMQM_PNS); 623 if (!(reg & PNS_DEQ_FD_BSY)) 624 break; 625 } 626 if (count == 100) 627 device_printf(sc->sc_dev, "Timeout stopping QMI\n"); 628 reg = bus_read_4(sc->sc_mem, FMBM_TCFG); 629 bus_write_4(sc->sc_mem, FMBM_TCFG, reg & ~BMI_PORT_CFG_EN); 630 for (count = 0; count < 100; count++) { 631 DELAY(10); 632 reg = bus_read_4(sc->sc_mem, FMBM_TST); 633 if (!(reg & PNS_DEQ_FD_BSY)) 634 break; 635 } 636 if (count == 100) 637 device_printf(sc->sc_dev, "Timeout stopping BMI"); 638 break; 639 case FMAN_PORT_TYPE_RX: 640 reg = bus_read_4(sc->sc_mem, FMBM_RCFG); 641 bus_write_4(sc->sc_mem, FMBM_RCFG, reg & ~BMI_PORT_CFG_EN); 642 for (count = 0; count < 100; count++) { 643 DELAY(10); 644 reg = bus_read_4(sc->sc_mem, FMBM_RST); 645 if (!(reg & PNS_DEQ_FD_BSY)) 646 break; 647 } 648 if (count == 100) 649 device_printf(sc->sc_dev, "Timeout stopping BMI"); 650 break; 651 } 652 653 return (0); 654 } 655 656 static int 657 fman_port_enable(device_t dev) 658 { 659 struct fman_port_softc *sc; 660 uint32_t reg; 661 662 sc = device_get_softc(dev); 663 switch (sc->sc_port_type) { 664 case FMAN_PORT_TYPE_TX: 665 reg = bus_read_4(sc->sc_mem, FMQM_PNC); 666 bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN); 667 reg = bus_read_4(sc->sc_mem, FMBM_TCFG); 668 bus_write_4(sc->sc_mem, FMBM_TCFG, reg | BMI_PORT_CFG_EN); 669 break; 670 case FMAN_PORT_TYPE_RX: 671 reg = bus_read_4(sc->sc_mem, FMBM_RCFG); 672 bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN); 673 bus_write_4(sc->sc_mem, FMBM_RCFG, reg | BMI_PORT_CFG_EN); 674 bus_write_4(sc->sc_mem, FMBM_RSTC, RSTC_EN); 675 break; 676 } 677 678 return (0); 679 } 680 681 static device_method_t fman_port_methods[] = { 682 DEVMETHOD(device_probe, fman_port_probe), 683 DEVMETHOD(device_attach, fman_port_attach), 684 DEVMETHOD(device_detach, fman_port_detach), 685 686 DEVMETHOD(fman_port_config, fman_port_config), 687 DEVMETHOD(fman_port_init, fman_port_init), 688 DEVMETHOD(fman_port_enable, fman_port_enable), 689 DEVMETHOD(fman_port_disable, fman_port_disable), 690 691 DEVMETHOD_END 692 }; 693 694 DEFINE_CLASS_0(fman_port, fman_port_driver, fman_port_methods, 695 sizeof(struct fman_port_softc)); 696 EARLY_DRIVER_MODULE(fman_port, fman, fman_port_driver, 0, 0, 697 BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); 698