1 /*- 2 * Copyright (c) 2011-2012 Semihalf. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/kernel.h> 30 #include <sys/module.h> 31 #include <sys/bus.h> 32 #include <sys/rman.h> 33 #include <sys/malloc.h> 34 #include <sys/mbuf.h> 35 #include <sys/socket.h> 36 #include <sys/sysctl.h> 37 #include <sys/sockio.h> 38 39 #include <machine/bus.h> 40 #include <machine/resource.h> 41 42 #include <net/ethernet.h> 43 #include <net/if.h> 44 #include <net/if_dl.h> 45 #include <net/if_media.h> 46 #include <net/if_types.h> 47 #include <net/if_arp.h> 48 49 #include <dev/mii/mii.h> 50 #include <dev/mii/miivar.h> 51 #include <dev/ofw/ofw_bus.h> 52 #include <dev/ofw/ofw_bus_subr.h> 53 #include <dev/ofw/openfirm.h> 54 55 #include "miibus_if.h" 56 57 #include "dpaa_eth.h" 58 #include "fman.h" 59 #include "fman_port.h" 60 #include "if_dtsec.h" 61 62 #include "fman_if.h" 63 #include "fman_port_if.h" 64 65 #define DTSEC_MIN_FRAME_SIZE 64 66 #define DTSEC_MAX_FRAME_SIZE 9600 67 68 #define DTSEC_REG_MAXFRM 0x110 69 #define DTSEC_REG_IGADDR(i) (0x080 + 4 * (i)) 70 #define DTSEC_REG_GADDR(i) (0x0a0 + 4 * (i)) 71 72 #define DTSEC_ECNTRL 0x014 73 #define ECNTRL_R100M 0x00000008 74 #define DTSEC_TCTRL 0x040 75 #define TCTRL_GTS 0x00000020 76 #define DTSEC_RCTRL 0x050 77 #define RCTRL_CFA 0x00008000 78 #define RCTRL_GHTX 0x00000400 79 #define RCTRL_GRS 0x00000020 80 #define RCTRL_MPROM 0x00000008 81 #define DTSEC_MACCFG1 0x100 82 #define DTSEC_MACCFG2 0x104 83 #define MACCFG_IF_M 0x00000300 84 #define MACCFG_IF_10_100 0x00000100 85 #define MACCFG_IF_1G 0x00000200 86 #define MACCFG_FULLDUPLEX 0x00000001 87 #define DTSEC_MACSTNADDR1 0x140 88 #define DTSEC_MACSTNADDR2 0x144 89 90 static void dtsec_if_init_locked(struct dtsec_softc *sc); 91 92 /** 93 * @group FMan MAC routines. 94 * @{ 95 */ 96 97 static int 98 dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac) 99 { 100 FMAN_GET_REVISION(device_get_parent(sc->sc_base.sc_dev), &sc->sc_base.sc_rev_major, 101 &sc->sc_base.sc_rev_minor); 102 103 if (FMAN_RESET_MAC(device_get_parent(sc->sc_base.sc_dev), sc->sc_base.sc_eth_id) != 0) 104 return (ENXIO); 105 106 return (0); 107 } 108 /** @} */ 109 110 111 /** 112 * @group IFnet routines. 113 * @{ 114 */ 115 static int 116 dtsec_set_mtu(struct dtsec_softc *sc, unsigned int mtu) 117 { 118 119 mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN; 120 121 DTSEC_LOCK_ASSERT(sc); 122 123 if (mtu >= DTSEC_MIN_FRAME_SIZE && mtu <= DTSEC_MAX_FRAME_SIZE) { 124 bus_write_4(sc->sc_base.sc_mem, DTSEC_REG_MAXFRM, mtu); 125 return (mtu); 126 } 127 128 return (0); 129 } 130 131 static u_int 132 dtsec_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) 133 { 134 uint32_t h, *hashtable = arg; 135 136 h = (ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 24) & 0xFF; 137 hashtable[(h >> 5)] |= 1 << (0x1F - (h & 0x1F)); 138 139 return (1); 140 } 141 142 static void 143 dtsec_setup_multicast(struct dtsec_softc *sc) 144 { 145 uint32_t hashtable[8] = {}; 146 int i; 147 148 if (if_getflags(sc->sc_base.sc_ifnet) & IFF_ALLMULTI) { 149 for (i = 0; i < 8; i++) 150 bus_write_4(sc->sc_base.sc_mem, DTSEC_REG_GADDR(i), 0xFFFFFFFF); 151 bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL, 152 bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) | RCTRL_MPROM); 153 154 return; 155 } 156 bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL, 157 bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) & ~RCTRL_MPROM); 158 159 if_foreach_llmaddr(sc->sc_base.sc_ifnet, dtsec_hash_maddr, hashtable); 160 for (i = 0; i < 8; i++) 161 bus_write_4(sc->sc_base.sc_mem, DTSEC_REG_GADDR(i), 162 hashtable[i]); 163 } 164 165 static void 166 dtsec_if_graceful_stop(struct dtsec_softc *sc) 167 { 168 bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL, 169 bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) | RCTRL_GRS); 170 if (sc->sc_base.sc_rev_major == 2) 171 DELAY(100); 172 else 173 DELAY(10); 174 175 bus_write_4(sc->sc_base.sc_mem, DTSEC_TCTRL, 176 bus_read_4(sc->sc_base.sc_mem, DTSEC_TCTRL) | TCTRL_GTS); 177 } 178 179 static void 180 dtsec_if_graceful_start(struct dtsec_softc *sc) 181 { 182 bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL, 183 bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) & ~RCTRL_GRS); 184 if (sc->sc_base.sc_rev_major == 2) 185 DELAY(100); 186 else 187 DELAY(10); 188 189 bus_write_4(sc->sc_base.sc_mem, DTSEC_TCTRL, 190 bus_read_4(sc->sc_base.sc_mem, DTSEC_TCTRL) & ~TCTRL_GTS); 191 } 192 193 static int 194 dtsec_if_enable_locked(struct dtsec_softc *sc) 195 { 196 int error; 197 198 DTSEC_LOCK_ASSERT(sc); 199 200 dtsec_if_graceful_start(sc); 201 202 error = FMAN_PORT_ENABLE(sc->sc_base.sc_rx_port); 203 if (error != 0) 204 return (EIO); 205 206 error = FMAN_PORT_ENABLE(sc->sc_base.sc_tx_port); 207 if (error != 0) 208 return (EIO); 209 210 dtsec_setup_multicast(sc); 211 212 if_setdrvflagbits(sc->sc_base.sc_ifnet, IFF_DRV_RUNNING, 0); 213 214 /* Refresh link state */ 215 dtsec_miibus_statchg(sc->sc_base.sc_dev); 216 217 return (0); 218 } 219 220 static int 221 dtsec_if_disable_locked(struct dtsec_softc *sc) 222 { 223 int error; 224 225 DTSEC_LOCK_ASSERT(sc); 226 227 dtsec_if_graceful_stop(sc); 228 229 error = FMAN_PORT_DISABLE(sc->sc_base.sc_rx_port); 230 if (error != 0) 231 return (EIO); 232 233 error = FMAN_PORT_DISABLE(sc->sc_base.sc_tx_port); 234 if (error != 0) 235 return (EIO); 236 237 if_setdrvflagbits(sc->sc_base.sc_ifnet, 0, IFF_DRV_RUNNING); 238 239 return (0); 240 } 241 242 static int 243 dtsec_if_ioctl(if_t ifp, u_long command, caddr_t data) 244 { 245 struct dtsec_softc *sc; 246 struct ifreq *ifr; 247 int error; 248 249 sc = if_getsoftc(ifp); 250 ifr = (struct ifreq *)data; 251 error = 0; 252 253 /* Basic functionality to achieve media status reports */ 254 switch (command) { 255 case SIOCSIFMTU: 256 DTSEC_LOCK(sc); 257 if (dtsec_set_mtu(sc, ifr->ifr_mtu)) 258 if_setmtu(ifp, ifr->ifr_mtu); 259 else 260 error = EINVAL; 261 DTSEC_UNLOCK(sc); 262 break; 263 case SIOCSIFFLAGS: 264 DTSEC_LOCK(sc); 265 266 if (if_getflags(ifp) & IFF_UP) { 267 if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) 268 dtsec_if_init_locked(sc); 269 } else 270 error = dtsec_if_disable_locked(sc); 271 272 DTSEC_UNLOCK(sc); 273 break; 274 275 case SIOCGIFMEDIA: 276 case SIOCSIFMEDIA: 277 error = ifmedia_ioctl(ifp, ifr, &sc->sc_base.sc_mii->mii_media, 278 command); 279 break; 280 281 default: 282 error = ether_ioctl(ifp, command, data); 283 } 284 285 return (error); 286 } 287 288 static void 289 dtsec_if_tick(void *arg) 290 { 291 struct dtsec_softc *sc; 292 293 sc = arg; 294 295 /* TODO */ 296 DTSEC_LOCK(sc); 297 298 mii_tick(sc->sc_base.sc_mii); 299 callout_reset(&sc->sc_base.sc_tick_callout, hz, dtsec_if_tick, sc); 300 301 DTSEC_UNLOCK(sc); 302 } 303 304 static void 305 dtsec_if_deinit_locked(struct dtsec_softc *sc) 306 { 307 308 DTSEC_LOCK_ASSERT(sc); 309 310 DTSEC_UNLOCK(sc); 311 callout_drain(&sc->sc_base.sc_tick_callout); 312 DTSEC_LOCK(sc); 313 } 314 315 static void 316 dtsec_if_set_macaddr(struct dtsec_softc *sc, const char *addr) 317 { 318 uint32_t reg; 319 320 reg = (addr[5] << 24) | (addr[4] << 16) | (addr[3] << 8) | addr[2]; 321 bus_write_4(sc->sc_base.sc_mem, DTSEC_MACSTNADDR1, reg); 322 reg = (addr[1] << 24) | (addr[0] << 16); 323 bus_write_4(sc->sc_base.sc_mem, DTSEC_MACSTNADDR2, reg); 324 } 325 326 static void 327 dtsec_if_init_locked(struct dtsec_softc *sc) 328 { 329 int error; 330 const char *macaddr; 331 332 DTSEC_LOCK_ASSERT(sc); 333 334 macaddr = if_getlladdr(sc->sc_base.sc_ifnet); 335 dtsec_if_set_macaddr(sc, macaddr); 336 337 /* Start MII polling */ 338 if (sc->sc_base.sc_mii) 339 callout_reset(&sc->sc_base.sc_tick_callout, hz, 340 dtsec_if_tick, sc); 341 342 if (if_getflags(sc->sc_base.sc_ifnet) & IFF_UP) { 343 error = dtsec_if_enable_locked(sc); 344 if (error != 0) 345 goto err; 346 } else { 347 error = dtsec_if_disable_locked(sc); 348 if (error != 0) 349 goto err; 350 } 351 352 return; 353 354 err: 355 dtsec_if_deinit_locked(sc); 356 device_printf(sc->sc_base.sc_dev, "initialization error.\n"); 357 return; 358 } 359 360 static void 361 dtsec_if_init(void *data) 362 { 363 struct dtsec_softc *sc; 364 365 sc = data; 366 367 DTSEC_LOCK(sc); 368 dtsec_if_init_locked(sc); 369 DTSEC_UNLOCK(sc); 370 } 371 372 static void 373 dtsec_if_start(if_t ifp) 374 { 375 struct dtsec_softc *sc; 376 377 sc = if_getsoftc(ifp); 378 DTSEC_LOCK(sc); 379 dpaa_eth_if_start_locked(&sc->sc_base); 380 DTSEC_UNLOCK(sc); 381 } 382 383 static void 384 dtsec_if_watchdog(if_t ifp) 385 { 386 /* TODO */ 387 } 388 /** @} */ 389 390 391 /** 392 * @group IFmedia routines. 393 * @{ 394 */ 395 static int 396 dtsec_ifmedia_upd(if_t ifp) 397 { 398 struct dtsec_softc *sc = if_getsoftc(ifp); 399 400 DTSEC_LOCK(sc); 401 mii_mediachg(sc->sc_base.sc_mii); 402 DTSEC_UNLOCK(sc); 403 404 return (0); 405 } 406 407 static void 408 dtsec_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) 409 { 410 struct dtsec_softc *sc = if_getsoftc(ifp); 411 412 DTSEC_LOCK(sc); 413 414 mii_pollstat(sc->sc_base.sc_mii); 415 416 ifmr->ifm_active = sc->sc_base.sc_mii->mii_media_active; 417 ifmr->ifm_status = sc->sc_base.sc_mii->mii_media_status; 418 419 DTSEC_UNLOCK(sc); 420 } 421 /** @} */ 422 423 424 /** 425 * @group dTSEC bus interface. 426 * @{ 427 */ 428 429 int 430 dtsec_attach(device_t dev) 431 { 432 struct dtsec_softc *sc; 433 cell_t ports[2]; 434 phandle_t node; 435 int error; 436 if_t ifp; 437 438 sc = device_get_softc(dev); 439 440 sc->sc_base.sc_dev = dev; 441 node = ofw_bus_get_node(dev); 442 443 /* Init locks */ 444 mtx_init(&sc->sc_base.sc_lock, device_get_nameunit(dev), 445 "DTSEC Global Lock", MTX_DEF); 446 447 mtx_init(&sc->sc_base.sc_mii_lock, device_get_nameunit(dev), 448 "DTSEC MII Lock", MTX_DEF); 449 450 /* Init callouts */ 451 callout_init(&sc->sc_base.sc_tick_callout, CALLOUT_MPSAFE); 452 453 /* Create RX buffer pool */ 454 error = dpaa_eth_pool_rx_init(&sc->sc_base); 455 if (error != 0) 456 return (EIO); 457 458 /* Create RX frame queue range */ 459 error = dpaa_eth_fq_rx_init(&sc->sc_base); 460 if (error != 0) 461 return (EIO); 462 463 /* Create frame info pool */ 464 error = dpaa_eth_fi_pool_init(&sc->sc_base); 465 if (error != 0) 466 return (EIO); 467 468 /* Create TX frame queue range */ 469 error = dpaa_eth_fq_tx_init(&sc->sc_base); 470 if (error != 0) 471 return (EIO); 472 473 if (OF_getencprop(node, "fsl,fman-ports", ports, sizeof(ports)) < 0) { 474 device_printf(dev, "missing ports in device tree\n"); 475 return (ENXIO); 476 } 477 /* Init FMan MAC module. */ 478 error = dtsec_fm_mac_init(sc, sc->sc_base.sc_mac_addr); 479 if (error != 0) { 480 dtsec_detach(dev); 481 return (ENXIO); 482 } 483 484 sc->sc_base.sc_rx_port = OF_device_from_xref(ports[0]); 485 sc->sc_base.sc_tx_port = OF_device_from_xref(ports[1]); 486 dpaa_eth_fm_port_rx_init(&sc->sc_base); 487 dpaa_eth_fm_port_tx_init(&sc->sc_base); 488 489 if (sc->sc_base.sc_rx_port == NULL || sc->sc_base.sc_tx_port == NULL) { 490 device_printf(dev, "invalid ports"); 491 dtsec_detach(dev); 492 return (ENXIO); 493 } 494 495 /* Create network interface for upper layers */ 496 ifp = sc->sc_base.sc_ifnet = if_alloc(IFT_ETHER); 497 if_setsoftc(ifp, sc); 498 499 if_setflags(ifp, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST); 500 if_setinitfn(ifp, dtsec_if_init); 501 if_setstartfn(ifp, dtsec_if_start); 502 if_setioctlfn(ifp, dtsec_if_ioctl); 503 if_setsendqlen(ifp, IFQ_MAXLEN); 504 505 if (sc->sc_base.sc_phy_addr >= 0) 506 if_initname(ifp, device_get_name(sc->sc_base.sc_dev), 507 device_get_unit(sc->sc_base.sc_dev)); 508 else 509 if_initname(ifp, "dtsec_phy", 510 device_get_unit(sc->sc_base.sc_dev)); 511 512 /* TODO */ 513 #if 0 514 if_setsendqlen(ifp, TSEC_TX_NUM_DESC - 1); 515 if_setsendqready(ifp); 516 #endif 517 518 if_setcapabilities(ifp, IFCAP_JUMBO_MTU | IFCAP_VLAN_MTU); 519 if_setcapenable(ifp, if_getcapabilities(ifp)); 520 521 /* Attach PHY(s) */ 522 error = mii_attach(sc->sc_base.sc_dev, &sc->sc_base.sc_mii_dev, 523 ifp, dtsec_ifmedia_upd, dtsec_ifmedia_sts, BMSR_DEFCAPMASK, 524 sc->sc_base.sc_phy_addr, MII_OFFSET_ANY, 0); 525 if (error) { 526 device_printf(sc->sc_base.sc_dev, 527 "attaching PHYs failed: %d\n", error); 528 dtsec_detach(sc->sc_base.sc_dev); 529 return (error); 530 } 531 532 /* Attach to stack */ 533 ether_ifattach(ifp, sc->sc_base.sc_mac_addr); 534 535 return (0); 536 } 537 538 int 539 dtsec_detach(device_t dev) 540 { 541 struct dtsec_softc *sc; 542 if_t ifp; 543 544 sc = device_get_softc(dev); 545 ifp = sc->sc_base.sc_ifnet; 546 547 if (device_is_attached(dev)) { 548 ether_ifdetach(ifp); 549 /* Shutdown interface */ 550 DTSEC_LOCK(sc); 551 dtsec_if_deinit_locked(sc); 552 DTSEC_UNLOCK(sc); 553 } 554 555 if (sc->sc_base.sc_ifnet) { 556 if_free(sc->sc_base.sc_ifnet); 557 sc->sc_base.sc_ifnet = NULL; 558 } 559 560 /* Free RX/TX FQRs */ 561 dpaa_eth_fq_rx_free(&sc->sc_base); 562 dpaa_eth_fq_tx_free(&sc->sc_base); 563 564 /* Free frame info pool */ 565 dpaa_eth_fi_pool_free(&sc->sc_base); 566 567 /* Free RX buffer pool */ 568 dpaa_eth_pool_rx_free(&sc->sc_base); 569 570 /* Destroy lock */ 571 mtx_destroy(&sc->sc_base.sc_lock); 572 573 return (0); 574 } 575 576 int 577 dtsec_suspend(device_t dev) 578 { 579 580 return (0); 581 } 582 583 int 584 dtsec_resume(device_t dev) 585 { 586 587 return (0); 588 } 589 590 int 591 dtsec_shutdown(device_t dev) 592 { 593 594 return (0); 595 } 596 /** @} */ 597 598 599 /** 600 * @group MII bus interface. 601 * @{ 602 */ 603 int 604 dtsec_miibus_readreg(device_t dev, int phy, int reg) 605 { 606 struct dtsec_softc *sc; 607 608 sc = device_get_softc(dev); 609 610 return (MIIBUS_READREG(sc->sc_base.sc_mdio, phy, reg)); 611 } 612 613 int 614 dtsec_miibus_writereg(device_t dev, int phy, int reg, int value) 615 { 616 617 struct dtsec_softc *sc; 618 619 sc = device_get_softc(dev); 620 621 return (MIIBUS_WRITEREG(sc->sc_base.sc_mdio, phy, reg, value)); 622 } 623 624 void 625 dtsec_miibus_statchg(device_t dev) 626 { 627 struct dtsec_softc *sc; 628 uint32_t reg; 629 bool duplex; 630 int speed; 631 632 sc = device_get_softc(dev); 633 634 DTSEC_LOCK_ASSERT(sc); 635 636 duplex = ((sc->sc_base.sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX); 637 638 switch (IFM_SUBTYPE(sc->sc_base.sc_mii->mii_media_active)) { 639 case IFM_1000_T: 640 case IFM_1000_SX: 641 if (!duplex) { 642 device_printf(sc->sc_base.sc_dev, 643 "Only full-duplex supported for 1Gbps speeds"); 644 return; 645 } 646 speed = MACCFG_IF_1G; 647 break; 648 649 default: 650 speed = MACCFG_IF_10_100; 651 } 652 653 reg = bus_read_4(sc->sc_base.sc_mem, DTSEC_MACCFG2); 654 reg &= ~(MACCFG_IF_M | MACCFG_FULLDUPLEX); 655 656 if (duplex) 657 reg |= MACCFG_FULLDUPLEX; 658 reg |= speed; 659 bus_write_4(sc->sc_base.sc_mem, DTSEC_MACCFG2, reg); 660 661 reg = bus_read_4(sc->sc_base.sc_mem, DTSEC_ECNTRL) & ~ECNTRL_R100M; 662 if (IFM_SUBTYPE(sc->sc_base.sc_mii->mii_media_active) == IFM_100_TX) 663 reg |= ECNTRL_R100M; 664 bus_write_4(sc->sc_base.sc_mem, DTSEC_ECNTRL, reg); 665 } 666 /** @} */ 667