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