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