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_generic_probe(dev); 467 bus_generic_attach(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].miibus != NULL) 501 device_delete_child(dev, sc->ports[i].miibus); 502 if (sc->ports[i].ifp != NULL) 503 if_free(sc->ports[i].ifp); 504 if (sc->ports[i].ifname != NULL) 505 free(sc->ports[i].ifname, M_FELIX); 506 } 507 508 if (sc->regs != NULL) 509 error = bus_release_resource(sc->dev, SYS_RES_MEMORY, 510 rman_get_rid(sc->regs), sc->regs); 511 512 if (sc->mdio != NULL) 513 error = bus_release_resource(sc->dev, SYS_RES_MEMORY, 514 rman_get_rid(sc->mdio), sc->mdio); 515 516 return (error); 517 } 518 519 static etherswitch_info_t* 520 felix_getinfo(device_t dev) 521 { 522 felix_softc_t sc; 523 524 sc = device_get_softc(dev); 525 return (&sc->info); 526 } 527 528 static int 529 felix_getconf(device_t dev, etherswitch_conf_t *conf) 530 { 531 felix_softc_t sc; 532 533 sc = device_get_softc(dev); 534 535 /* Return the VLAN mode. */ 536 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; 537 conf->vlan_mode = sc->vlan_mode; 538 return (0); 539 } 540 541 static int 542 felix_init_vlan(felix_softc_t sc) 543 { 544 int timeout = FELIX_INIT_TIMEOUT; 545 uint32_t reg; 546 int i; 547 548 /* Flush VLAN table in hardware. */ 549 FELIX_WR4(sc, FELIX_ANA_VT, FELIX_ANA_VT_RESET); 550 do { 551 DELAY(1000); 552 reg = FELIX_RD4(sc, FELIX_ANA_VT); 553 if ((reg & FELIX_ANA_VT_STS) == FELIX_ANA_VT_IDLE) 554 break; 555 } while (timeout-- > 0); 556 if (timeout == 0) { 557 device_printf(sc->dev, 558 "Timeout during VLAN table reset.\n"); 559 return (ETIMEDOUT); 560 } 561 562 /* Flush VLAN table in sc. */ 563 for (i = 0; i < sc->info.es_nvlangroups; i++) 564 sc->vlans[i] = 0; 565 566 /* 567 * Make all ports VLAN aware. 568 * Read VID from incoming frames and use it for port grouping 569 * purposes. 570 * Don't set this if pvid is set. 571 */ 572 for (i = 0; i < sc->info.es_nports; i++) { 573 reg = FELIX_ANA_PORT_RD4(sc, i, FELIX_ANA_PORT_VLAN_CFG); 574 if ((reg & FELIX_ANA_PORT_VLAN_CFG_VID_MASK) != 0) 575 continue; 576 577 reg |= FELIX_ANA_PORT_VLAN_CFG_VID_AWARE; 578 FELIX_ANA_PORT_WR4(sc, i, FELIX_ANA_PORT_VLAN_CFG, reg); 579 } 580 return (0); 581 } 582 583 static int 584 felix_setconf(device_t dev, etherswitch_conf_t *conf) 585 { 586 felix_softc_t sc; 587 int error; 588 589 error = 0; 590 /* Set the VLAN mode. */ 591 sc = device_get_softc(dev); 592 FELIX_LOCK(sc); 593 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) { 594 switch (conf->vlan_mode) { 595 case ETHERSWITCH_VLAN_DOT1Q: 596 sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q; 597 sc->info.es_nvlangroups = FELIX_NUM_VLANS; 598 error = felix_init_vlan(sc); 599 break; 600 default: 601 error = EINVAL; 602 } 603 } 604 FELIX_UNLOCK(sc); 605 return (error); 606 } 607 608 static void 609 felix_lock(device_t dev) 610 { 611 felix_softc_t sc; 612 613 sc = device_get_softc(dev); 614 FELIX_LOCK_ASSERT(sc, MA_NOTOWNED); 615 FELIX_LOCK(sc); 616 } 617 618 static void 619 felix_unlock(device_t dev) 620 { 621 felix_softc_t sc; 622 623 sc = device_get_softc(dev); 624 FELIX_LOCK_ASSERT(sc, MA_OWNED); 625 FELIX_UNLOCK(sc); 626 } 627 628 static void 629 felix_get_port_cfg(felix_softc_t sc, etherswitch_port_t *p) 630 { 631 uint32_t reg; 632 633 p->es_flags = 0; 634 635 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_DROP_CFG); 636 if (reg & FELIX_ANA_PORT_DROP_CFG_TAGGED) 637 p->es_flags |= ETHERSWITCH_PORT_DROPTAGGED; 638 639 if (reg & FELIX_ANA_PORT_DROP_CFG_UNTAGGED) 640 p->es_flags |= ETHERSWITCH_PORT_DROPUNTAGGED; 641 642 reg = FELIX_DEVGMII_PORT_RD4(sc, p->es_port, FELIX_DEVGMII_VLAN_CFG); 643 if (reg & FELIX_DEVGMII_VLAN_CFG_DOUBLE_ENA) 644 p->es_flags |= ETHERSWITCH_PORT_DOUBLE_TAG; 645 646 reg = FELIX_REW_PORT_RD4(sc, p->es_port, FELIX_REW_PORT_TAG_CFG); 647 if (reg & FELIX_REW_PORT_TAG_CFG_ALL) 648 p->es_flags |= ETHERSWITCH_PORT_ADDTAG; 649 650 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_VLAN_CFG); 651 if (reg & FELIX_ANA_PORT_VLAN_CFG_POP) 652 p->es_flags |= ETHERSWITCH_PORT_STRIPTAGINGRESS; 653 654 p->es_pvid = reg & FELIX_ANA_PORT_VLAN_CFG_VID_MASK; 655 } 656 657 static int 658 felix_getport(device_t dev, etherswitch_port_t *p) 659 { 660 struct ifmediareq *ifmr; 661 struct mii_data *mii; 662 felix_softc_t sc; 663 int error; 664 665 error = 0; 666 sc = device_get_softc(dev); 667 FELIX_LOCK_ASSERT(sc, MA_NOTOWNED); 668 669 if (p->es_port >= sc->info.es_nports || p->es_port < 0) 670 return (EINVAL); 671 672 FELIX_LOCK(sc); 673 felix_get_port_cfg(sc, p); 674 if (sc->ports[p->es_port].fixed_port) { 675 ifmr = &p->es_ifmr; 676 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 677 ifmr->ifm_count = 0; 678 ifmr->ifm_active = sc->ports[p->es_port].fixed_link_status; 679 ifmr->ifm_current = ifmr->ifm_active; 680 ifmr->ifm_mask = 0; 681 } else { 682 mii = felix_miiforport(sc, p->es_port); 683 error = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 684 &mii->mii_media, SIOCGIFMEDIA); 685 } 686 FELIX_UNLOCK(sc); 687 return (error); 688 } 689 690 static void 691 felix_set_port_cfg(felix_softc_t sc, etherswitch_port_t *p) 692 { 693 uint32_t reg; 694 695 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_DROP_CFG); 696 if (p->es_flags & ETHERSWITCH_PORT_DROPTAGGED) 697 reg |= FELIX_ANA_PORT_DROP_CFG_TAGGED; 698 else 699 reg &= ~FELIX_ANA_PORT_DROP_CFG_TAGGED; 700 701 if (p->es_flags & ETHERSWITCH_PORT_DROPUNTAGGED) 702 reg |= FELIX_ANA_PORT_DROP_CFG_UNTAGGED; 703 else 704 reg &= ~FELIX_ANA_PORT_DROP_CFG_UNTAGGED; 705 706 FELIX_ANA_PORT_WR4(sc, p->es_port, FELIX_ANA_PORT_DROP_CFG, reg); 707 708 reg = FELIX_REW_PORT_RD4(sc, p->es_port, FELIX_REW_PORT_TAG_CFG); 709 if (p->es_flags & ETHERSWITCH_PORT_ADDTAG) 710 reg |= FELIX_REW_PORT_TAG_CFG_ALL; 711 else 712 reg &= ~FELIX_REW_PORT_TAG_CFG_ALL; 713 714 FELIX_REW_PORT_WR4(sc, p->es_port, FELIX_REW_PORT_TAG_CFG, reg); 715 716 reg = FELIX_ANA_PORT_RD4(sc, p->es_port, FELIX_ANA_PORT_VLAN_CFG); 717 if (p->es_flags & ETHERSWITCH_PORT_STRIPTAGINGRESS) 718 reg |= FELIX_ANA_PORT_VLAN_CFG_POP; 719 else 720 reg &= ~FELIX_ANA_PORT_VLAN_CFG_POP; 721 722 reg &= ~FELIX_ANA_PORT_VLAN_CFG_VID_MASK; 723 reg |= p->es_pvid & FELIX_ANA_PORT_VLAN_CFG_VID_MASK; 724 /* 725 * If port VID is set use it for VLAN classification, 726 * instead of frame VID. 727 * By default the frame tag takes precedence. 728 * Force the switch to ignore it. 729 */ 730 if (p->es_pvid != 0) 731 reg &= ~FELIX_ANA_PORT_VLAN_CFG_VID_AWARE; 732 else 733 reg |= FELIX_ANA_PORT_VLAN_CFG_VID_AWARE; 734 735 FELIX_ANA_PORT_WR4(sc, p->es_port, FELIX_ANA_PORT_VLAN_CFG, reg); 736 } 737 738 static int 739 felix_setport(device_t dev, etherswitch_port_t *p) 740 { 741 felix_softc_t sc; 742 struct mii_data *mii; 743 int error; 744 745 error = 0; 746 sc = device_get_softc(dev); 747 FELIX_LOCK_ASSERT(sc, MA_NOTOWNED); 748 749 if (p->es_port >= sc->info.es_nports || p->es_port < 0) 750 return (EINVAL); 751 752 FELIX_LOCK(sc); 753 felix_set_port_cfg(sc, p); 754 if (felix_is_phyport(sc, p->es_port)) { 755 mii = felix_miiforport(sc, p->es_port); 756 error = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media, 757 SIOCSIFMEDIA); 758 } 759 FELIX_UNLOCK(sc); 760 761 return (error); 762 } 763 764 static int 765 felix_readreg_wrapper(device_t dev, int addr_reg) 766 { 767 felix_softc_t sc; 768 769 sc = device_get_softc(dev); 770 if (addr_reg > rman_get_size(sc->regs)) 771 return (UINT32_MAX); /* Can't return errors here. */ 772 773 return (FELIX_RD4(sc, addr_reg)); 774 } 775 776 static int 777 felix_writereg_wrapper(device_t dev, int addr_reg, int val) 778 { 779 felix_softc_t sc; 780 781 sc = device_get_softc(dev); 782 if (addr_reg > rman_get_size(sc->regs)) 783 return (EINVAL); 784 785 FELIX_WR4(sc, addr_reg, val); 786 return (0); 787 } 788 789 static int 790 felix_readphy(device_t dev, int phy, int reg) 791 { 792 felix_softc_t sc; 793 794 sc = device_get_softc(dev); 795 796 return (enetc_mdio_read(sc->mdio, FELIX_MDIO_BASE, phy, reg)); 797 } 798 799 static int 800 felix_writephy(device_t dev, int phy, int reg, int data) 801 { 802 felix_softc_t sc; 803 804 sc = device_get_softc(dev); 805 806 return (enetc_mdio_write(sc->mdio, FELIX_MDIO_BASE, phy, reg, data)); 807 } 808 809 static int 810 felix_set_dot1q_vlan(felix_softc_t sc, etherswitch_vlangroup_t *vg) 811 { 812 uint32_t reg; 813 int i, vid; 814 815 vid = vg->es_vid & ETHERSWITCH_VID_MASK; 816 817 /* Tagged mode is not supported. */ 818 if (vg->es_member_ports != vg->es_untagged_ports) 819 return (EINVAL); 820 821 /* 822 * Hardware support 4096 groups, but we can't do group_id == vid. 823 * Note that hw_group_id == vid. 824 */ 825 if (vid == 0) { 826 /* Clear VLAN table entry using old VID. */ 827 FELIX_WR4(sc, FELIX_ANA_VTIDX, sc->vlans[vg->es_vlangroup]); 828 FELIX_WR4(sc, FELIX_ANA_VT, FELIX_ANA_VT_WRITE); 829 sc->vlans[vg->es_vlangroup] = 0; 830 return (0); 831 } 832 833 /* The VID is already used in a different group. */ 834 for (i = 0; i < sc->info.es_nvlangroups; i++) 835 if (i != vg->es_vlangroup && vid == sc->vlans[i]) 836 return (EINVAL); 837 838 /* This group already uses a different VID. */ 839 if (sc->vlans[vg->es_vlangroup] != 0 && 840 sc->vlans[vg->es_vlangroup] != vid) 841 return (EINVAL); 842 843 sc->vlans[vg->es_vlangroup] = vid; 844 845 /* Assign members to the given group. */ 846 reg = vg->es_member_ports & FELIX_ANA_VT_PORTMASK_MASK; 847 reg <<= FELIX_ANA_VT_PORTMASK_SHIFT; 848 reg |= FELIX_ANA_VT_WRITE; 849 850 FELIX_WR4(sc, FELIX_ANA_VTIDX, vid); 851 FELIX_WR4(sc, FELIX_ANA_VT, reg); 852 853 /* 854 * According to documentation read and write commands 855 * are instant. 856 * Add a small delay just to be safe. 857 */ 858 mb(); 859 DELAY(100); 860 reg = FELIX_RD4(sc, FELIX_ANA_VT); 861 if ((reg & FELIX_ANA_VT_STS) != FELIX_ANA_VT_IDLE) 862 return (ENXIO); 863 864 return (0); 865 } 866 867 static int 868 felix_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 869 { 870 felix_softc_t sc; 871 int error; 872 873 sc = device_get_softc(dev); 874 875 FELIX_LOCK(sc); 876 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) 877 error = felix_set_dot1q_vlan(sc, vg); 878 else 879 error = EINVAL; 880 881 FELIX_UNLOCK(sc); 882 return (error); 883 } 884 885 static int 886 felix_get_dot1q_vlan(felix_softc_t sc, etherswitch_vlangroup_t *vg) 887 { 888 uint32_t reg; 889 int vid; 890 891 vid = sc->vlans[vg->es_vlangroup]; 892 893 if (vid == 0) 894 return (0); 895 896 FELIX_WR4(sc, FELIX_ANA_VTIDX, vid); 897 FELIX_WR4(sc, FELIX_ANA_VT, FELIX_ANA_VT_READ); 898 899 /* 900 * According to documentation read and write commands 901 * are instant. 902 * Add a small delay just to be safe. 903 */ 904 mb(); 905 DELAY(100); 906 reg = FELIX_RD4(sc, FELIX_ANA_VT); 907 if ((reg & FELIX_ANA_VT_STS) != FELIX_ANA_VT_IDLE) 908 return (ENXIO); 909 910 reg >>= FELIX_ANA_VT_PORTMASK_SHIFT; 911 reg &= FELIX_ANA_VT_PORTMASK_MASK; 912 913 vg->es_untagged_ports = vg->es_member_ports = reg; 914 vg->es_fid = 0; 915 vg->es_vid = vid | ETHERSWITCH_VID_VALID; 916 return (0); 917 } 918 919 static int 920 felix_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 921 { 922 felix_softc_t sc; 923 int error; 924 925 sc = device_get_softc(dev); 926 927 FELIX_LOCK(sc); 928 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) 929 error = felix_get_dot1q_vlan(sc, vg); 930 else 931 error = EINVAL; 932 933 FELIX_UNLOCK(sc); 934 return (error); 935 } 936 937 static void 938 felix_tick(void *arg) 939 { 940 struct mii_data *mii; 941 felix_softc_t sc; 942 int port; 943 944 sc = arg; 945 946 FELIX_LOCK_ASSERT(sc, MA_OWNED); 947 948 for (port = 0; port < sc->info.es_nports; port++) { 949 if (!felix_is_phyport(sc, port)) 950 continue; 951 952 mii = felix_miiforport(sc, port); 953 MPASS(mii != NULL); 954 mii_tick(mii); 955 } 956 if (sc->timer_ticks != 0) 957 callout_reset(&sc->tick_callout, sc->timer_ticks, felix_tick, sc); 958 } 959 960 static int 961 felix_ifmedia_upd(if_t ifp) 962 { 963 struct mii_data *mii; 964 felix_softc_t sc; 965 966 sc = if_getsoftc(ifp); 967 mii = felix_miiforport(sc, if_getdunit(ifp)); 968 if (mii == NULL) 969 return (ENXIO); 970 971 mii_mediachg(mii); 972 return (0); 973 } 974 975 static void 976 felix_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) 977 { 978 felix_softc_t sc; 979 struct mii_data *mii; 980 981 sc = if_getsoftc(ifp); 982 mii = felix_miiforport(sc, if_getdunit(ifp)); 983 if (mii == NULL) 984 return; 985 986 mii_pollstat(mii); 987 ifmr->ifm_active = mii->mii_media_active; 988 ifmr->ifm_status = mii->mii_media_status; 989 } 990 991 static bool 992 felix_is_phyport(felix_softc_t sc, int port) 993 { 994 995 return (!sc->ports[port].fixed_port); 996 } 997 998 static struct mii_data* 999 felix_miiforport(felix_softc_t sc, unsigned int port) 1000 { 1001 1002 if (!felix_is_phyport(sc, port)) 1003 return (NULL); 1004 1005 return (device_get_softc(sc->ports[port].miibus)); 1006 } 1007