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