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