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