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