1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021 Alstom Group. 5 * Copyright (c) 2021 Semihalf. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/bus.h> 31 #include <sys/kernel.h> 32 #include <sys/module.h> 33 #include <sys/socket.h> 34 #include <sys/sockio.h> 35 #include <sys/sysctl.h> 36 #include <sys/rman.h> 37 38 #include <machine/bus.h> 39 #include <machine/resource.h> 40 41 #include <net/if.h> 42 #include <net/if_media.h> 43 #include <net/if_types.h> 44 45 #include <dev/enetc/enetc_mdio.h> 46 47 #include <dev/etherswitch/etherswitch.h> 48 #include <dev/mii/mii.h> 49 #include <dev/mii/miivar.h> 50 #include <dev/pci/pcireg.h> 51 #include <dev/pci/pcivar.h> 52 53 #include <dev/ofw/ofw_bus.h> 54 #include <dev/ofw/ofw_bus_subr.h> 55 56 #include <dev/etherswitch/felix/felix_var.h> 57 #include <dev/etherswitch/felix/felix_reg.h> 58 59 #include "etherswitch_if.h" 60 #include "miibus_if.h" 61 62 MALLOC_DECLARE(M_FELIX); 63 MALLOC_DEFINE(M_FELIX, "felix", "felix switch"); 64 65 static device_probe_t felix_probe; 66 static device_attach_t felix_attach; 67 static device_detach_t felix_detach; 68 69 static etherswitch_info_t* felix_getinfo(device_t); 70 static int felix_getconf(device_t, etherswitch_conf_t *); 71 static int felix_setconf(device_t, etherswitch_conf_t *); 72 static void felix_lock(device_t); 73 static void felix_unlock(device_t); 74 static int felix_getport(device_t, etherswitch_port_t *); 75 static int felix_setport(device_t, etherswitch_port_t *); 76 static int felix_readreg_wrapper(device_t, int); 77 static int felix_writereg_wrapper(device_t, int, int); 78 static int felix_readphy(device_t, int, int); 79 static int felix_writephy(device_t, int, int, int); 80 static int felix_setvgroup(device_t, etherswitch_vlangroup_t *); 81 static int felix_getvgroup(device_t, etherswitch_vlangroup_t *); 82 83 static int felix_parse_port_fdt(felix_softc_t, phandle_t, int *); 84 static int felix_setup(felix_softc_t); 85 static void felix_setup_port(felix_softc_t, int); 86 87 static void felix_tick(void *); 88 static int felix_ifmedia_upd(if_t); 89 static void felix_ifmedia_sts(if_t, struct ifmediareq *); 90 91 static void felix_get_port_cfg(felix_softc_t, etherswitch_port_t *); 92 static void felix_set_port_cfg(felix_softc_t, etherswitch_port_t *); 93 94 static bool felix_is_phyport(felix_softc_t, int); 95 static struct mii_data *felix_miiforport(felix_softc_t, unsigned int); 96 97 static struct felix_pci_id felix_pci_ids[] = { 98 {PCI_VENDOR_FREESCALE, FELIX_DEV_ID, FELIX_DEV_NAME}, 99 {0, 0, NULL} 100 }; 101 102 static device_method_t felix_methods[] = { 103 /* device interface */ 104 DEVMETHOD(device_probe, felix_probe), 105 DEVMETHOD(device_attach, felix_attach), 106 DEVMETHOD(device_detach, felix_detach), 107 108 /* bus interface */ 109 DEVMETHOD(bus_add_child, device_add_child_ordered), 110 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 111 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 112 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 113 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 114 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 115 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), 116 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 117 118 /* etherswitch interface */ 119 DEVMETHOD(etherswitch_getinfo, felix_getinfo), 120 DEVMETHOD(etherswitch_getconf, felix_getconf), 121 DEVMETHOD(etherswitch_setconf, felix_setconf), 122 DEVMETHOD(etherswitch_lock, felix_lock), 123 DEVMETHOD(etherswitch_unlock, felix_unlock), 124 DEVMETHOD(etherswitch_getport, felix_getport), 125 DEVMETHOD(etherswitch_setport, felix_setport), 126 DEVMETHOD(etherswitch_readreg, felix_readreg_wrapper), 127 DEVMETHOD(etherswitch_writereg, felix_writereg_wrapper), 128 DEVMETHOD(etherswitch_readphyreg, felix_readphy), 129 DEVMETHOD(etherswitch_writephyreg, felix_writephy), 130 DEVMETHOD(etherswitch_setvgroup, felix_setvgroup), 131 DEVMETHOD(etherswitch_getvgroup, felix_getvgroup), 132 133 /* miibus interface */ 134 DEVMETHOD(miibus_readreg, felix_readphy), 135 DEVMETHOD(miibus_writereg, felix_writephy), 136 137 DEVMETHOD_END 138 }; 139 140 DEFINE_CLASS_0(felix, felix_driver, felix_methods, 141 sizeof(struct felix_softc)); 142 143 DRIVER_MODULE_ORDERED(felix, pci, felix_driver, NULL, NULL, SI_ORDER_ANY); 144 DRIVER_MODULE(miibus, felix, miibus_fdt_driver, NULL, NULL); 145 DRIVER_MODULE(etherswitch, felix, etherswitch_driver, NULL, NULL); 146 MODULE_VERSION(felix, 1); 147 MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, felix, 148 felix_pci_ids, nitems(felix_pci_ids) - 1); 149 150 static int 151 felix_probe(device_t dev) 152 { 153 struct felix_pci_id *id; 154 felix_softc_t sc; 155 156 sc = device_get_softc(dev); 157 sc->dev = dev; 158 159 for (id = felix_pci_ids; id->vendor != 0; ++id) { 160 if (pci_get_device(dev) != id->device || 161 pci_get_vendor(dev) != id->vendor) 162 continue; 163 164 device_set_desc(dev, id->desc); 165 166 return (BUS_PROBE_DEFAULT); 167 } 168 169 return (ENXIO); 170 } 171 172 static int 173 felix_parse_port_fdt(felix_softc_t sc, phandle_t child, int *pport) 174 { 175 uint32_t port, status; 176 phandle_t node; 177 178 if (OF_getencprop(child, "reg", (void *)&port, sizeof(port)) < 0) { 179 device_printf(sc->dev, "Port node doesn't have reg property\n"); 180 return (ENXIO); 181 } 182 183 *pport = port; 184 185 node = OF_getproplen(child, "ethernet"); 186 if (node <= 0) 187 sc->ports[port].cpu_port = false; 188 else 189 sc->ports[port].cpu_port = true; 190 191 node = ofw_bus_find_child(child, "fixed-link"); 192 if (node <= 0) { 193 sc->ports[port].fixed_port = false; 194 return (0); 195 } 196 197 sc->ports[port].fixed_port = true; 198 199 if (OF_getencprop(node, "speed", &status, sizeof(status)) <= 0) { 200 device_printf(sc->dev, 201 "Port has fixed-link node without link speed specified\n"); 202 return (ENXIO); 203 } 204 205 switch (status) { 206 case 2500: 207 status = IFM_2500_T; 208 break; 209 case 1000: 210 status = IFM_1000_T; 211 break; 212 case 100: 213 status = IFM_100_T; 214 break; 215 case 10: 216 status = IFM_10_T; 217 break; 218 default: 219 device_printf(sc->dev, 220 "Unsupported link speed value of %d\n", 221 status); 222 return (ENXIO); 223 } 224 225 if (OF_hasprop(node, "full-duplex")) 226 status |= IFM_FDX; 227 else 228 status |= IFM_HDX; 229 230 status |= IFM_ETHER; 231 sc->ports[port].fixed_link_status = status; 232 return (0); 233 } 234 235 static int 236 felix_init_interface(felix_softc_t sc, int port) 237 { 238 char name[IFNAMSIZ]; 239 240 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->dev)); 241 242 sc->ports[port].ifp = if_alloc(IFT_ETHER); 243 if_setsoftc(sc->ports[port].ifp, sc); 244 if_setflags(sc->ports[port].ifp, IFF_UP | IFF_BROADCAST | IFF_MULTICAST | 245 IFF_DRV_RUNNING | IFF_SIMPLEX); 246 sc->ports[port].ifname = malloc(strlen(name) + 1, M_FELIX, M_NOWAIT); 247 if (sc->ports[port].ifname == NULL) { 248 if_free(sc->ports[port].ifp); 249 return (ENOMEM); 250 } 251 252 memcpy(sc->ports[port].ifname, name, strlen(name) + 1); 253 if_initname(sc->ports[port].ifp, sc->ports[port].ifname, port); 254 return (0); 255 } 256 257 static void 258 felix_setup_port(felix_softc_t sc, int port) 259 { 260 261 /* Link speed has to be always set to 1000 in the clock register. */ 262 FELIX_DEVGMII_PORT_WR4(sc, port, FELIX_DEVGMII_CLK_CFG, 263 FELIX_DEVGMII_CLK_CFG_SPEED_1000); 264 FELIX_DEVGMII_PORT_WR4(sc, port, FELIX_DEVGMII_MAC_CFG, 265 FELIX_DEVGMII_MAC_CFG_TX_ENA | FELIX_DEVGMII_MAC_CFG_RX_ENA); 266 FELIX_WR4(sc, FELIX_QSYS_PORT_MODE(port), 267 FELIX_QSYS_PORT_MODE_PORT_ENA); 268 269 /* 270 * Enable "VLANMTU". Each port has a configurable MTU. 271 * Accept frames that are 8 and 4 bytes longer than it 272 * for double and single tagged frames respectively. 273 * Since etherswitch API doesn't provide an option to change 274 * MTU don't touch it for now. 275 */ 276 FELIX_DEVGMII_PORT_WR4(sc, port, FELIX_DEVGMII_VLAN_CFG, 277 FELIX_DEVGMII_VLAN_CFG_ENA | 278 FELIX_DEVGMII_VLAN_CFG_LEN_ENA | 279 FELIX_DEVGMII_VLAN_CFG_DOUBLE_ENA); 280 } 281 282 static int 283 felix_setup(felix_softc_t sc) 284 { 285 int timeout, i; 286 uint32_t reg; 287 288 /* Trigger soft reset, bit is self-clearing, with 5s timeout. */ 289 FELIX_WR4(sc, FELIX_DEVCPU_GCB_RST, FELIX_DEVCPU_GCB_RST_EN); 290 timeout = FELIX_INIT_TIMEOUT; 291 do { 292 DELAY(1000); 293 reg = FELIX_RD4(sc, FELIX_DEVCPU_GCB_RST); 294 if ((reg & FELIX_DEVCPU_GCB_RST_EN) == 0) 295 break; 296 } while (timeout-- > 0); 297 if (timeout == 0) { 298 device_printf(sc->dev, 299 "Timeout while waiting for switch to reset\n"); 300 return (ETIMEDOUT); 301 } 302 303 FELIX_WR4(sc, FELIX_SYS_RAM_CTRL, FELIX_SYS_RAM_CTRL_INIT); 304 timeout = FELIX_INIT_TIMEOUT; 305 do { 306 DELAY(1000); 307 reg = FELIX_RD4(sc, FELIX_SYS_RAM_CTRL); 308 if ((reg & FELIX_SYS_RAM_CTRL_INIT) == 0) 309 break; 310 } while (timeout-- > 0); 311 if (timeout == 0) { 312 device_printf(sc->dev, 313 "Timeout while waiting for switch RAM init.\n"); 314 return (ETIMEDOUT); 315 } 316 317 FELIX_WR4(sc, FELIX_SYS_CFG, FELIX_SYS_CFG_CORE_EN); 318 319 for (i = 0; i < sc->info.es_nports; i++) 320 felix_setup_port(sc, i); 321 322 return (0); 323 } 324 325 static int 326 felix_timer_rate(SYSCTL_HANDLER_ARGS) 327 { 328 felix_softc_t sc; 329 int error, value, old; 330 331 sc = arg1; 332 333 old = value = sc->timer_ticks; 334 error = sysctl_handle_int(oidp, &value, 0, req); 335 if (error != 0 || req->newptr == NULL) 336 return (error); 337 338 if (value < 0) 339 return (EINVAL); 340 341 if (value == old) 342 return (0); 343 344 FELIX_LOCK(sc); 345 sc->timer_ticks = value; 346 callout_reset(&sc->tick_callout, sc->timer_ticks, felix_tick, sc); 347 FELIX_UNLOCK(sc); 348 349 return (0); 350 } 351 352 static int 353 felix_attach(device_t dev) 354 { 355 phandle_t child, ports, node; 356 int error, port, rid; 357 felix_softc_t sc; 358 uint32_t phy_addr; 359 ssize_t size; 360 361 sc = device_get_softc(dev); 362 sc->info.es_nports = 0; 363 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q; 364 strlcpy(sc->info.es_name, "Felix TSN Switch", sizeof(sc->info.es_name)); 365 366 rid = PCIR_BAR(FELIX_BAR_MDIO); 367 sc->mdio = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 368 RF_ACTIVE); 369 if (sc->mdio == NULL) { 370 device_printf(dev, "Failed to allocate MDIO registers.\n"); 371 return (ENXIO); 372 } 373 374 rid = PCIR_BAR(FELIX_BAR_REGS); 375 sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 376 RF_ACTIVE); 377 if (sc->regs == NULL) { 378 device_printf(dev, "Failed to allocate registers BAR.\n"); 379 error = ENXIO; 380 goto out_fail; 381 } 382 383 mtx_init(&sc->mtx, "felix lock", NULL, MTX_DEF); 384 callout_init_mtx(&sc->tick_callout, &sc->mtx, 0); 385 386 node = ofw_bus_get_node(dev); 387 if (node <= 0) { 388 error = ENXIO; 389 goto out_fail; 390 } 391 392 ports = ofw_bus_find_child(node, "ports"); 393 if (ports == 0) { 394 device_printf(dev, 395 "Failed to find \"ports\" property in DTS.\n"); 396 error = ENXIO; 397 goto out_fail; 398 } 399 400 for (child = OF_child(ports); child != 0; child = OF_peer(child)) { 401 /* Do not parse disabled ports. */ 402 if (ofw_bus_node_status_okay(child) == 0) 403 continue; 404 405 error = felix_parse_port_fdt(sc, child, &port); 406 if (error != 0) 407 goto out_fail; 408 409 error = felix_init_interface(sc, port); 410 if (error != 0) { 411 device_printf(sc->dev, 412 "Failed to initialize interface.\n"); 413 goto out_fail; 414 } 415 416 if (sc->ports[port].fixed_port) { 417 sc->info.es_nports++; 418 continue; 419 } 420 421 size = OF_getencprop(child, "phy-handle", &node, sizeof(node)); 422 if (size <= 0) { 423 device_printf(sc->dev, 424 "Failed to acquire PHY handle from FDT.\n"); 425 error = ENXIO; 426 goto out_fail; 427 } 428 429 node = OF_node_from_xref(node); 430 size = OF_getencprop(node, "reg", &phy_addr, sizeof(phy_addr)); 431 if (size <= 0) { 432 device_printf(sc->dev, 433 "Failed to obtain PHY address.\n"); 434 error = ENXIO; 435 goto out_fail; 436 } 437 438 sc->ports[port].phyaddr = phy_addr; 439 sc->ports[port].miibus = NULL; 440 error = mii_attach(dev, &sc->ports[port].miibus, sc->ports[port].ifp, 441 felix_ifmedia_upd, felix_ifmedia_sts, BMSR_DEFCAPMASK, 442 phy_addr, MII_OFFSET_ANY, 0); 443 if (error != 0) 444 goto out_fail; 445 446 sc->info.es_nports++; 447 } 448 449 error = felix_setup(sc); 450 if (error != 0) 451 goto out_fail; 452 453 sc->timer_ticks = hz; /* Default to 1s. */ 454 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 455 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 456 OID_AUTO, "timer_ticks", CTLTYPE_INT | CTLFLAG_RW, 457 sc, 0, felix_timer_rate, "I", 458 "Number of ticks between timer invocations"); 459 460 /* The tick routine has to be called with the lock held. */ 461 FELIX_LOCK(sc); 462 felix_tick(sc); 463 FELIX_UNLOCK(sc); 464 465 /* Allow etherswitch to attach as our child. */ 466 bus_identify_children(dev); 467 bus_attach_children(dev); 468 469 return (0); 470 471 out_fail: 472 felix_detach(dev); 473 return (error); 474 } 475 476 static int 477 felix_detach(device_t dev) 478 { 479 felix_softc_t sc; 480 int error; 481 int i; 482 483 error = 0; 484 sc = device_get_softc(dev); 485 bus_generic_detach(dev); 486 487 mtx_lock(&sc->mtx); 488 callout_stop(&sc->tick_callout); 489 mtx_unlock(&sc->mtx); 490 mtx_destroy(&sc->mtx); 491 492 /* 493 * If we have been fully attached do a soft reset. 494 * This way after when driver is unloaded switch is left in unmanaged mode. 495 */ 496 if (device_is_attached(dev)) 497 felix_setup(sc); 498 499 for (i = 0; i < sc->info.es_nports; i++) { 500 if (sc->ports[i].ifp != NULL) 501 if_free(sc->ports[i].ifp); 502 if (sc->ports[i].ifname != NULL) 503 free(sc->ports[i].ifname, M_FELIX); 504 } 505 506 if (sc->regs != NULL) 507 error = bus_release_resource(sc->dev, SYS_RES_MEMORY, 508 rman_get_rid(sc->regs), sc->regs); 509 510 if (sc->mdio != NULL) 511 error = bus_release_resource(sc->dev, SYS_RES_MEMORY, 512 rman_get_rid(sc->mdio), sc->mdio); 513 514 return (error); 515 } 516 517 static etherswitch_info_t* 518 felix_getinfo(device_t dev) 519 { 520 felix_softc_t sc; 521 522 sc = device_get_softc(dev); 523 return (&sc->info); 524 } 525 526 static int 527 felix_getconf(device_t dev, etherswitch_conf_t *conf) 528 { 529 felix_softc_t sc; 530 531 sc = device_get_softc(dev); 532 533 /* Return the VLAN mode. */ 534 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; 535 conf->vlan_mode = sc->vlan_mode; 536 return (0); 537 } 538 539 static int 540 felix_init_vlan(felix_softc_t sc) 541 { 542 int timeout = FELIX_INIT_TIMEOUT; 543 uint32_t reg; 544 int i; 545 546 /* Flush VLAN table in hardware. */ 547 FELIX_WR4(sc, FELIX_ANA_VT, FELIX_ANA_VT_RESET); 548 do { 549 DELAY(1000); 550 reg = FELIX_RD4(sc, FELIX_ANA_VT); 551 if ((reg & FELIX_ANA_VT_STS) == FELIX_ANA_VT_IDLE) 552 break; 553 } while (timeout-- > 0); 554 if (timeout == 0) { 555 device_printf(sc->dev, 556 "Timeout during VLAN table reset.\n"); 557 return (ETIMEDOUT); 558 } 559 560 /* Flush VLAN table in sc. */ 561 for (i = 0; i < sc->info.es_nvlangroups; i++) 562 sc->vlans[i] = 0; 563 564 /* 565 * Make all ports VLAN aware. 566 * Read VID from incoming frames and use it for port grouping 567 * purposes. 568 * Don't set this if pvid is set. 569 */ 570 for (i = 0; i < sc->info.es_nports; i++) { 571 reg = FELIX_ANA_PORT_RD4(sc, i, FELIX_ANA_PORT_VLAN_CFG); 572 if ((reg & FELIX_ANA_PORT_VLAN_CFG_VID_MASK) != 0) 573 continue; 574 575 reg |= FELIX_ANA_PORT_VLAN_CFG_VID_AWARE; 576 FELIX_ANA_PORT_WR4(sc, i, FELIX_ANA_PORT_VLAN_CFG, reg); 577 } 578 return (0); 579 } 580 581 static int 582 felix_setconf(device_t dev, etherswitch_conf_t *conf) 583 { 584 felix_softc_t sc; 585 int error; 586 587 error = 0; 588 /* Set the VLAN mode. */ 589 sc = device_get_softc(dev); 590 FELIX_LOCK(sc); 591 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) { 592 switch (conf->vlan_mode) { 593 case ETHERSWITCH_VLAN_DOT1Q: 594 sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q; 595 sc->info.es_nvlangroups = FELIX_NUM_VLANS; 596 error = felix_init_vlan(sc); 597 break; 598 default: 599 error = EINVAL; 600 } 601 } 602 FELIX_UNLOCK(sc); 603 return (error); 604 } 605 606 static void 607 felix_lock(device_t dev) 608 { 609 felix_softc_t sc; 610 611 sc = device_get_softc(dev); 612 FELIX_LOCK_ASSERT(sc, MA_NOTOWNED); 613 FELIX_LOCK(sc); 614 } 615 616 static void 617 felix_unlock(device_t dev) 618 { 619 felix_softc_t sc; 620 621 sc = device_get_softc(dev); 622 FELIX_LOCK_ASSERT(sc, MA_OWNED); 623 FELIX_UNLOCK(sc); 624 } 625 626 static void 627 felix_get_port_cfg(felix_softc_t sc, etherswitch_port_t *p) 628 { 629 uint32_t reg; 630 631 p->es_flags = 0; 632 633 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_DROP_CFG); 634 if (reg & FELIX_ANA_PORT_DROP_CFG_TAGGED) 635 p->es_flags |= ETHERSWITCH_PORT_DROPTAGGED; 636 637 if (reg & FELIX_ANA_PORT_DROP_CFG_UNTAGGED) 638 p->es_flags |= ETHERSWITCH_PORT_DROPUNTAGGED; 639 640 reg = FELIX_DEVGMII_PORT_RD4(sc, p->es_port, FELIX_DEVGMII_VLAN_CFG); 641 if (reg & FELIX_DEVGMII_VLAN_CFG_DOUBLE_ENA) 642 p->es_flags |= ETHERSWITCH_PORT_DOUBLE_TAG; 643 644 reg = FELIX_REW_PORT_RD4(sc, p->es_port, FELIX_REW_PORT_TAG_CFG); 645 if (reg & FELIX_REW_PORT_TAG_CFG_ALL) 646 p->es_flags |= ETHERSWITCH_PORT_ADDTAG; 647 648 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_VLAN_CFG); 649 if (reg & FELIX_ANA_PORT_VLAN_CFG_POP) 650 p->es_flags |= ETHERSWITCH_PORT_STRIPTAGINGRESS; 651 652 p->es_pvid = reg & FELIX_ANA_PORT_VLAN_CFG_VID_MASK; 653 } 654 655 static int 656 felix_getport(device_t dev, etherswitch_port_t *p) 657 { 658 struct ifmediareq *ifmr; 659 struct mii_data *mii; 660 felix_softc_t sc; 661 int error; 662 663 error = 0; 664 sc = device_get_softc(dev); 665 FELIX_LOCK_ASSERT(sc, MA_NOTOWNED); 666 667 if (p->es_port >= sc->info.es_nports || p->es_port < 0) 668 return (EINVAL); 669 670 FELIX_LOCK(sc); 671 felix_get_port_cfg(sc, p); 672 if (sc->ports[p->es_port].fixed_port) { 673 ifmr = &p->es_ifmr; 674 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 675 ifmr->ifm_count = 0; 676 ifmr->ifm_active = sc->ports[p->es_port].fixed_link_status; 677 ifmr->ifm_current = ifmr->ifm_active; 678 ifmr->ifm_mask = 0; 679 } else { 680 mii = felix_miiforport(sc, p->es_port); 681 error = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 682 &mii->mii_media, SIOCGIFMEDIA); 683 } 684 FELIX_UNLOCK(sc); 685 return (error); 686 } 687 688 static void 689 felix_set_port_cfg(felix_softc_t sc, etherswitch_port_t *p) 690 { 691 uint32_t reg; 692 693 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_DROP_CFG); 694 if (p->es_flags & ETHERSWITCH_PORT_DROPTAGGED) 695 reg |= FELIX_ANA_PORT_DROP_CFG_TAGGED; 696 else 697 reg &= ~FELIX_ANA_PORT_DROP_CFG_TAGGED; 698 699 if (p->es_flags & ETHERSWITCH_PORT_DROPUNTAGGED) 700 reg |= FELIX_ANA_PORT_DROP_CFG_UNTAGGED; 701 else 702 reg &= ~FELIX_ANA_PORT_DROP_CFG_UNTAGGED; 703 704 FELIX_ANA_PORT_WR4(sc, p->es_port, FELIX_ANA_PORT_DROP_CFG, reg); 705 706 reg = FELIX_REW_PORT_RD4(sc, p->es_port, FELIX_REW_PORT_TAG_CFG); 707 if (p->es_flags & ETHERSWITCH_PORT_ADDTAG) 708 reg |= FELIX_REW_PORT_TAG_CFG_ALL; 709 else 710 reg &= ~FELIX_REW_PORT_TAG_CFG_ALL; 711 712 FELIX_REW_PORT_WR4(sc, p->es_port, FELIX_REW_PORT_TAG_CFG, reg); 713 714 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_VLAN_CFG); 715 if (p->es_flags & ETHERSWITCH_PORT_STRIPTAGINGRESS) 716 reg |= FELIX_ANA_PORT_VLAN_CFG_POP; 717 else 718 reg &= ~FELIX_ANA_PORT_VLAN_CFG_POP; 719 720 reg &= ~FELIX_ANA_PORT_VLAN_CFG_VID_MASK; 721 reg |= p->es_pvid & FELIX_ANA_PORT_VLAN_CFG_VID_MASK; 722 /* 723 * If port VID is set use it for VLAN classification, 724 * instead of frame VID. 725 * By default the frame tag takes precedence. 726 * Force the switch to ignore it. 727 */ 728 if (p->es_pvid != 0) 729 reg &= ~FELIX_ANA_PORT_VLAN_CFG_VID_AWARE; 730 else 731 reg |= FELIX_ANA_PORT_VLAN_CFG_VID_AWARE; 732 733 FELIX_ANA_PORT_WR4(sc, p->es_port, FELIX_ANA_PORT_VLAN_CFG, reg); 734 } 735 736 static int 737 felix_setport(device_t dev, etherswitch_port_t *p) 738 { 739 felix_softc_t sc; 740 struct mii_data *mii; 741 int error; 742 743 error = 0; 744 sc = device_get_softc(dev); 745 FELIX_LOCK_ASSERT(sc, MA_NOTOWNED); 746 747 if (p->es_port >= sc->info.es_nports || p->es_port < 0) 748 return (EINVAL); 749 750 FELIX_LOCK(sc); 751 felix_set_port_cfg(sc, p); 752 if (felix_is_phyport(sc, p->es_port)) { 753 mii = felix_miiforport(sc, p->es_port); 754 error = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media, 755 SIOCSIFMEDIA); 756 } 757 FELIX_UNLOCK(sc); 758 759 return (error); 760 } 761 762 static int 763 felix_readreg_wrapper(device_t dev, int addr_reg) 764 { 765 felix_softc_t sc; 766 767 sc = device_get_softc(dev); 768 if (addr_reg > rman_get_size(sc->regs)) 769 return (UINT32_MAX); /* Can't return errors here. */ 770 771 return (FELIX_RD4(sc, addr_reg)); 772 } 773 774 static int 775 felix_writereg_wrapper(device_t dev, int addr_reg, int val) 776 { 777 felix_softc_t sc; 778 779 sc = device_get_softc(dev); 780 if (addr_reg > rman_get_size(sc->regs)) 781 return (EINVAL); 782 783 FELIX_WR4(sc, addr_reg, val); 784 return (0); 785 } 786 787 static int 788 felix_readphy(device_t dev, int phy, int reg) 789 { 790 felix_softc_t sc; 791 792 sc = device_get_softc(dev); 793 794 return (enetc_mdio_read(sc->mdio, FELIX_MDIO_BASE, phy, reg)); 795 } 796 797 static int 798 felix_writephy(device_t dev, int phy, int reg, int data) 799 { 800 felix_softc_t sc; 801 802 sc = device_get_softc(dev); 803 804 return (enetc_mdio_write(sc->mdio, FELIX_MDIO_BASE, phy, reg, data)); 805 } 806 807 static int 808 felix_set_dot1q_vlan(felix_softc_t sc, etherswitch_vlangroup_t *vg) 809 { 810 uint32_t reg; 811 int i, vid; 812 813 vid = vg->es_vid & ETHERSWITCH_VID_MASK; 814 815 /* Tagged mode is not supported. */ 816 if (vg->es_member_ports != vg->es_untagged_ports) 817 return (EINVAL); 818 819 /* 820 * Hardware support 4096 groups, but we can't do group_id == vid. 821 * Note that hw_group_id == vid. 822 */ 823 if (vid == 0) { 824 /* Clear VLAN table entry using old VID. */ 825 FELIX_WR4(sc, FELIX_ANA_VTIDX, sc->vlans[vg->es_vlangroup]); 826 FELIX_WR4(sc, FELIX_ANA_VT, FELIX_ANA_VT_WRITE); 827 sc->vlans[vg->es_vlangroup] = 0; 828 return (0); 829 } 830 831 /* The VID is already used in a different group. */ 832 for (i = 0; i < sc->info.es_nvlangroups; i++) 833 if (i != vg->es_vlangroup && vid == sc->vlans[i]) 834 return (EINVAL); 835 836 /* This group already uses a different VID. */ 837 if (sc->vlans[vg->es_vlangroup] != 0 && 838 sc->vlans[vg->es_vlangroup] != vid) 839 return (EINVAL); 840 841 sc->vlans[vg->es_vlangroup] = vid; 842 843 /* Assign members to the given group. */ 844 reg = vg->es_member_ports & FELIX_ANA_VT_PORTMASK_MASK; 845 reg <<= FELIX_ANA_VT_PORTMASK_SHIFT; 846 reg |= FELIX_ANA_VT_WRITE; 847 848 FELIX_WR4(sc, FELIX_ANA_VTIDX, vid); 849 FELIX_WR4(sc, FELIX_ANA_VT, reg); 850 851 /* 852 * According to documentation read and write commands 853 * are instant. 854 * Add a small delay just to be safe. 855 */ 856 mb(); 857 DELAY(100); 858 reg = FELIX_RD4(sc, FELIX_ANA_VT); 859 if ((reg & FELIX_ANA_VT_STS) != FELIX_ANA_VT_IDLE) 860 return (ENXIO); 861 862 return (0); 863 } 864 865 static int 866 felix_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 867 { 868 felix_softc_t sc; 869 int error; 870 871 sc = device_get_softc(dev); 872 873 FELIX_LOCK(sc); 874 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) 875 error = felix_set_dot1q_vlan(sc, vg); 876 else 877 error = EINVAL; 878 879 FELIX_UNLOCK(sc); 880 return (error); 881 } 882 883 static int 884 felix_get_dot1q_vlan(felix_softc_t sc, etherswitch_vlangroup_t *vg) 885 { 886 uint32_t reg; 887 int vid; 888 889 vid = sc->vlans[vg->es_vlangroup]; 890 891 if (vid == 0) 892 return (0); 893 894 FELIX_WR4(sc, FELIX_ANA_VTIDX, vid); 895 FELIX_WR4(sc, FELIX_ANA_VT, FELIX_ANA_VT_READ); 896 897 /* 898 * According to documentation read and write commands 899 * are instant. 900 * Add a small delay just to be safe. 901 */ 902 mb(); 903 DELAY(100); 904 reg = FELIX_RD4(sc, FELIX_ANA_VT); 905 if ((reg & FELIX_ANA_VT_STS) != FELIX_ANA_VT_IDLE) 906 return (ENXIO); 907 908 reg >>= FELIX_ANA_VT_PORTMASK_SHIFT; 909 reg &= FELIX_ANA_VT_PORTMASK_MASK; 910 911 vg->es_untagged_ports = vg->es_member_ports = reg; 912 vg->es_fid = 0; 913 vg->es_vid = vid | ETHERSWITCH_VID_VALID; 914 return (0); 915 } 916 917 static int 918 felix_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 919 { 920 felix_softc_t sc; 921 int error; 922 923 sc = device_get_softc(dev); 924 925 FELIX_LOCK(sc); 926 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) 927 error = felix_get_dot1q_vlan(sc, vg); 928 else 929 error = EINVAL; 930 931 FELIX_UNLOCK(sc); 932 return (error); 933 } 934 935 static void 936 felix_tick(void *arg) 937 { 938 struct mii_data *mii; 939 felix_softc_t sc; 940 int port; 941 942 sc = arg; 943 944 FELIX_LOCK_ASSERT(sc, MA_OWNED); 945 946 for (port = 0; port < sc->info.es_nports; port++) { 947 if (!felix_is_phyport(sc, port)) 948 continue; 949 950 mii = felix_miiforport(sc, port); 951 MPASS(mii != NULL); 952 mii_tick(mii); 953 } 954 if (sc->timer_ticks != 0) 955 callout_reset(&sc->tick_callout, sc->timer_ticks, felix_tick, sc); 956 } 957 958 static int 959 felix_ifmedia_upd(if_t ifp) 960 { 961 struct mii_data *mii; 962 felix_softc_t sc; 963 964 sc = if_getsoftc(ifp); 965 mii = felix_miiforport(sc, if_getdunit(ifp)); 966 if (mii == NULL) 967 return (ENXIO); 968 969 mii_mediachg(mii); 970 return (0); 971 } 972 973 static void 974 felix_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) 975 { 976 felix_softc_t sc; 977 struct mii_data *mii; 978 979 sc = if_getsoftc(ifp); 980 mii = felix_miiforport(sc, if_getdunit(ifp)); 981 if (mii == NULL) 982 return; 983 984 mii_pollstat(mii); 985 ifmr->ifm_active = mii->mii_media_active; 986 ifmr->ifm_status = mii->mii_media_status; 987 } 988 989 static bool 990 felix_is_phyport(felix_softc_t sc, int port) 991 { 992 993 return (!sc->ports[port].fixed_port); 994 } 995 996 static struct mii_data* 997 felix_miiforport(felix_softc_t sc, unsigned int port) 998 { 999 1000 if (!felix_is_phyport(sc, port)) 1001 return (NULL); 1002 1003 return (device_get_softc(sc->ports[port].miibus)); 1004 } 1005