arswitch.c revision 241578
1/*- 2 * Copyright (c) 2011-2012 Stefan Bethke. 3 * Copyright (c) 2012 Adrian Chadd. 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 * $FreeBSD: head/sys/dev/etherswitch/arswitch/arswitch.c 241578 2012-10-15 12:20:40Z ray $ 28 */ 29 30#include <sys/param.h> 31#include <sys/bus.h> 32#include <sys/errno.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/socket.h> 36#include <sys/sockio.h> 37#include <sys/sysctl.h> 38#include <sys/systm.h> 39 40#include <net/if.h> 41#include <net/if_arp.h> 42#include <net/ethernet.h> 43#include <net/if_dl.h> 44#include <net/if_media.h> 45#include <net/if_types.h> 46 47#include <machine/bus.h> 48#include <dev/iicbus/iic.h> 49#include <dev/iicbus/iiconf.h> 50#include <dev/iicbus/iicbus.h> 51#include <dev/mii/mii.h> 52#include <dev/mii/miivar.h> 53#include <dev/etherswitch/mdio.h> 54 55#include <dev/etherswitch/etherswitch.h> 56 57#include <dev/etherswitch/arswitch/arswitchreg.h> 58#include <dev/etherswitch/arswitch/arswitchvar.h> 59#include <dev/etherswitch/arswitch/arswitch_reg.h> 60#include <dev/etherswitch/arswitch/arswitch_phy.h> 61 62#include <dev/etherswitch/arswitch/arswitch_7240.h> 63#include <dev/etherswitch/arswitch/arswitch_8216.h> 64#include <dev/etherswitch/arswitch/arswitch_8226.h> 65#include <dev/etherswitch/arswitch/arswitch_8316.h> 66 67#include "mdio_if.h" 68#include "miibus_if.h" 69#include "etherswitch_if.h" 70 71#if defined(DEBUG) 72static SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch"); 73#endif 74 75static inline int arswitch_portforphy(int phy); 76static void arswitch_tick(void *arg); 77static int arswitch_ifmedia_upd(struct ifnet *); 78static void arswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *); 79 80static void 81arswitch_identify(driver_t *driver, device_t parent) 82{ 83 device_t child; 84 85 if (device_find_child(parent, driver->name, -1) == NULL) { 86 child = BUS_ADD_CHILD(parent, 0, driver->name, -1); 87 } 88} 89 90static int 91arswitch_probe(device_t dev) 92{ 93 struct arswitch_softc *sc; 94 uint32_t id; 95 char *chipname, desc[256]; 96 97 sc = device_get_softc(dev); 98 bzero(sc, sizeof(*sc)); 99 sc->page = -1; 100 101 /* AR7240 probe */ 102 if (ar7240_probe(dev) == 0) { 103 chipname = "AR7240"; 104 sc->sc_switchtype = AR8X16_SWITCH_AR7240; 105 id = 0; 106 goto done; 107 } 108 109 /* AR8xxx probe */ 110 id = arswitch_readreg(dev, AR8X16_REG_MASK_CTRL); 111 switch ((id & AR8X16_MASK_CTRL_VER_MASK) >> 112 AR8X16_MASK_CTRL_VER_SHIFT) { 113 case 1: 114 chipname = "AR8216"; 115 sc->sc_switchtype = AR8X16_SWITCH_AR8216; 116 break; 117 case 2: 118 chipname = "AR8226"; 119 sc->sc_switchtype = AR8X16_SWITCH_AR8226; 120 break; 121 case 16: 122 chipname = "AR8316"; 123 sc->sc_switchtype = AR8X16_SWITCH_AR8316; 124 break; 125 default: 126 chipname = NULL; 127 } 128 129done: 130 DPRINTF(dev, "chipname=%s, rev=%02x\n", chipname, 131 id & AR8X16_MASK_CTRL_REV_MASK); 132 if (chipname != NULL) { 133 snprintf(desc, sizeof(desc), 134 "Atheros %s Ethernet Switch", 135 chipname); 136 device_set_desc_copy(dev, desc); 137 return (BUS_PROBE_DEFAULT); 138 } 139 return (ENXIO); 140} 141 142static int 143arswitch_attach_phys(struct arswitch_softc *sc) 144{ 145 int phy, err = 0; 146 char name[IFNAMSIZ]; 147 148 /* PHYs need an interface, so we generate a dummy one */ 149 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); 150 for (phy = 0; phy < sc->numphys; phy++) { 151 sc->ifp[phy] = if_alloc(IFT_ETHER); 152 sc->ifp[phy]->if_softc = sc; 153 sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST | 154 IFF_DRV_RUNNING | IFF_SIMPLEX; 155 sc->ifname[phy] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK); 156 bcopy(name, sc->ifname[phy], strlen(name)+1); 157 if_initname(sc->ifp[phy], sc->ifname[phy], 158 arswitch_portforphy(phy)); 159 err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy], 160 arswitch_ifmedia_upd, arswitch_ifmedia_sts, \ 161 BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 162 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", 163 device_get_nameunit(sc->miibus[phy]), 164 sc->ifp[phy]->if_xname); 165 if (err != 0) { 166 device_printf(sc->sc_dev, 167 "attaching PHY %d failed\n", 168 phy); 169 } 170 } 171 return (err); 172} 173 174static int 175arswitch_attach(device_t dev) 176{ 177 struct arswitch_softc *sc; 178 int err = 0; 179 180 sc = device_get_softc(dev); 181 182 /* sc->sc_switchtype is already decided in arswitch_probe() */ 183 sc->sc_dev = dev; 184 mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF); 185 sc->page = -1; 186 strlcpy(sc->info.es_name, device_get_desc(dev), 187 sizeof(sc->info.es_name)); 188 189 /* 190 * Attach switch related functions 191 */ 192 if (AR8X16_IS_SWITCH(sc, AR7240)) 193 ar7240_attach(sc); 194 else if (AR8X16_IS_SWITCH(sc, AR8216)) 195 ar8216_attach(sc); 196 else if (AR8X16_IS_SWITCH(sc, AR8226)) 197 ar8226_attach(sc); 198 else if (AR8X16_IS_SWITCH(sc, AR8316)) 199 ar8316_attach(sc); 200 else 201 return (ENXIO); 202 203 /* 204 * XXX these two should be part of the switch attach function 205 */ 206 sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */ 207 sc->info.es_nvlangroups = 16; 208 209 /* XXX Defaults for externally connected AR8316 */ 210 sc->numphys = 4; 211 sc->phy4cpu = 1; 212 sc->is_rgmii = 1; 213 sc->is_gmii = 0; 214 215 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 216 "numphys", &sc->numphys); 217 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 218 "phy4cpu", &sc->phy4cpu); 219 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 220 "is_rgmii", &sc->is_rgmii); 221 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 222 "is_gmii", &sc->is_gmii); 223 224 /* 225 * This requires much more setup depending upon each chip, including: 226 * 227 * + Proper reinitialisation of the PHYs; 228 * + Initialising the VLAN table; 229 * + Initialising the port access table and CPU flood/broadcast 230 * configuration; 231 * + Other things I haven't yet thought of. 232 */ 233#ifdef NOTYET 234 arswitch_writereg(dev, AR8X16_REG_MASK_CTRL, 235 AR8X16_MASK_CTRL_SOFT_RESET); 236 DELAY(1000); 237 if (arswitch_readreg(dev, AR8X16_REG_MASK_CTRL) & 238 AR8X16_MASK_CTRL_SOFT_RESET) { 239 device_printf(dev, "unable to reset switch\n"); 240 return (ENXIO); 241 } 242#endif 243 244 err = sc->hal.arswitch_hw_setup(sc); 245 if (err != 0) 246 return (err); 247 248 err = sc->hal.arswitch_hw_global_setup(sc); 249 if (err != 0) 250 return (err); 251 252 /* 253 * Attach the PHYs and complete the bus enumeration. 254 */ 255 err = arswitch_attach_phys(sc); 256 if (err != 0) 257 return (err); 258 259 bus_generic_probe(dev); 260 bus_enumerate_hinted_children(dev); 261 err = bus_generic_attach(dev); 262 if (err != 0) 263 return (err); 264 265 callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0); 266 267 ARSWITCH_LOCK(sc); 268 arswitch_tick(sc); 269 ARSWITCH_UNLOCK(sc); 270 271 return (err); 272} 273 274static int 275arswitch_detach(device_t dev) 276{ 277 struct arswitch_softc *sc = device_get_softc(dev); 278 int i; 279 280 callout_drain(&sc->callout_tick); 281 282 for (i=0; i < sc->numphys; i++) { 283 if (sc->miibus[i] != NULL) 284 device_delete_child(dev, sc->miibus[i]); 285 if (sc->ifp[i] != NULL) 286 if_free(sc->ifp[i]); 287 free(sc->ifname[i], M_DEVBUF); 288 } 289 290 bus_generic_detach(dev); 291 mtx_destroy(&sc->sc_mtx); 292 293 return (0); 294} 295 296/* 297 * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to 298 * port 2, etc. 299 */ 300static inline int 301arswitch_portforphy(int phy) 302{ 303 return (phy+1); 304} 305 306static inline struct mii_data * 307arswitch_miiforport(struct arswitch_softc *sc, int port) 308{ 309 int phy = port-1; 310 311 if (phy < 0 || phy >= sc->numphys) 312 return (NULL); 313 return (device_get_softc(sc->miibus[phy])); 314} 315 316static inline struct ifnet * 317arswitch_ifpforport(struct arswitch_softc *sc, int port) 318{ 319 int phy = port-1; 320 321 if (phy < 0 || phy >= sc->numphys) 322 return (NULL); 323 return (sc->ifp[phy]); 324} 325 326/* 327 * Convert port status to ifmedia. 328 */ 329static void 330arswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active) 331{ 332 *media_active = IFM_ETHER; 333 *media_status = IFM_AVALID; 334 335 if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0) 336 *media_status |= IFM_ACTIVE; 337 else { 338 *media_active |= IFM_NONE; 339 return; 340 } 341 switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) { 342 case AR8X16_PORT_STS_SPEED_10: 343 *media_active |= IFM_10_T; 344 break; 345 case AR8X16_PORT_STS_SPEED_100: 346 *media_active |= IFM_100_TX; 347 break; 348 case AR8X16_PORT_STS_SPEED_1000: 349 *media_active |= IFM_1000_T; 350 break; 351 } 352 if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0) 353 *media_active |= IFM_FDX; 354 else 355 *media_active |= IFM_HDX; 356 if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0) 357 *media_active |= IFM_ETH_TXPAUSE; 358 if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0) 359 *media_active |= IFM_ETH_RXPAUSE; 360} 361 362/* 363 * Poll the status for all PHYs. We're using the switch port status because 364 * thats a lot quicker to read than talking to all the PHYs. Care must be 365 * taken that the resulting ifmedia_active is identical to what the PHY will 366 * compute, or gratuitous link status changes will occur whenever the PHYs 367 * update function is called. 368 */ 369static void 370arswitch_miipollstat(struct arswitch_softc *sc) 371{ 372 int i; 373 struct mii_data *mii; 374 struct mii_softc *miisc; 375 int portstatus; 376 377 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED); 378 379 for (i = 0; i < sc->numphys; i++) { 380 if (sc->miibus[i] == NULL) 381 continue; 382 mii = device_get_softc(sc->miibus[i]); 383 portstatus = arswitch_readreg(sc->sc_dev, 384 AR8X16_REG_PORT_STS(arswitch_portforphy(i))); 385#if 0 386 DPRINTF(sc->sc_dev, "p[%d]=%b\n", 387 arge_portforphy(i), 388 portstatus, 389 "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7" 390 "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE"); 391#endif 392 arswitch_update_ifmedia(portstatus, &mii->mii_media_status, 393 &mii->mii_media_active); 394 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 395 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != 396 miisc->mii_inst) 397 continue; 398 mii_phy_update(miisc, MII_POLLSTAT); 399 } 400 } 401} 402 403static void 404arswitch_tick(void *arg) 405{ 406 struct arswitch_softc *sc = arg; 407 408 arswitch_miipollstat(sc); 409 callout_reset(&sc->callout_tick, hz, arswitch_tick, sc); 410} 411 412static void 413arswitch_lock(device_t dev) 414{ 415 struct arswitch_softc *sc = device_get_softc(dev); 416 417 ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 418 ARSWITCH_LOCK(sc); 419} 420 421static void 422arswitch_unlock(device_t dev) 423{ 424 struct arswitch_softc *sc = device_get_softc(dev); 425 426 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED); 427 ARSWITCH_UNLOCK(sc); 428} 429 430static etherswitch_info_t * 431arswitch_getinfo(device_t dev) 432{ 433 struct arswitch_softc *sc = device_get_softc(dev); 434 435 return (&sc->info); 436} 437 438static int 439arswitch_getport(device_t dev, etherswitch_port_t *p) 440{ 441 struct arswitch_softc *sc = device_get_softc(dev); 442 struct mii_data *mii; 443 struct ifmediareq *ifmr = &p->es_ifmr; 444 int err; 445 446 if (p->es_port < 0 || p->es_port >= AR8X16_NUM_PORTS) 447 return (ENXIO); 448 p->es_vlangroup = 0; 449 450 mii = arswitch_miiforport(sc, p->es_port); 451 if (p->es_port == 0) { 452 /* fill in fixed values for CPU port */ 453 ifmr->ifm_count = 0; 454 ifmr->ifm_current = ifmr->ifm_active = 455 IFM_ETHER | IFM_1000_T | IFM_FDX; 456 ifmr->ifm_mask = 0; 457 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 458 } else if (mii != NULL) { 459 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 460 &mii->mii_media, SIOCGIFMEDIA); 461 if (err) 462 return (err); 463 } else { 464 return (ENXIO); 465 } 466 return (0); 467} 468 469/* 470 * XXX doesn't yet work? 471 */ 472static int 473arswitch_setport(device_t dev, etherswitch_port_t *p) 474{ 475 int err; 476 struct arswitch_softc *sc; 477 struct ifmedia *ifm; 478 struct mii_data *mii; 479 struct ifnet *ifp; 480 481 /* 482 * XXX check the sc numphys, or the #define ? 483 */ 484 if (p->es_port < 0 || p->es_port >= AR8X16_NUM_PHYS) 485 return (ENXIO); 486 487 sc = device_get_softc(dev); 488 489 /* 490 * XXX TODO: don't set the CPU port? 491 */ 492 493 mii = arswitch_miiforport(sc, p->es_port); 494 if (mii == NULL) 495 return (ENXIO); 496 497 ifp = arswitch_ifpforport(sc, p->es_port); 498 499 ifm = &mii->mii_media; 500 err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); 501 return (err); 502} 503 504static int 505arswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 506{ 507 508 /* XXX not implemented yet */ 509 vg->es_vid = 0; 510 vg->es_member_ports = 0; 511 vg->es_untagged_ports = 0; 512 vg->es_fid = 0; 513 return (0); 514} 515 516static int 517arswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 518{ 519 520 /* XXX not implemented yet */ 521 return (0); 522} 523 524static void 525arswitch_statchg(device_t dev) 526{ 527 528 DPRINTF(dev, "%s\n", __func__); 529} 530 531static int 532arswitch_ifmedia_upd(struct ifnet *ifp) 533{ 534 struct arswitch_softc *sc = ifp->if_softc; 535 struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit); 536 537 if (mii == NULL) 538 return (ENXIO); 539 mii_mediachg(mii); 540 return (0); 541} 542 543static void 544arswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 545{ 546 struct arswitch_softc *sc = ifp->if_softc; 547 struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit); 548 549 DPRINTF(sc->sc_dev, "%s\n", __func__); 550 551 if (mii == NULL) 552 return; 553 mii_pollstat(mii); 554 ifmr->ifm_active = mii->mii_media_active; 555 ifmr->ifm_status = mii->mii_media_status; 556} 557 558static device_method_t arswitch_methods[] = { 559 /* Device interface */ 560 DEVMETHOD(device_identify, arswitch_identify), 561 DEVMETHOD(device_probe, arswitch_probe), 562 DEVMETHOD(device_attach, arswitch_attach), 563 DEVMETHOD(device_detach, arswitch_detach), 564 565 /* bus interface */ 566 DEVMETHOD(bus_add_child, device_add_child_ordered), 567 568 /* MII interface */ 569 DEVMETHOD(miibus_readreg, arswitch_readphy), 570 DEVMETHOD(miibus_writereg, arswitch_writephy), 571 DEVMETHOD(miibus_statchg, arswitch_statchg), 572 573 /* MDIO interface */ 574 DEVMETHOD(mdio_readreg, arswitch_readphy), 575 DEVMETHOD(mdio_writereg, arswitch_writephy), 576 577 /* etherswitch interface */ 578 DEVMETHOD(etherswitch_lock, arswitch_lock), 579 DEVMETHOD(etherswitch_unlock, arswitch_unlock), 580 DEVMETHOD(etherswitch_getinfo, arswitch_getinfo), 581 DEVMETHOD(etherswitch_readreg, arswitch_readreg), 582 DEVMETHOD(etherswitch_writereg, arswitch_writereg), 583 DEVMETHOD(etherswitch_readphyreg, arswitch_readphy), 584 DEVMETHOD(etherswitch_writephyreg, arswitch_writephy), 585 DEVMETHOD(etherswitch_getport, arswitch_getport), 586 DEVMETHOD(etherswitch_setport, arswitch_setport), 587 DEVMETHOD(etherswitch_getvgroup, arswitch_getvgroup), 588 DEVMETHOD(etherswitch_setvgroup, arswitch_setvgroup), 589 590 DEVMETHOD_END 591}; 592 593DEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods, 594 sizeof(struct arswitch_softc)); 595static devclass_t arswitch_devclass; 596 597DRIVER_MODULE(arswitch, mdio, arswitch_driver, arswitch_devclass, 0, 0); 598DRIVER_MODULE(miibus, arswitch, miibus_driver, miibus_devclass, 0, 0); 599DRIVER_MODULE(mdio, arswitch, mdio_driver, mdio_devclass, 0, 0); 600DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, etherswitch_devclass, 0, 0); 601MODULE_VERSION(arswitch, 1); 602MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */ 603MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */ 604