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