1 /*- 2 * Copyright (c) 2015 Semihalf 3 * Copyright (c) 2015 Stormshield 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/types.h> 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/sockio.h> 35 #include <sys/kernel.h> 36 #include <sys/kthread.h> 37 #include <sys/socket.h> 38 #include <sys/module.h> 39 #include <sys/errno.h> 40 #include <sys/bus.h> 41 #include <sys/conf.h> 42 #include <sys/uio.h> 43 #include <sys/fcntl.h> 44 45 #include <net/if.h> 46 #include <net/if_media.h> 47 #include <net/if_types.h> 48 49 #include <machine/bus.h> 50 #include <machine/resource.h> 51 52 #include <arm/mv/mvwin.h> 53 #include <arm/mv/mvreg.h> 54 #include <arm/mv/mvvar.h> 55 56 #include <dev/etherswitch/etherswitch.h> 57 #include <dev/mdio/mdio.h> 58 #include <dev/mii/mii.h> 59 #include <dev/mii/miivar.h> 60 #include <dev/mge/if_mgevar.h> 61 62 #include <dev/fdt/fdt_common.h> 63 #include <dev/ofw/ofw_bus.h> 64 #include <dev/ofw/ofw_bus_subr.h> 65 66 #include "e6000swreg.h" 67 #include "etherswitch_if.h" 68 #include "miibus_if.h" 69 #include "mdio_if.h" 70 71 MALLOC_DECLARE(M_E6000SW); 72 MALLOC_DEFINE(M_E6000SW, "e6000sw", "e6000sw switch"); 73 74 #define E6000SW_LOCK(_sc) \ 75 sx_xlock(&(_sc)->sx) 76 #define E6000SW_UNLOCK(_sc) \ 77 sx_unlock(&(_sc)->sx) 78 #define E6000SW_LOCK_ASSERT(_sc, _what) \ 79 sx_assert(&(_sc)->sx, (_what)) 80 #define E6000SW_TRYLOCK(_sc) \ 81 sx_tryxlock(&(_sc)->sx) 82 83 typedef struct e6000sw_softc { 84 device_t dev; 85 phandle_t node; 86 87 struct sx sx; 88 struct ifnet *ifp[E6000SW_MAX_PORTS]; 89 char *ifname[E6000SW_MAX_PORTS]; 90 device_t miibus[E6000SW_MAX_PORTS]; 91 struct mii_data *mii[E6000SW_MAX_PORTS]; 92 struct callout tick_callout; 93 94 uint32_t cpuports_mask; 95 uint32_t fixed_mask; 96 int sw_addr; 97 int num_ports; 98 boolean_t multi_chip; 99 100 int vid[E6000SW_NUM_VGROUPS]; 101 int members[E6000SW_NUM_VGROUPS]; 102 int vgroup[E6000SW_MAX_PORTS]; 103 } e6000sw_softc_t; 104 105 static etherswitch_info_t etherswitch_info = { 106 .es_nports = 0, 107 .es_nvlangroups = E6000SW_NUM_VGROUPS, 108 .es_name = "Marvell 6000 series switch" 109 }; 110 111 static void e6000sw_identify(driver_t *driver, device_t parent); 112 static int e6000sw_probe(device_t dev); 113 static int e6000sw_attach(device_t dev); 114 static int e6000sw_detach(device_t dev); 115 static int e6000sw_readphy(device_t dev, int phy, int reg); 116 static int e6000sw_writephy(device_t dev, int phy, int reg, int data); 117 static etherswitch_info_t* e6000sw_getinfo(device_t dev); 118 static void e6000sw_lock(device_t dev); 119 static void e6000sw_unlock(device_t dev); 120 static int e6000sw_getport(device_t dev, etherswitch_port_t *p); 121 static int e6000sw_setport(device_t dev, etherswitch_port_t *p); 122 static int e6000sw_readreg_wrapper(device_t dev, int addr_reg); 123 static int e6000sw_writereg_wrapper(device_t dev, int addr_reg, int val); 124 static int e6000sw_readphy_wrapper(device_t dev, int phy, int reg); 125 static int e6000sw_writephy_wrapper(device_t dev, int phy, int reg, int data); 126 static int e6000sw_getvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg); 127 static int e6000sw_setvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg); 128 static int e6000sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg); 129 static int e6000sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg); 130 static void e6000sw_setup(device_t dev, e6000sw_softc_t *sc); 131 static void e6000sw_port_vlan_conf(e6000sw_softc_t *sc); 132 static void e6000sw_tick(void *arg); 133 static void e6000sw_set_atustat(device_t dev, e6000sw_softc_t *sc, int bin, 134 int flag); 135 static int e6000sw_atu_flush(device_t dev, e6000sw_softc_t *sc, int flag); 136 static __inline void e6000sw_writereg(e6000sw_softc_t *sc, int addr, int reg, 137 int val); 138 static __inline uint32_t e6000sw_readreg(e6000sw_softc_t *sc, int addr, 139 int reg); 140 static int e6000sw_ifmedia_upd(struct ifnet *ifp); 141 static void e6000sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 142 static int e6000sw_atu_mac_table(device_t dev, e6000sw_softc_t *sc, struct 143 atu_opt *atu, int flag); 144 static int e6000sw_get_pvid(e6000sw_softc_t *sc, int port, int *pvid); 145 static int e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid); 146 static __inline int e6000sw_is_cpuport(e6000sw_softc_t *sc, int port); 147 static __inline int e6000sw_is_fixedport(e6000sw_softc_t *sc, int port); 148 static __inline int e6000sw_is_phyport(e6000sw_softc_t *sc, int port); 149 static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *sc, 150 unsigned int phy); 151 152 static struct proc *e6000sw_kproc; 153 154 static device_method_t e6000sw_methods[] = { 155 /* device interface */ 156 DEVMETHOD(device_identify, e6000sw_identify), 157 DEVMETHOD(device_probe, e6000sw_probe), 158 DEVMETHOD(device_attach, e6000sw_attach), 159 DEVMETHOD(device_detach, e6000sw_detach), 160 161 /* bus interface */ 162 DEVMETHOD(bus_add_child, device_add_child_ordered), 163 164 /* mii interface */ 165 DEVMETHOD(miibus_readreg, e6000sw_readphy), 166 DEVMETHOD(miibus_writereg, e6000sw_writephy), 167 168 /* etherswitch interface */ 169 DEVMETHOD(etherswitch_getinfo, e6000sw_getinfo), 170 DEVMETHOD(etherswitch_lock, e6000sw_lock), 171 DEVMETHOD(etherswitch_unlock, e6000sw_unlock), 172 DEVMETHOD(etherswitch_getport, e6000sw_getport), 173 DEVMETHOD(etherswitch_setport, e6000sw_setport), 174 DEVMETHOD(etherswitch_readreg, e6000sw_readreg_wrapper), 175 DEVMETHOD(etherswitch_writereg, e6000sw_writereg_wrapper), 176 DEVMETHOD(etherswitch_readphyreg, e6000sw_readphy_wrapper), 177 DEVMETHOD(etherswitch_writephyreg, e6000sw_writephy_wrapper), 178 DEVMETHOD(etherswitch_setvgroup, e6000sw_setvgroup_wrapper), 179 DEVMETHOD(etherswitch_getvgroup, e6000sw_getvgroup_wrapper), 180 181 DEVMETHOD_END 182 }; 183 184 static devclass_t e6000sw_devclass; 185 186 DEFINE_CLASS_0(e6000sw, e6000sw_driver, e6000sw_methods, 187 sizeof(e6000sw_softc_t)); 188 189 DRIVER_MODULE(e6000sw, mdio, e6000sw_driver, e6000sw_devclass, 0, 0); 190 DRIVER_MODULE(etherswitch, e6000sw, etherswitch_driver, etherswitch_devclass, 0, 191 0); 192 DRIVER_MODULE(miibus, e6000sw, miibus_driver, miibus_devclass, 0, 0); 193 MODULE_DEPEND(e6000sw, mdio, 1, 1, 1); 194 195 #define SMI_CMD 0 196 #define SMI_CMD_BUSY (1<<15) 197 #define SMI_CMD_OP_READ ((2<<10)|SMI_CMD_BUSY|(1<<12)) 198 #define SMI_CMD_OP_WRITE ((1<<10)|SMI_CMD_BUSY|(1<<12)) 199 #define SMI_DATA 1 200 201 #define MDIO_READ(dev, addr, reg) MDIO_READREG(device_get_parent(dev), (addr), (reg)) 202 #define MDIO_WRITE(dev, addr, reg, val) MDIO_WRITEREG(device_get_parent(dev), (addr), (reg), (val)) 203 static void 204 e6000sw_identify(driver_t *driver, device_t parent) 205 { 206 207 if (device_find_child(parent, "e6000sw", -1) == NULL) 208 BUS_ADD_CHILD(parent, 0, "e6000sw", -1); 209 } 210 211 static int 212 e6000sw_probe(device_t dev) 213 { 214 e6000sw_softc_t *sc; 215 const char *description; 216 unsigned int id; 217 uint16_t dev_addr; 218 phandle_t dsa_node, switch_node; 219 220 dsa_node = fdt_find_compatible(OF_finddevice("/"), 221 "marvell,dsa", 0); 222 switch_node = OF_child(dsa_node); 223 224 if (switch_node == 0) 225 return (ENXIO); 226 227 sc = device_get_softc(dev); 228 bzero(sc, sizeof(e6000sw_softc_t)); 229 sc->dev = dev; 230 sc->node = switch_node; 231 232 /* Read ADDR[4:1]n using indirect access */ 233 MDIO_WRITE(dev, REG_GLOBAL2, SCR_AND_MISC_REG, 234 SCR_AND_MISC_PTR_CFG); 235 dev_addr = MDIO_READ(dev, REG_GLOBAL2, SCR_AND_MISC_REG) & 236 SCR_AND_MISC_DATA_CFG_MASK; 237 if (dev_addr != 0) { 238 sc->multi_chip = true; 239 device_printf(dev, "multi-chip addresing mode\n"); 240 } else { 241 device_printf(dev, "single-chip addressing mode\n"); 242 } 243 244 if (OF_getencprop(sc->node, "reg", &sc->sw_addr, 245 sizeof(sc->sw_addr)) < 0) 246 return (ENXIO); 247 248 /* Lock is necessary due to assertions. */ 249 sx_init(&sc->sx, "e6000sw"); 250 E6000SW_LOCK(sc); 251 252 id = e6000sw_readreg(sc, REG_PORT(0), SWITCH_ID); 253 254 switch (id & 0xfff0) { 255 case 0x3520: 256 description = "Marvell 88E6352"; 257 break; 258 case 0x1720: 259 description = "Marvell 88E6172"; 260 break; 261 case 0x1760: 262 description = "Marvell 88E6176"; 263 break; 264 default: 265 E6000SW_UNLOCK(sc); 266 sx_destroy(&sc->sx); 267 device_printf(dev, "Unrecognized device, id 0x%x.\n", id); 268 return (ENXIO); 269 } 270 271 device_set_desc(dev, description); 272 273 E6000SW_UNLOCK(sc); 274 275 return (BUS_PROBE_DEFAULT); 276 } 277 278 static int 279 e6000sw_parse_child_fdt(device_t dev, phandle_t child, uint32_t *fixed_mask, 280 uint32_t *cpu_mask, int *pport, int *pvlangroup) 281 { 282 char portlabel[100]; 283 uint32_t port, vlangroup; 284 boolean_t fixed_link; 285 286 if (fixed_mask == NULL || cpu_mask == NULL || pport == NULL) 287 return (ENXIO); 288 289 OF_getprop(child, "label", (void *)portlabel, 100); 290 OF_getencprop(child, "reg", (void *)&port, sizeof(port)); 291 292 if (OF_getencprop(child, "vlangroup", (void *)&vlangroup, 293 sizeof(vlangroup)) > 0) { 294 if (vlangroup >= E6000SW_NUM_VGROUPS) 295 return (ENXIO); 296 *pvlangroup = vlangroup; 297 } else { 298 *pvlangroup = -1; 299 } 300 301 if (port >= E6000SW_MAX_PORTS) 302 return (ENXIO); 303 *pport = port; 304 305 if (strncmp(portlabel, "cpu", 3) == 0) { 306 device_printf(dev, "CPU port at %d\n", port); 307 *cpu_mask |= (1 << port); 308 return (0); 309 } 310 311 fixed_link = OF_child(child); 312 if (fixed_link) { 313 *fixed_mask |= (1 << port); 314 device_printf(dev, "fixed port at %d\n", port); 315 } else { 316 device_printf(dev, "PHY at %d\n", port); 317 } 318 319 return (0); 320 } 321 322 static int 323 e6000sw_init_interface(e6000sw_softc_t *sc, int port) 324 { 325 char name[IFNAMSIZ]; 326 327 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->dev)); 328 329 sc->ifp[port] = if_alloc(IFT_ETHER); 330 if (sc->ifp[port] == NULL) 331 return (ENOMEM); 332 sc->ifp[port]->if_softc = sc; 333 sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST | 334 IFF_DRV_RUNNING | IFF_SIMPLEX; 335 sc->ifname[port] = malloc(strlen(name) + 1, M_E6000SW, M_WAITOK); 336 if (sc->ifname[port] == NULL) 337 return (ENOMEM); 338 memcpy(sc->ifname[port], name, strlen(name) + 1); 339 if_initname(sc->ifp[port], sc->ifname[port], port); 340 341 return (0); 342 } 343 344 static int 345 e6000sw_attach_miibus(e6000sw_softc_t *sc, int port) 346 { 347 int err; 348 349 err = mii_attach(sc->dev, &sc->miibus[port], sc->ifp[port], 350 e6000sw_ifmedia_upd, e6000sw_ifmedia_sts, BMSR_DEFCAPMASK, 351 port, MII_OFFSET_ANY, 0); 352 if (err != 0) 353 return (err); 354 355 sc->mii[port] = device_get_softc(sc->miibus[port]); 356 return (0); 357 } 358 359 static int 360 e6000sw_attach(device_t dev) 361 { 362 e6000sw_softc_t *sc; 363 phandle_t child; 364 int err, port, vlangroup; 365 int member_ports[E6000SW_NUM_VGROUPS]; 366 etherswitch_vlangroup_t vg; 367 368 err = 0; 369 sc = device_get_softc(dev); 370 371 E6000SW_LOCK(sc); 372 e6000sw_setup(dev, sc); 373 bzero(member_ports, sizeof(member_ports)); 374 375 for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) { 376 err = e6000sw_parse_child_fdt(dev, child, &sc->fixed_mask, 377 &sc->cpuports_mask, &port, &vlangroup); 378 if (err != 0) { 379 device_printf(sc->dev, "failed to parse DTS\n"); 380 goto out_fail; 381 } 382 383 if (vlangroup != -1) 384 member_ports[vlangroup] |= (1 << port); 385 386 sc->num_ports++; 387 388 err = e6000sw_init_interface(sc, port); 389 if (err != 0) { 390 device_printf(sc->dev, "failed to init interface\n"); 391 goto out_fail; 392 } 393 394 /* Don't attach miibus at CPU/fixed ports */ 395 if (!e6000sw_is_phyport(sc, port)) 396 continue; 397 398 err = e6000sw_attach_miibus(sc, port); 399 if (err != 0) { 400 device_printf(sc->dev, "failed to attach miibus\n"); 401 goto out_fail; 402 } 403 } 404 405 etherswitch_info.es_nports = sc->num_ports; 406 for (port = 0; port < sc->num_ports; port++) 407 sc->vgroup[port] = E6000SW_PORT_NO_VGROUP; 408 409 /* Set VLAN configuration */ 410 e6000sw_port_vlan_conf(sc); 411 412 /* Set vlangroups */ 413 for (vlangroup = 0; vlangroup < E6000SW_NUM_VGROUPS; vlangroup++) 414 if (member_ports[vlangroup] != 0) { 415 vg.es_vlangroup = vg.es_vid = vlangroup; 416 vg.es_member_ports = vg.es_untagged_ports = 417 member_ports[vlangroup]; 418 e6000sw_setvgroup(dev, &vg); 419 } 420 421 E6000SW_UNLOCK(sc); 422 423 bus_generic_probe(dev); 424 bus_generic_attach(dev); 425 426 kproc_create(e6000sw_tick, sc, &e6000sw_kproc, 0, 0, 427 "e6000sw tick kproc"); 428 429 return (0); 430 431 out_fail: 432 e6000sw_detach(dev); 433 434 return (err); 435 } 436 437 static __inline void 438 e6000sw_poll_done(e6000sw_softc_t *sc) 439 { 440 441 while (e6000sw_readreg(sc, REG_GLOBAL2, PHY_CMD) & 442 (1 << PHY_CMD_SMI_BUSY)) 443 continue; 444 } 445 446 /* 447 * PHY registers are paged. Put page index in reg 22 (accessible from every 448 * page), then access specific register. 449 */ 450 static int 451 e6000sw_readphy(device_t dev, int phy, int reg) 452 { 453 e6000sw_softc_t *sc; 454 uint32_t val; 455 456 sc = device_get_softc(dev); 457 val = 0; 458 459 if (!e6000sw_is_phyport(sc, phy) || reg >= E6000SW_NUM_PHY_REGS) { 460 device_printf(dev, "Wrong register address.\n"); 461 return (EINVAL); 462 } 463 464 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 465 466 e6000sw_poll_done(sc); 467 val |= 1 << PHY_CMD_SMI_BUSY; 468 val |= PHY_CMD_MODE_MDIO << PHY_CMD_MODE; 469 val |= PHY_CMD_OPCODE_READ << PHY_CMD_OPCODE; 470 val |= (reg << PHY_CMD_REG_ADDR) & PHY_CMD_REG_ADDR_MASK; 471 val |= (phy << PHY_CMD_DEV_ADDR) & PHY_CMD_DEV_ADDR_MASK; 472 e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG, val); 473 e6000sw_poll_done(sc); 474 val = e6000sw_readreg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG) 475 & PHY_DATA_MASK; 476 477 return (val); 478 } 479 480 static int 481 e6000sw_writephy(device_t dev, int phy, int reg, int data) 482 { 483 e6000sw_softc_t *sc; 484 uint32_t val; 485 486 sc = device_get_softc(dev); 487 val = 0; 488 489 if (!e6000sw_is_phyport(sc, phy) || reg >= E6000SW_NUM_PHY_REGS) { 490 device_printf(dev, "Wrong register address.\n"); 491 return (EINVAL); 492 } 493 494 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 495 496 e6000sw_poll_done(sc); 497 val |= PHY_CMD_MODE_MDIO << PHY_CMD_MODE; 498 val |= 1 << PHY_CMD_SMI_BUSY; 499 val |= PHY_CMD_OPCODE_WRITE << PHY_CMD_OPCODE; 500 val |= (reg << PHY_CMD_REG_ADDR) & PHY_CMD_REG_ADDR_MASK; 501 val |= (phy << PHY_CMD_DEV_ADDR) & PHY_CMD_DEV_ADDR_MASK; 502 e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG, 503 data & PHY_DATA_MASK); 504 e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG, val); 505 e6000sw_poll_done(sc); 506 507 return (0); 508 } 509 510 static int 511 e6000sw_detach(device_t dev) 512 { 513 int phy; 514 e6000sw_softc_t *sc; 515 516 sc = device_get_softc(dev); 517 bus_generic_detach(dev); 518 sx_destroy(&sc->sx); 519 for (phy = 0; phy < sc->num_ports; phy++) { 520 if (sc->miibus[phy] != NULL) 521 device_delete_child(dev, sc->miibus[phy]); 522 if (sc->ifp[phy] != NULL) 523 if_free(sc->ifp[phy]); 524 if (sc->ifname[phy] != NULL) 525 free(sc->ifname[phy], M_E6000SW); 526 } 527 528 return (0); 529 } 530 531 static etherswitch_info_t* 532 e6000sw_getinfo(device_t dev) 533 { 534 535 return (ðerswitch_info); 536 } 537 538 static void 539 e6000sw_lock(device_t dev) 540 { 541 struct e6000sw_softc *sc; 542 543 sc = device_get_softc(dev); 544 545 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 546 E6000SW_LOCK(sc); 547 } 548 549 static void 550 e6000sw_unlock(device_t dev) 551 { 552 struct e6000sw_softc *sc; 553 554 sc = device_get_softc(dev); 555 556 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 557 E6000SW_UNLOCK(sc); 558 } 559 560 static int 561 e6000sw_getport(device_t dev, etherswitch_port_t *p) 562 { 563 struct mii_data *mii; 564 int err; 565 struct ifmediareq *ifmr; 566 567 err = 0; 568 e6000sw_softc_t *sc = device_get_softc(dev); 569 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 570 571 E6000SW_LOCK(sc); 572 573 if (p->es_port >= sc->num_ports || 574 p->es_port < 0) { 575 err = EINVAL; 576 goto out; 577 } 578 579 e6000sw_get_pvid(sc, p->es_port, &p->es_pvid); 580 581 if (e6000sw_is_cpuport(sc, p->es_port)) { 582 p->es_flags |= ETHERSWITCH_PORT_CPU; 583 ifmr = &p->es_ifmr; 584 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 585 ifmr->ifm_count = 0; 586 ifmr->ifm_current = ifmr->ifm_active = 587 IFM_ETHER | IFM_1000_T | IFM_FDX; 588 ifmr->ifm_mask = 0; 589 } else if (e6000sw_is_fixedport(sc, p->es_port)) { 590 ifmr = &p->es_ifmr; 591 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 592 ifmr->ifm_count = 0; 593 ifmr->ifm_current = ifmr->ifm_active = 594 IFM_ETHER | IFM_1000_T | IFM_FDX; 595 ifmr->ifm_mask = 0; 596 } else { 597 mii = e6000sw_miiforphy(sc, p->es_port); 598 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 599 &mii->mii_media, SIOCGIFMEDIA); 600 } 601 602 out: 603 E6000SW_UNLOCK(sc); 604 return (err); 605 } 606 607 static int 608 e6000sw_setport(device_t dev, etherswitch_port_t *p) 609 { 610 e6000sw_softc_t *sc; 611 int err; 612 struct mii_data *mii; 613 614 err = 0; 615 sc = device_get_softc(dev); 616 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 617 618 E6000SW_LOCK(sc); 619 620 if (p->es_port >= sc->num_ports || 621 p->es_port < 0) { 622 err = EINVAL; 623 goto out; 624 } 625 626 if (p->es_pvid != 0) 627 e6000sw_set_pvid(sc, p->es_port, p->es_pvid); 628 if (!e6000sw_is_cpuport(sc, p->es_port)) { 629 mii = e6000sw_miiforphy(sc, p->es_port); 630 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media, 631 SIOCSIFMEDIA); 632 } 633 634 out: 635 E6000SW_UNLOCK(sc); 636 return (err); 637 } 638 639 /* 640 * Registers in this switch are divided into sections, specified in 641 * documentation. So as to access any of them, section index and reg index 642 * is necessary. etherswitchcfg uses only one variable, so indexes were 643 * compressed into addr_reg: 32 * section_index + reg_index. 644 */ 645 static int 646 e6000sw_readreg_wrapper(device_t dev, int addr_reg) 647 { 648 649 if ((addr_reg > (REG_GLOBAL2 * 32 + REG_NUM_MAX)) || 650 (addr_reg < (REG_PORT(0) * 32))) { 651 device_printf(dev, "Wrong register address.\n"); 652 return (EINVAL); 653 } 654 655 return (e6000sw_readreg(device_get_softc(dev), addr_reg / 32, 656 addr_reg % 32)); 657 } 658 659 static int 660 e6000sw_writereg_wrapper(device_t dev, int addr_reg, int val) 661 { 662 663 if ((addr_reg > (REG_GLOBAL2 * 32 + REG_NUM_MAX)) || 664 (addr_reg < (REG_PORT(0) * 32))) { 665 device_printf(dev, "Wrong register address.\n"); 666 return (EINVAL); 667 } 668 e6000sw_writereg(device_get_softc(dev), addr_reg / 5, 669 addr_reg % 32, val); 670 671 return (0); 672 } 673 674 /* 675 * These wrappers are necessary because PHY accesses from etherswitchcfg 676 * need to be synchronized with locks, while miibus PHY accesses do not. 677 */ 678 static int 679 e6000sw_readphy_wrapper(device_t dev, int phy, int reg) 680 { 681 e6000sw_softc_t *sc; 682 int ret; 683 684 sc = device_get_softc(dev); 685 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 686 687 E6000SW_LOCK(sc); 688 ret = e6000sw_readphy(dev, phy, reg); 689 E6000SW_UNLOCK(sc); 690 691 return (ret); 692 } 693 694 static int 695 e6000sw_writephy_wrapper(device_t dev, int phy, int reg, int data) 696 { 697 e6000sw_softc_t *sc; 698 int ret; 699 700 sc = device_get_softc(dev); 701 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 702 703 E6000SW_LOCK(sc); 704 ret = e6000sw_writephy(dev, phy, reg, data); 705 E6000SW_UNLOCK(sc); 706 707 return (ret); 708 } 709 710 /* 711 * setvgroup/getvgroup called from etherswitchfcg need to be locked, 712 * while internal calls do not. 713 */ 714 static int 715 e6000sw_setvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg) 716 { 717 e6000sw_softc_t *sc; 718 int ret; 719 720 sc = device_get_softc(dev); 721 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 722 723 E6000SW_LOCK(sc); 724 ret = e6000sw_setvgroup(dev, vg); 725 E6000SW_UNLOCK(sc); 726 727 return (ret); 728 } 729 730 static int 731 e6000sw_getvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg) 732 { 733 e6000sw_softc_t *sc; 734 int ret; 735 736 sc = device_get_softc(dev); 737 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 738 739 E6000SW_LOCK(sc); 740 ret = e6000sw_getvgroup(dev, vg); 741 E6000SW_UNLOCK(sc); 742 743 return (ret); 744 } 745 746 static __inline void 747 e6000sw_flush_port(e6000sw_softc_t *sc, int port) 748 { 749 uint32_t reg; 750 751 reg = e6000sw_readreg(sc, REG_PORT(port), 752 PORT_VLAN_MAP); 753 reg &= ~PORT_VLAN_MAP_TABLE_MASK; 754 reg &= ~PORT_VLAN_MAP_FID_MASK; 755 e6000sw_writereg(sc, REG_PORT(port), 756 PORT_VLAN_MAP, reg); 757 if (sc->vgroup[port] != E6000SW_PORT_NO_VGROUP) { 758 /* 759 * If port belonged somewhere, owner-group 760 * should have its entry removed. 761 */ 762 sc->members[sc->vgroup[port]] &= ~(1 << port); 763 sc->vgroup[port] = E6000SW_PORT_NO_VGROUP; 764 } 765 } 766 767 static __inline void 768 e6000sw_port_assign_vgroup(e6000sw_softc_t *sc, int port, int fid, int vgroup, 769 int members) 770 { 771 uint32_t reg; 772 773 reg = e6000sw_readreg(sc, REG_PORT(port), 774 PORT_VLAN_MAP); 775 reg &= ~PORT_VLAN_MAP_TABLE_MASK; 776 reg &= ~PORT_VLAN_MAP_FID_MASK; 777 reg |= members & ~(1 << port); 778 reg |= (fid << PORT_VLAN_MAP_FID) & PORT_VLAN_MAP_FID_MASK; 779 e6000sw_writereg(sc, REG_PORT(port), PORT_VLAN_MAP, 780 reg); 781 sc->vgroup[port] = vgroup; 782 } 783 784 static int 785 e6000sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 786 { 787 e6000sw_softc_t *sc; 788 int port, fid; 789 790 sc = device_get_softc(dev); 791 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 792 793 if (vg->es_vlangroup >= E6000SW_NUM_VGROUPS) 794 return (EINVAL); 795 if (vg->es_member_ports != vg->es_untagged_ports) { 796 device_printf(dev, "Tagged ports not supported.\n"); 797 return (EINVAL); 798 } 799 800 vg->es_untagged_ports &= PORT_VLAN_MAP_TABLE_MASK; 801 fid = vg->es_vlangroup + 1; 802 for (port = 0; port < sc->num_ports; port++) { 803 if ((sc->members[vg->es_vlangroup] & (1 << port)) || 804 (vg->es_untagged_ports & (1 << port))) 805 e6000sw_flush_port(sc, port); 806 if (vg->es_untagged_ports & (1 << port)) 807 e6000sw_port_assign_vgroup(sc, port, fid, 808 vg->es_vlangroup, vg->es_untagged_ports); 809 } 810 sc->vid[vg->es_vlangroup] = vg->es_vid; 811 sc->members[vg->es_vlangroup] = vg->es_untagged_ports; 812 813 return (0); 814 } 815 816 static int 817 e6000sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 818 { 819 e6000sw_softc_t *sc; 820 821 sc = device_get_softc(dev); 822 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 823 824 if (vg->es_vlangroup >= E6000SW_NUM_VGROUPS) 825 return (EINVAL); 826 vg->es_untagged_ports = vg->es_member_ports = 827 sc->members[vg->es_vlangroup]; 828 vg->es_vid = ETHERSWITCH_VID_VALID; 829 830 return (0); 831 } 832 833 static __inline struct mii_data* 834 e6000sw_miiforphy(e6000sw_softc_t *sc, unsigned int phy) 835 { 836 837 if (!e6000sw_is_phyport(sc, phy)) 838 return (NULL); 839 840 return (device_get_softc(sc->miibus[phy])); 841 } 842 843 static int 844 e6000sw_ifmedia_upd(struct ifnet *ifp) 845 { 846 e6000sw_softc_t *sc; 847 struct mii_data *mii; 848 849 sc = ifp->if_softc; 850 mii = e6000sw_miiforphy(sc, ifp->if_dunit); 851 if (mii == NULL) 852 return (ENXIO); 853 mii_mediachg(mii); 854 855 return (0); 856 } 857 858 static void 859 e6000sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 860 { 861 e6000sw_softc_t *sc; 862 struct mii_data *mii; 863 864 sc = ifp->if_softc; 865 mii = e6000sw_miiforphy(sc, ifp->if_dunit); 866 867 if (mii == NULL) 868 return; 869 870 mii_pollstat(mii); 871 ifmr->ifm_active = mii->mii_media_active; 872 ifmr->ifm_status = mii->mii_media_status; 873 } 874 875 876 static int 877 e6000sw_smi_waitready(e6000sw_softc_t *sc, int phy) 878 { 879 int i; 880 881 for (i = 0; i < E6000SW_SMI_TIMEOUT; i++) { 882 if ((MDIO_READ(sc->dev, phy, SMI_CMD) 883 & SMI_CMD_BUSY) == 0) 884 return 0; 885 } 886 887 return 1; 888 } 889 890 static __inline uint32_t 891 e6000sw_readreg(e6000sw_softc_t *sc, int addr, int reg) 892 { 893 894 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 895 896 if (!sc->multi_chip) 897 return (MDIO_READ(sc->dev, addr, reg) & 0xffff); 898 899 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 900 printf("e6000sw: readreg timeout\n"); 901 return (0xffff); 902 } 903 MDIO_WRITE(sc->dev, sc->sw_addr, SMI_CMD, SMI_CMD_OP_READ | 904 (addr << 5) | reg); 905 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 906 printf("e6000sw: readreg timeout\n"); 907 return (0xffff); 908 } 909 910 return (MDIO_READ(sc->dev, sc->sw_addr, SMI_DATA) & 0xffff); 911 } 912 913 static __inline void 914 e6000sw_writereg(e6000sw_softc_t *sc, int addr, int reg, int val) 915 { 916 917 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 918 919 if (!sc->multi_chip) { 920 MDIO_WRITE(sc->dev, addr, reg, val); 921 return; 922 } 923 924 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 925 printf("e6000sw: readreg timeout\n"); 926 return; 927 } 928 MDIO_WRITE(sc->dev, sc->sw_addr, SMI_DATA, val); 929 MDIO_WRITE(sc->dev, sc->sw_addr, SMI_CMD, SMI_CMD_OP_WRITE | 930 (addr << 5) | reg); 931 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 932 printf("e6000sw: readreg timeout\n"); 933 return; 934 } 935 936 return; 937 } 938 939 static __inline int 940 e6000sw_is_cpuport(e6000sw_softc_t *sc, int port) 941 { 942 943 return (sc->cpuports_mask & (1 << port)); 944 } 945 946 static __inline int 947 e6000sw_is_fixedport(e6000sw_softc_t *sc, int port) 948 { 949 950 return (sc->fixed_mask & (1 << port)); 951 } 952 953 static __inline int 954 e6000sw_is_phyport(e6000sw_softc_t *sc, int port) 955 { 956 uint32_t phy_mask; 957 phy_mask = ~(sc->fixed_mask | sc->cpuports_mask); 958 959 return (phy_mask & (1 << port)); 960 } 961 962 static __inline int 963 e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid) 964 { 965 966 e6000sw_writereg(sc, REG_PORT(port), PORT_VID, pvid & 967 PORT_VID_DEF_VID_MASK); 968 969 return (0); 970 } 971 972 static __inline int 973 e6000sw_get_pvid(e6000sw_softc_t *sc, int port, int *pvid) 974 { 975 976 if (pvid == NULL) 977 return (ENXIO); 978 979 *pvid = e6000sw_readreg(sc, REG_PORT(port), PORT_VID) & 980 PORT_VID_DEF_VID_MASK; 981 982 return (0); 983 } 984 985 static void 986 e6000sw_tick (void *arg) 987 { 988 e6000sw_softc_t *sc; 989 struct mii_softc *miisc; 990 int port; 991 992 sc = arg; 993 994 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 995 for (;;) { 996 E6000SW_LOCK(sc); 997 for (port = 0; port < sc->num_ports; port++) { 998 /* Tick only on PHY ports */ 999 if (!e6000sw_is_phyport(sc, port)) 1000 continue; 1001 mii_tick(sc->mii[port]); 1002 LIST_FOREACH(miisc, &sc->mii[port]->mii_phys, mii_list) { 1003 if (IFM_INST(sc->mii[port]->mii_media.ifm_cur->ifm_media) 1004 != miisc->mii_inst) 1005 continue; 1006 mii_phy_update(miisc, MII_POLLSTAT); 1007 } 1008 } 1009 E6000SW_UNLOCK(sc); 1010 pause("e6000sw tick", 1000); 1011 } 1012 } 1013 1014 static void 1015 e6000sw_setup(device_t dev, e6000sw_softc_t *sc) 1016 { 1017 uint16_t atu_ctrl, atu_age; 1018 1019 /* Set aging time */ 1020 e6000sw_writereg(sc, REG_GLOBAL, ATU_CONTROL, 1021 (E6000SW_DEFAULT_AGETIME << ATU_CONTROL_AGETIME) | 1022 (1 << ATU_CONTROL_LEARN2ALL)); 1023 1024 /* Send all with specific mac address to cpu port */ 1025 e6000sw_writereg(sc, REG_GLOBAL2, MGMT_EN_2x, MGMT_EN_ALL); 1026 e6000sw_writereg(sc, REG_GLOBAL2, MGMT_EN_0x, MGMT_EN_ALL); 1027 1028 /* Disable Remote Management */ 1029 e6000sw_writereg(sc, REG_GLOBAL, SWITCH_GLOBAL_CONTROL2, 0); 1030 1031 /* Disable loopback filter and flow control messages */ 1032 e6000sw_writereg(sc, REG_GLOBAL2, SWITCH_MGMT, 1033 SWITCH_MGMT_PRI_MASK | 1034 (1 << SWITCH_MGMT_RSVD2CPU) | 1035 SWITCH_MGMT_FC_PRI_MASK | 1036 (1 << SWITCH_MGMT_FORCEFLOW)); 1037 1038 e6000sw_atu_flush(dev, sc, NO_OPERATION); 1039 e6000sw_atu_mac_table(dev, sc, NULL, NO_OPERATION); 1040 e6000sw_set_atustat(dev, sc, 0, COUNT_ALL); 1041 1042 /* Set ATU AgeTime to 15 seconds */ 1043 atu_age = 1; 1044 1045 atu_ctrl = e6000sw_readreg(sc, REG_GLOBAL, ATU_CONTROL); 1046 1047 /* Set new AgeTime field */ 1048 atu_ctrl &= ~ATU_CONTROL_AGETIME_MASK; 1049 e6000sw_writereg(sc, REG_GLOBAL, ATU_CONTROL, atu_ctrl | 1050 (atu_age << ATU_CONTROL_AGETIME)); 1051 } 1052 1053 static void 1054 e6000sw_port_vlan_conf(e6000sw_softc_t *sc) 1055 { 1056 int port, ret; 1057 device_t dev; 1058 1059 dev = sc->dev; 1060 /* Disable all ports */ 1061 for (port = 0; port < sc->num_ports; port++) { 1062 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_CONTROL); 1063 e6000sw_writereg(sc, REG_PORT(port), PORT_CONTROL, 1064 (ret & ~PORT_CONTROL_ENABLE)); 1065 } 1066 1067 /* Set port priority */ 1068 for (port = 0; port < sc->num_ports; port++) { 1069 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_VID); 1070 ret &= ~PORT_VID_PRIORITY_MASK; 1071 e6000sw_writereg(sc, REG_PORT(port), PORT_VID, ret); 1072 } 1073 1074 /* Set VID map */ 1075 for (port = 0; port < sc->num_ports; port++) { 1076 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_VID); 1077 ret &= ~PORT_VID_DEF_VID_MASK; 1078 ret |= (port + 1); 1079 e6000sw_writereg(sc, REG_PORT(port), PORT_VID, ret); 1080 } 1081 1082 /* Enable all ports */ 1083 for (port = 0; port < sc->num_ports; port++) { 1084 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_CONTROL); 1085 e6000sw_writereg(sc, REG_PORT(port), PORT_CONTROL, (ret | 1086 PORT_CONTROL_ENABLE)); 1087 } 1088 } 1089 1090 static void 1091 e6000sw_set_atustat(device_t dev, e6000sw_softc_t *sc, int bin, int flag) 1092 { 1093 uint16_t ret; 1094 1095 ret = e6000sw_readreg(sc, REG_GLOBAL2, ATU_STATS); 1096 e6000sw_writereg(sc, REG_GLOBAL2, ATU_STATS, (bin << ATU_STATS_BIN ) | 1097 (flag << ATU_STATS_FLAG)); 1098 } 1099 1100 static int 1101 e6000sw_atu_mac_table(device_t dev, e6000sw_softc_t *sc, struct atu_opt *atu, 1102 int flag) 1103 { 1104 uint16_t ret_opt; 1105 uint16_t ret_data; 1106 int retries; 1107 1108 if (flag == NO_OPERATION) 1109 return (0); 1110 else if ((flag & (LOAD_FROM_FIB | PURGE_FROM_FIB | GET_NEXT_IN_FIB | 1111 GET_VIOLATION_DATA | CLEAR_VIOLATION_DATA)) == 0) { 1112 device_printf(dev, "Wrong Opcode for ATU operation\n"); 1113 return (EINVAL); 1114 } 1115 1116 ret_opt = e6000sw_readreg(sc, REG_GLOBAL, ATU_OPERATION); 1117 1118 if (ret_opt & ATU_UNIT_BUSY) { 1119 device_printf(dev, "ATU unit is busy, cannot access" 1120 "register\n"); 1121 return (EBUSY); 1122 } else { 1123 if(flag & LOAD_FROM_FIB) { 1124 ret_data = e6000sw_readreg(sc, REG_GLOBAL, ATU_DATA); 1125 e6000sw_writereg(sc, REG_GLOBAL2, ATU_DATA, (ret_data & 1126 ~ENTRY_STATE)); 1127 } 1128 e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR01, atu->mac_01); 1129 e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR23, atu->mac_23); 1130 e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR45, atu->mac_45); 1131 e6000sw_writereg(sc, REG_GLOBAL, ATU_FID, atu->fid); 1132 1133 e6000sw_writereg(sc, REG_GLOBAL, ATU_OPERATION, (ret_opt | 1134 ATU_UNIT_BUSY | flag)); 1135 1136 retries = E6000SW_RETRIES; 1137 while (--retries & (e6000sw_readreg(sc, REG_GLOBAL, 1138 ATU_OPERATION) & ATU_UNIT_BUSY)) 1139 DELAY(1); 1140 1141 if (retries == 0) 1142 device_printf(dev, "Timeout while flushing\n"); 1143 else if (flag & GET_NEXT_IN_FIB) { 1144 atu->mac_01 = e6000sw_readreg(sc, REG_GLOBAL, 1145 ATU_MAC_ADDR01); 1146 atu->mac_23 = e6000sw_readreg(sc, REG_GLOBAL, 1147 ATU_MAC_ADDR23); 1148 atu->mac_45 = e6000sw_readreg(sc, REG_GLOBAL, 1149 ATU_MAC_ADDR45); 1150 } 1151 } 1152 1153 return (0); 1154 } 1155 1156 static int 1157 e6000sw_atu_flush(device_t dev, e6000sw_softc_t *sc, int flag) 1158 { 1159 uint16_t ret; 1160 int retries; 1161 1162 if (flag == NO_OPERATION) 1163 return (0); 1164 1165 ret = e6000sw_readreg(sc, REG_GLOBAL, ATU_OPERATION); 1166 if (ret & ATU_UNIT_BUSY) { 1167 device_printf(dev, "Atu unit is busy, cannot flush\n"); 1168 return (EBUSY); 1169 } else { 1170 e6000sw_writereg(sc, REG_GLOBAL, ATU_OPERATION, (ret | 1171 ATU_UNIT_BUSY | flag)); 1172 retries = E6000SW_RETRIES; 1173 while (--retries & (e6000sw_readreg(sc, REG_GLOBAL, 1174 ATU_OPERATION) & ATU_UNIT_BUSY)) 1175 DELAY(1); 1176 1177 if (retries == 0) 1178 device_printf(dev, "Timeout while flushing\n"); 1179 } 1180 1181 return (0); 1182 } 1183