1 /*- 2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 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 /* 28 * TI 3 Port Switch Ethernet (CPSW) Driver 29 * Found in TI8148, AM335x SoCs 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/endian.h> 38 #include <sys/mbuf.h> 39 #include <sys/lock.h> 40 #include <sys/mutex.h> 41 #include <sys/kernel.h> 42 #include <sys/module.h> 43 #include <sys/socket.h> 44 #include <sys/sysctl.h> 45 46 #include <net/ethernet.h> 47 #include <net/bpf.h> 48 #include <net/if.h> 49 #include <net/if_arp.h> 50 #include <net/if_dl.h> 51 #include <net/if_media.h> 52 #include <net/if_types.h> 53 #include <net/if_vlan_var.h> 54 55 #include <netinet/in_systm.h> 56 #include <netinet/in.h> 57 #include <netinet/ip.h> 58 59 #include <sys/sockio.h> 60 #include <sys/bus.h> 61 #include <machine/bus.h> 62 #include <sys/rman.h> 63 #include <machine/resource.h> 64 65 #include <dev/mii/mii.h> 66 #include <dev/mii/miivar.h> 67 68 #include <dev/fdt/fdt_common.h> 69 #include <dev/ofw/ofw_bus.h> 70 #include <dev/ofw/ofw_bus_subr.h> 71 72 #include <arm/ti/cpsw/if_cpswreg.h> 73 #include <arm/ti/cpsw/if_cpswvar.h> 74 75 #include <arm/ti/ti_scm.h> 76 77 #include "miibus_if.h" 78 79 static int cpsw_probe(device_t dev); 80 static int cpsw_attach(device_t dev); 81 static int cpsw_detach(device_t dev); 82 static int cpsw_shutdown(device_t dev); 83 static int cpsw_suspend(device_t dev); 84 static int cpsw_resume(device_t dev); 85 86 static int cpsw_miibus_readreg(device_t dev, int phy, int reg); 87 static int cpsw_miibus_writereg(device_t dev, int phy, int reg, int value); 88 89 static int cpsw_ifmedia_upd(struct ifnet *ifp); 90 static void cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 91 92 static void cpsw_init(void *arg); 93 static void cpsw_init_locked(void *arg); 94 static void cpsw_start(struct ifnet *ifp); 95 static void cpsw_start_locked(struct ifnet *ifp); 96 static void cpsw_stop(struct cpsw_softc *sc); 97 static int cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data); 98 static int cpsw_allocate_dma(struct cpsw_softc *sc); 99 static int cpsw_free_dma(struct cpsw_softc *sc); 100 static int cpsw_new_rxbuf(struct cpsw_softc *sc, uint32_t i, uint32_t next); 101 static void cpsw_watchdog(struct cpsw_softc *sc); 102 103 static void cpsw_intr_rx_thresh(void *arg); 104 static void cpsw_intr_rx(void *arg); 105 static void cpsw_intr_rx_locked(void *arg); 106 static void cpsw_intr_tx(void *arg); 107 static void cpsw_intr_tx_locked(void *arg); 108 static void cpsw_intr_misc(void *arg); 109 110 static void cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry); 111 static void cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry); 112 static int cpsw_ale_uc_entry_set(struct cpsw_softc *sc, uint8_t port, uint8_t *mac); 113 static int cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac); 114 #ifdef CPSW_DEBUG 115 static void cpsw_ale_dump_table(struct cpsw_softc *sc); 116 #endif 117 118 static device_method_t cpsw_methods[] = { 119 /* Device interface */ 120 DEVMETHOD(device_probe, cpsw_probe), 121 DEVMETHOD(device_attach, cpsw_attach), 122 DEVMETHOD(device_detach, cpsw_detach), 123 DEVMETHOD(device_shutdown, cpsw_shutdown), 124 DEVMETHOD(device_suspend, cpsw_suspend), 125 DEVMETHOD(device_resume, cpsw_resume), 126 /* MII interface */ 127 DEVMETHOD(miibus_readreg, cpsw_miibus_readreg), 128 DEVMETHOD(miibus_writereg, cpsw_miibus_writereg), 129 { 0, 0 } 130 }; 131 132 static driver_t cpsw_driver = { 133 "cpsw", 134 cpsw_methods, 135 sizeof(struct cpsw_softc), 136 }; 137 138 static devclass_t cpsw_devclass; 139 140 141 DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0); 142 DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0); 143 MODULE_DEPEND(cpsw, ether, 1, 1, 1); 144 MODULE_DEPEND(cpsw, miibus, 1, 1, 1); 145 146 static struct resource_spec res_spec[] = { 147 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 148 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 149 { SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE }, 150 { SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE }, 151 { SYS_RES_IRQ, 3, RF_ACTIVE | RF_SHAREABLE }, 152 { -1, 0 } 153 }; 154 155 static struct { 156 driver_intr_t *handler; 157 char * description; 158 } cpsw_intrs[CPSW_INTR_COUNT + 1] = { 159 { cpsw_intr_rx_thresh,"CPSW RX threshold interrupt" }, 160 { cpsw_intr_rx, "CPSW RX interrupt" }, 161 { cpsw_intr_tx, "CPSW TX interrupt" }, 162 { cpsw_intr_misc,"CPSW misc interrupt" }, 163 }; 164 165 /* Locking macros */ 166 #define CPSW_TX_LOCK(sc) do { \ 167 mtx_assert(&(sc)->rx_lock, MA_NOTOWNED); \ 168 mtx_lock(&(sc)->tx_lock); \ 169 } while (0) 170 171 #define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx_lock) 172 #define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx_lock, MA_OWNED) 173 174 #define CPSW_RX_LOCK(sc) do { \ 175 mtx_assert(&(sc)->tx_lock, MA_NOTOWNED); \ 176 mtx_lock(&(sc)->rx_lock); \ 177 } while (0) 178 179 #define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx_lock) 180 #define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx_lock, MA_OWNED) 181 182 #define CPSW_GLOBAL_LOCK(sc) do { \ 183 if ((mtx_owned(&(sc)->tx_lock) ? 1 : 0) != \ 184 (mtx_owned(&(sc)->rx_lock) ? 1 : 0)) { \ 185 panic("cpsw deadlock possibility detection!"); \ 186 } \ 187 mtx_lock(&(sc)->tx_lock); \ 188 mtx_lock(&(sc)->rx_lock); \ 189 } while (0) 190 191 #define CPSW_GLOBAL_UNLOCK(sc) do { \ 192 CPSW_RX_UNLOCK(sc); \ 193 CPSW_TX_UNLOCK(sc); \ 194 } while (0) 195 196 #define CPSW_GLOBAL_LOCK_ASSERT(sc) do { \ 197 CPSW_TX_LOCK_ASSERT(sc); \ 198 CPSW_RX_LOCK_ASSERT(sc); \ 199 } while (0) 200 201 202 static int 203 cpsw_probe(device_t dev) 204 { 205 206 if (!ofw_bus_is_compatible(dev, "ti,cpsw")) 207 return (ENXIO); 208 209 device_set_desc(dev, "3-port Switch Ethernet Subsystem"); 210 return (BUS_PROBE_DEFAULT); 211 } 212 213 static int 214 cpsw_attach(device_t dev) 215 { 216 struct cpsw_softc *sc; 217 struct mii_softc *miisc; 218 struct ifnet *ifp; 219 int i, error, phy; 220 uint32_t reg; 221 222 sc = device_get_softc(dev); 223 sc->dev = dev; 224 sc->node = ofw_bus_get_node(dev); 225 226 /* Get phy address from fdt */ 227 if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) != 0) { 228 device_printf(dev, "failed to get PHY address from FDT\n"); 229 return (ENXIO); 230 } 231 /* Initialize mutexes */ 232 mtx_init(&sc->tx_lock, device_get_nameunit(dev), 233 "cpsw TX lock", MTX_DEF); 234 mtx_init(&sc->rx_lock, device_get_nameunit(dev), 235 "cpsw RX lock", MTX_DEF); 236 237 /* Allocate IO and IRQ resources */ 238 error = bus_alloc_resources(dev, res_spec, sc->res); 239 if (error) { 240 device_printf(dev, "could not allocate resources\n"); 241 cpsw_detach(dev); 242 return (ENXIO); 243 } 244 245 reg = cpsw_read_4(CPSW_SS_IDVER); 246 device_printf(dev, "Version %d.%d (%d)\n", (reg >> 8 & 0x7), 247 reg & 0xFF, (reg >> 11) & 0x1F); 248 249 /* Allocate DMA, buffers, buffer descriptors */ 250 error = cpsw_allocate_dma(sc); 251 if (error) { 252 cpsw_detach(dev); 253 return (ENXIO); 254 } 255 256 //cpsw_add_sysctls(sc); TODO 257 258 /* Allocate network interface */ 259 ifp = sc->ifp = if_alloc(IFT_ETHER); 260 if (ifp == NULL) { 261 device_printf(dev, "if_alloc() failed\n"); 262 cpsw_detach(dev); 263 return (ENOMEM); 264 } 265 266 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 267 ifp->if_softc = sc; 268 ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST; 269 ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; //FIXME VLAN? 270 ifp->if_capenable = ifp->if_capabilities; 271 272 ifp->if_init = cpsw_init; 273 ifp->if_start = cpsw_start; 274 ifp->if_ioctl = cpsw_ioctl; 275 276 ifp->if_snd.ifq_drv_maxlen = CPSW_MAX_TX_BUFFERS - 1; 277 IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 278 IFQ_SET_READY(&ifp->if_snd); 279 280 /* Get high part of MAC address from control module (mac_id0_hi) */ 281 ti_scm_reg_read_4(0x634, ®); 282 sc->mac_addr[0] = reg & 0xFF; 283 sc->mac_addr[1] = (reg >> 8) & 0xFF; 284 sc->mac_addr[2] = (reg >> 16) & 0xFF; 285 sc->mac_addr[3] = (reg >> 24) & 0xFF; 286 287 /* Get low part of MAC address from control module (mac_id0_lo) */ 288 ti_scm_reg_read_4(0x630, ®); 289 sc->mac_addr[4] = reg & 0xFF; 290 sc->mac_addr[5] = (reg >> 8) & 0xFF; 291 292 ether_ifattach(ifp, sc->mac_addr); 293 callout_init(&sc->wd_callout, 0); 294 295 /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */ 296 /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */ 297 cpsw_write_4(MDIOCONTROL, (1<<30) | (1<<18) | 0xFF); 298 299 /* Attach PHY(s) */ 300 error = mii_attach(dev, &sc->miibus, ifp, cpsw_ifmedia_upd, 301 cpsw_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 302 if (error) { 303 device_printf(dev, "attaching PHYs failed\n"); 304 cpsw_detach(dev); 305 return (error); 306 } 307 sc->mii = device_get_softc(sc->miibus); 308 309 /* Tell the MAC where to find the PHY so autoneg works */ 310 miisc = LIST_FIRST(&sc->mii->mii_phys); 311 312 /* Select PHY and enable interrupts */ 313 cpsw_write_4(MDIOUSERPHYSEL0, (1 << 6) | (miisc->mii_phy & 0x1F)); 314 315 /* Attach interrupt handlers */ 316 for (i = 1; i <= CPSW_INTR_COUNT; ++i) { 317 error = bus_setup_intr(dev, sc->res[i], 318 INTR_TYPE_NET | INTR_MPSAFE, 319 NULL, *cpsw_intrs[i - 1].handler, 320 sc, &sc->ih_cookie[i - 1]); 321 if (error) { 322 device_printf(dev, "could not setup %s\n", 323 cpsw_intrs[i].description); 324 cpsw_detach(dev); 325 return (error); 326 } 327 } 328 329 return (0); 330 } 331 332 static int 333 cpsw_detach(device_t dev) 334 { 335 struct cpsw_softc *sc; 336 int error,i; 337 338 sc = device_get_softc(dev); 339 340 /* Stop controller and free TX queue */ 341 if (sc->ifp) 342 cpsw_shutdown(dev); 343 344 /* Wait for stopping ticks */ 345 callout_drain(&sc->wd_callout); 346 347 /* Stop and release all interrupts */ 348 for (i = 0; i < CPSW_INTR_COUNT; ++i) { 349 if (!sc->ih_cookie[i]) 350 continue; 351 352 error = bus_teardown_intr(dev, sc->res[1 + i], sc->ih_cookie[i]); 353 if (error) 354 device_printf(dev, "could not release %s\n", 355 cpsw_intrs[i + 1].description); 356 } 357 358 /* Detach network interface */ 359 if (sc->ifp) { 360 ether_ifdetach(sc->ifp); 361 if_free(sc->ifp); 362 } 363 364 /* Free DMA resources */ 365 cpsw_free_dma(sc); 366 367 /* Free IO memory handler */ 368 bus_release_resources(dev, res_spec, sc->res); 369 370 /* Destroy mutexes */ 371 mtx_destroy(&sc->rx_lock); 372 mtx_destroy(&sc->tx_lock); 373 374 return (0); 375 } 376 377 static int 378 cpsw_suspend(device_t dev) 379 { 380 381 device_printf(dev, "%s\n", __FUNCTION__); 382 return (0); 383 } 384 385 static int 386 cpsw_resume(device_t dev) 387 { 388 389 device_printf(dev, "%s\n", __FUNCTION__); 390 return (0); 391 } 392 393 static int 394 cpsw_shutdown(device_t dev) 395 { 396 struct cpsw_softc *sc = device_get_softc(dev); 397 398 CPSW_GLOBAL_LOCK(sc); 399 400 cpsw_stop(sc); 401 402 CPSW_GLOBAL_UNLOCK(sc); 403 404 return (0); 405 } 406 407 static int 408 cpsw_miibus_readreg(device_t dev, int phy, int reg) 409 { 410 struct cpsw_softc *sc; 411 uint32_t r; 412 uint32_t retries = CPSW_MIIBUS_RETRIES; 413 414 sc = device_get_softc(dev); 415 416 /* Wait until interface is ready by watching GO bit */ 417 while(--retries && (cpsw_read_4(MDIOUSERACCESS0) & (1 << 31)) ) 418 DELAY(CPSW_MIIBUS_DELAY); 419 if (!retries) 420 device_printf(dev, "Timeout while waiting for MDIO.\n"); 421 422 /* Set GO, phy and reg */ 423 cpsw_write_4(MDIOUSERACCESS0, (1 << 31) | 424 ((reg & 0x1F) << 21) | ((phy & 0x1F) << 16)); 425 426 while(--retries && (cpsw_read_4(MDIOUSERACCESS0) & (1 << 31)) ) 427 DELAY(CPSW_MIIBUS_DELAY); 428 if (!retries) 429 device_printf(dev, "Timeout while waiting for MDIO.\n"); 430 431 r = cpsw_read_4(MDIOUSERACCESS0); 432 /* Check for ACK */ 433 if(r & (1<<29)) { 434 return (r & 0xFFFF); 435 } 436 device_printf(dev, "Failed to read from PHY.\n"); 437 return 0; 438 } 439 440 static int 441 cpsw_miibus_writereg(device_t dev, int phy, int reg, int value) 442 { 443 struct cpsw_softc *sc; 444 uint32_t retries = CPSW_MIIBUS_RETRIES; 445 446 sc = device_get_softc(dev); 447 448 /* Wait until interface is ready by watching GO bit */ 449 while(--retries && (cpsw_read_4(MDIOUSERACCESS0) & (1 << 31)) ) 450 DELAY(CPSW_MIIBUS_DELAY); 451 if (!retries) 452 device_printf(dev, "Timeout while waiting for MDIO.\n"); 453 454 /* Set GO, WRITE, phy, reg and value */ 455 cpsw_write_4(MDIOUSERACCESS0, (value & 0xFFFF) | (3 << 30) | 456 ((reg & 0x1F) << 21) | ((phy & 0x1F) << 16)); 457 458 while(--retries && (cpsw_read_4(MDIOUSERACCESS0) & (1 << 31)) ) 459 DELAY(CPSW_MIIBUS_DELAY); 460 if (!retries) 461 device_printf(dev, "Timeout while waiting for MDIO.\n"); 462 463 /* Check for ACK */ 464 if(cpsw_read_4(MDIOUSERACCESS0) & (1<<29)) { 465 return 0; 466 } 467 device_printf(dev, "Failed to write to PHY.\n"); 468 469 return 0; 470 } 471 472 static int 473 cpsw_allocate_dma(struct cpsw_softc *sc) 474 { 475 int err; 476 int i; 477 478 /* Allocate a busdma tag and DMA safe memory for tx mbufs. */ 479 err = bus_dma_tag_create( 480 bus_get_dma_tag(sc->dev), /* parent */ 481 1, 0, /* alignment, boundary */ 482 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 483 BUS_SPACE_MAXADDR, /* highaddr */ 484 NULL, NULL, /* filtfunc, filtfuncarg */ 485 MCLBYTES, 1, /* maxsize, nsegments */ 486 MCLBYTES, 0, /* maxsegsz, flags */ 487 NULL, NULL, /* lockfunc, lockfuncarg */ 488 &sc->mbuf_dtag); /* dmatag */ 489 490 if (err) 491 return (ENOMEM); 492 for (i = 0; i < CPSW_MAX_TX_BUFFERS; i++) { 493 if ( bus_dmamap_create(sc->mbuf_dtag, 0, &sc->tx_dmamap[i])) { 494 if_printf(sc->ifp, "failed to create dmamap for rx mbuf\n"); 495 return (ENOMEM); 496 } 497 } 498 499 for (i = 0; i < CPSW_MAX_RX_BUFFERS; i++) { 500 if ( bus_dmamap_create(sc->mbuf_dtag, 0, &sc->rx_dmamap[i])) { 501 if_printf(sc->ifp, "failed to create dmamap for rx mbuf\n"); 502 return (ENOMEM); 503 } 504 } 505 506 return (0); 507 } 508 509 static int 510 cpsw_free_dma(struct cpsw_softc *sc) 511 { 512 (void)sc; /* UNUSED */ 513 // TODO 514 return 0; 515 } 516 517 static int 518 cpsw_new_rxbuf(struct cpsw_softc *sc, uint32_t i, uint32_t next) 519 { 520 bus_dma_segment_t seg[1]; 521 struct cpsw_cpdma_bd bd; 522 int error; 523 int nsegs; 524 525 if (sc->rx_mbuf[i]) { 526 bus_dmamap_sync(sc->mbuf_dtag, sc->rx_dmamap[i], BUS_DMASYNC_POSTREAD); 527 bus_dmamap_unload(sc->mbuf_dtag, sc->rx_dmamap[i]); 528 } 529 530 sc->rx_mbuf[i] = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 531 if (sc->rx_mbuf[i] == NULL) 532 return (ENOBUFS); 533 534 sc->rx_mbuf[i]->m_len = sc->rx_mbuf[i]->m_pkthdr.len = sc->rx_mbuf[i]->m_ext.ext_size; 535 536 error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, sc->rx_dmamap[i], 537 sc->rx_mbuf[i], seg, &nsegs, BUS_DMA_NOWAIT); 538 539 KASSERT(nsegs == 1, ("Too many segments returned!")); 540 if (nsegs != 1 || error) 541 panic("%s: nsegs(%d), error(%d)",__func__, nsegs, error); 542 543 bus_dmamap_sync(sc->mbuf_dtag, sc->rx_dmamap[i], BUS_DMASYNC_PREREAD); 544 545 /* Create and submit new rx descriptor*/ 546 bd.next = next; 547 bd.bufptr = seg->ds_addr; 548 bd.buflen = MCLBYTES-1; 549 bd.bufoff = 2; /* make IP hdr aligned with 4 */ 550 bd.pktlen = 0; 551 bd.flags = CPDMA_BD_OWNER; 552 cpsw_cpdma_write_rxbd(i, &bd); 553 554 return (0); 555 } 556 557 558 static int 559 cpsw_encap(struct cpsw_softc *sc, struct mbuf *m0) 560 { 561 bus_dma_segment_t seg[1]; 562 struct cpsw_cpdma_bd bd; 563 int error; 564 int nsegs; 565 int idx; 566 567 if (sc->txbd_queue_size == CPSW_MAX_TX_BUFFERS) 568 return (ENOBUFS); 569 570 idx = sc->txbd_head + sc->txbd_queue_size; 571 572 if (idx >= (CPSW_MAX_TX_BUFFERS) ) 573 idx -= CPSW_MAX_TX_BUFFERS; 574 575 /* Create mapping in DMA memory */ 576 error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, sc->tx_dmamap[idx], m0, seg, &nsegs, 577 BUS_DMA_NOWAIT); 578 sc->tc[idx]++; 579 if (error != 0 || nsegs != 1 ) { 580 bus_dmamap_unload(sc->mbuf_dtag, sc->tx_dmamap[idx]); 581 return ((error != 0) ? error : -1); 582 } 583 bus_dmamap_sync(sc->mbuf_dtag, sc->tx_dmamap[idx], BUS_DMASYNC_PREWRITE); 584 585 /* Fill descriptor data */ 586 bd.next = 0; 587 bd.bufptr = seg->ds_addr; 588 bd.bufoff = 0; 589 bd.buflen = (seg->ds_len < 64 ? 64 : seg->ds_len); 590 bd.pktlen = (seg->ds_len < 64 ? 64 : seg->ds_len); 591 /* Set OWNERSHIP, SOP, EOP */ 592 bd.flags = (7<<13); 593 594 /* Write descriptor */ 595 cpsw_cpdma_write_txbd(idx, &bd); 596 597 /* Previous descriptor should point to us */ 598 cpsw_cpdma_write_txbd_next(((idx-1<0)?(CPSW_MAX_TX_BUFFERS-1):(idx-1)), 599 cpsw_cpdma_txbd_paddr(idx)); 600 601 sc->txbd_queue_size++; 602 603 return (0); 604 } 605 606 static void 607 cpsw_start(struct ifnet *ifp) 608 { 609 struct cpsw_softc *sc = ifp->if_softc; 610 611 CPSW_TX_LOCK(sc); 612 cpsw_start_locked(ifp); 613 CPSW_TX_UNLOCK(sc); 614 } 615 616 static void 617 cpsw_start_locked(struct ifnet *ifp) 618 { 619 struct cpsw_softc *sc = ifp->if_softc; 620 struct mbuf *m0, *mtmp; 621 uint32_t queued = 0; 622 623 CPSW_TX_LOCK_ASSERT(sc); 624 625 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 626 IFF_DRV_RUNNING) 627 return; 628 629 for (;;) { 630 /* Get packet from the queue */ 631 IF_DEQUEUE(&ifp->if_snd, m0); 632 if (m0 == NULL) 633 break; 634 635 mtmp = m_defrag(m0, M_DONTWAIT); 636 if (mtmp) 637 m0 = mtmp; 638 639 if (cpsw_encap(sc, m0)) { 640 IF_PREPEND(&ifp->if_snd, m0); 641 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 642 break; 643 } 644 queued++; 645 BPF_MTAP(ifp, m0); 646 } 647 648 if (!queued) 649 return; 650 651 if (sc->eoq) { 652 cpsw_write_4(CPSW_CPDMA_TX_HDP(0), cpsw_cpdma_txbd_paddr(sc->txbd_head)); 653 sc->eoq = 0; 654 } 655 sc->wd_timer = 5; 656 } 657 658 static void 659 cpsw_stop(struct cpsw_softc *sc) 660 { 661 struct ifnet *ifp; 662 663 ifp = sc->ifp; 664 665 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 666 return; 667 668 /* Stop tick engine */ 669 callout_stop(&sc->wd_callout); 670 671 /* Disable interface */ 672 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 673 sc->wd_timer = 0; 674 675 /* Disable interrupts TODO */ 676 677 } 678 679 static int 680 cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 681 { 682 struct cpsw_softc *sc = ifp->if_softc; 683 struct ifreq *ifr = (struct ifreq *)data; 684 int error; 685 uint32_t flags; 686 687 error = 0; 688 689 // FIXME 690 switch (command) { 691 case SIOCSIFFLAGS: 692 CPSW_GLOBAL_LOCK(sc); 693 if (ifp->if_flags & IFF_UP) { 694 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 695 flags = ifp->if_flags ^ sc->cpsw_if_flags; 696 if (flags & IFF_PROMISC) 697 printf("%s: SIOCSIFFLAGS " 698 "IFF_PROMISC unimplemented\n", 699 __func__); 700 701 if (flags & IFF_ALLMULTI) 702 printf("%s: SIOCSIFFLAGS " 703 "IFF_ALLMULTI unimplemented\n", 704 __func__); 705 } else { 706 printf("%s: SIOCSIFFLAGS cpsw_init_locked\n", __func__); 707 //cpsw_init_locked(sc); 708 } 709 } 710 else if (ifp->if_drv_flags & IFF_DRV_RUNNING) 711 cpsw_stop(sc); 712 713 sc->cpsw_if_flags = ifp->if_flags; 714 CPSW_GLOBAL_UNLOCK(sc); 715 break; 716 printf("%s: SIOCSIFFLAGS\n",__func__); 717 break; 718 case SIOCADDMULTI: 719 printf("%s: SIOCADDMULTI\n",__func__); 720 break; 721 case SIOCDELMULTI: 722 printf("%s: SIOCDELMULTI\n",__func__); 723 break; 724 case SIOCSIFCAP: 725 printf("%s: SIOCSIFCAP\n",__func__); 726 break; 727 case SIOCGIFMEDIA: /* fall through */ 728 printf("%s: SIOCGIFMEDIA\n",__func__); 729 error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command); 730 break; 731 case SIOCSIFMEDIA: 732 printf("%s: SIOCSIFMEDIA\n",__func__); 733 error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command); 734 break; 735 default: 736 error = ether_ioctl(ifp, command, data); 737 } 738 return (error); 739 } 740 741 static void 742 cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 743 { 744 struct cpsw_softc *sc = ifp->if_softc; 745 struct mii_data *mii; 746 747 CPSW_TX_LOCK(sc); 748 749 mii = sc->mii; 750 mii_pollstat(mii); 751 752 ifmr->ifm_active = mii->mii_media_active; 753 ifmr->ifm_status = mii->mii_media_status; 754 755 CPSW_TX_UNLOCK(sc); 756 } 757 758 759 static int 760 cpsw_ifmedia_upd(struct ifnet *ifp) 761 { 762 struct cpsw_softc *sc = ifp->if_softc; 763 764 if (ifp->if_flags & IFF_UP) { 765 CPSW_GLOBAL_LOCK(sc); 766 767 sc->cpsw_media_status = sc->mii->mii_media.ifm_media; 768 mii_mediachg(sc->mii); 769 cpsw_init_locked(sc); 770 771 CPSW_GLOBAL_UNLOCK(sc); 772 } 773 774 return (0); 775 } 776 777 static void 778 cpsw_intr_rx_thresh(void *arg) 779 { 780 (void)arg; /* UNUSED */ 781 } 782 783 static void 784 cpsw_intr_rx(void *arg) 785 { 786 struct cpsw_softc *sc = arg; 787 CPSW_RX_LOCK(sc); 788 cpsw_intr_rx_locked(arg); 789 CPSW_RX_UNLOCK(sc); 790 } 791 792 static void 793 cpsw_intr_rx_locked(void *arg) 794 { 795 struct cpsw_softc *sc = arg; 796 struct cpsw_cpdma_bd bd; 797 struct ifnet *ifp; 798 int i; 799 800 ifp = sc->ifp; 801 802 i = sc->rxbd_head; 803 cpsw_cpdma_read_rxbd(i, &bd); 804 805 while (bd.flags & CPDMA_BD_SOP) { 806 cpsw_write_4(CPSW_CPDMA_RX_CP(0), cpsw_cpdma_rxbd_paddr(i)); 807 808 bus_dmamap_sync(sc->mbuf_dtag, sc->rx_dmamap[i], BUS_DMASYNC_POSTREAD); 809 810 /* Fill mbuf */ 811 sc->rx_mbuf[i]->m_hdr.mh_data +=2; 812 sc->rx_mbuf[i]->m_len = bd.pktlen-2; 813 sc->rx_mbuf[i]->m_pkthdr.len = bd.pktlen-2; 814 sc->rx_mbuf[i]->m_flags |= M_PKTHDR; 815 sc->rx_mbuf[i]->m_pkthdr.rcvif = ifp; 816 817 if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 818 /* check for valid CRC by looking into pkt_err[5:4] */ 819 if ( (bd.flags & CPDMA_BD_PKT_ERR_MASK) == 0 ) { 820 sc->rx_mbuf[i]->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 821 sc->rx_mbuf[i]->m_pkthdr.csum_flags |= CSUM_IP_VALID; 822 sc->rx_mbuf[i]->m_pkthdr.csum_data = 0xffff; 823 } 824 } 825 826 /* Handover packet */ 827 CPSW_RX_UNLOCK(sc); 828 (*ifp->if_input)(ifp, sc->rx_mbuf[i]); 829 CPSW_RX_LOCK(sc); 830 831 /* Allocate new buffer for current descriptor */ 832 cpsw_new_rxbuf(sc, i, 0); 833 834 /* we are not at tail so old tail BD should point to new one */ 835 cpsw_cpdma_write_rxbd_next(sc->rxbd_tail, 836 cpsw_cpdma_rxbd_paddr(i)); 837 838 /* Check if EOQ is reached */ 839 if (cpsw_cpdma_read_rxbd_flags(sc->rxbd_tail) & CPDMA_BD_EOQ) { 840 cpsw_write_4(CPSW_CPDMA_RX_HDP(0), cpsw_cpdma_rxbd_paddr(i)); 841 } 842 sc->rxbd_tail = i; 843 844 /* read next descriptor */ 845 if (++i == CPSW_MAX_RX_BUFFERS) 846 i = 0; 847 cpsw_cpdma_read_rxbd(i, &bd); 848 sc->rxbd_head = i; 849 } 850 851 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1); 852 } 853 854 static void 855 cpsw_intr_tx(void *arg) 856 { 857 struct cpsw_softc *sc = arg; 858 CPSW_TX_LOCK(sc); 859 cpsw_intr_tx_locked(arg); 860 CPSW_TX_UNLOCK(sc); 861 } 862 863 static void 864 cpsw_intr_tx_locked(void *arg) 865 { 866 struct cpsw_softc *sc = arg; 867 uint32_t flags; 868 869 if(sc->txbd_head == -1) 870 return; 871 872 if(sc->txbd_queue_size<1) { 873 /* in some casses interrupt happens even when there is no 874 data in transmit queue */ 875 return; 876 } 877 878 /* Disable watchdog */ 879 sc->wd_timer = 0; 880 881 flags = cpsw_cpdma_read_txbd_flags(sc->txbd_head); 882 883 /* After BD is transmitted CPDMA will set OWNER to 0 */ 884 if (flags & CPDMA_BD_OWNER) 885 return; 886 887 if(flags & CPDMA_BD_EOQ) 888 sc->eoq=1; 889 890 /* release dmamap and mbuf */ 891 bus_dmamap_sync(sc->mbuf_dtag, sc->tx_dmamap[sc->txbd_head], 892 BUS_DMASYNC_POSTWRITE); 893 bus_dmamap_unload(sc->mbuf_dtag, sc->tx_dmamap[sc->txbd_head]); 894 m_freem(sc->tx_mbuf[sc->txbd_head]); 895 896 cpsw_write_4(CPSW_CPDMA_TX_CP(0), cpsw_cpdma_txbd_paddr(sc->txbd_head)); 897 898 if (++sc->txbd_head == CPSW_MAX_TX_BUFFERS) 899 sc->txbd_head = 0; 900 901 --sc->txbd_queue_size; 902 903 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 2); 904 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1); 905 } 906 907 static void 908 cpsw_intr_misc(void *arg) 909 { 910 struct cpsw_softc *sc = arg; 911 uint32_t stat = cpsw_read_4(CPSW_WR_C_MISC_STAT(0)); 912 printf("%s: stat=%x\n",__func__,stat); 913 /* EOI_RX_PULSE */ 914 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 3); 915 } 916 917 static void 918 cpsw_tick(void *msc) 919 { 920 struct cpsw_softc *sc = msc; 921 922 /* Check for TX timeout */ 923 cpsw_watchdog(sc); 924 925 mii_tick(sc->mii); 926 927 /* Check for media type change */ 928 if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) { 929 printf("%s: media type changed (ifm_media=%x)\n",__func__, 930 sc->mii->mii_media.ifm_media); 931 cpsw_ifmedia_upd(sc->ifp); 932 } 933 934 /* Schedule another timeout one second from now */ 935 callout_reset(&sc->wd_callout, hz, cpsw_tick, sc); 936 } 937 938 static void 939 cpsw_watchdog(struct cpsw_softc *sc) 940 { 941 struct ifnet *ifp; 942 943 ifp = sc->ifp; 944 945 CPSW_GLOBAL_LOCK(sc); 946 947 if (sc->wd_timer == 0 || --sc->wd_timer) { 948 CPSW_GLOBAL_UNLOCK(sc); 949 return; 950 } 951 952 ifp->if_oerrors++; 953 if_printf(ifp, "watchdog timeout\n"); 954 955 cpsw_stop(sc); 956 cpsw_init_locked(sc); 957 958 CPSW_GLOBAL_UNLOCK(sc); 959 } 960 961 static void 962 cpsw_init(void *arg) 963 { 964 struct cpsw_softc *sc = arg; 965 CPSW_GLOBAL_LOCK(sc); 966 cpsw_init_locked(arg); 967 CPSW_GLOBAL_UNLOCK(sc); 968 } 969 970 int once = 1; 971 972 static void 973 cpsw_init_locked(void *arg) 974 { 975 struct ifnet *ifp; 976 struct cpsw_softc *sc = arg; 977 uint8_t broadcast_address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 978 uint32_t next_bdp; 979 uint32_t i; 980 981 ifp = sc->ifp; 982 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 983 return; 984 985 printf("%s: start\n",__func__); 986 987 /* Reset writer */ 988 cpsw_write_4(CPSW_WR_SOFT_RESET, 1); 989 while(cpsw_read_4(CPSW_WR_SOFT_RESET) & 1); 990 991 /* Reset SS */ 992 cpsw_write_4(CPSW_SS_SOFT_RESET, 1); 993 while(cpsw_read_4(CPSW_SS_SOFT_RESET) & 1); 994 995 /* Clear table (30) and enable ALE(31) */ 996 if (once) 997 cpsw_write_4(CPSW_ALE_CONTROL, (3 << 30)); 998 else 999 cpsw_write_4(CPSW_ALE_CONTROL, (1 << 31)); 1000 once = 0; // FIXME 1001 1002 /* Reset and init Sliver port 1 and 2 */ 1003 for(i=0;i<2;i++) { 1004 /* Reset */ 1005 cpsw_write_4(CPSW_SL_SOFT_RESET(i), 1); 1006 while(cpsw_read_4(CPSW_SL_SOFT_RESET(i)) & 1); 1007 /* Set Slave Mapping */ 1008 cpsw_write_4(CPSW_SL_RX_PRI_MAP(i),0x76543210); 1009 cpsw_write_4(CPSW_PORT_P_TX_PRI_MAP(i+1),0x33221100); 1010 cpsw_write_4(CPSW_SL_RX_MAXLEN(i),0x5f2); 1011 /* Set MAC Address */ 1012 cpsw_write_4(CPSW_PORT_P_SA_HI(i+1), sc->mac_addr[0] | 1013 (sc->mac_addr[1] << 8) | 1014 (sc->mac_addr[2] << 16) | 1015 (sc->mac_addr[3] << 24)); 1016 cpsw_write_4(CPSW_PORT_P_SA_LO(i+1), sc->mac_addr[4] | 1017 (sc->mac_addr[5] << 8)); 1018 1019 /* Set MACCONTROL for ports 0,1: FULLDUPLEX(1), GMII_EN(5), 1020 IFCTL_A(15), IFCTL_B(16) FIXME */ 1021 cpsw_write_4(CPSW_SL_MACCONTROL(i), 1 | (1<<5) | (1<<15)); 1022 1023 /* Set ALE port to forwarding(3) */ 1024 cpsw_write_4(CPSW_ALE_PORTCTL(i+1), 3); 1025 } 1026 1027 /* Set Host Port Mapping */ 1028 cpsw_write_4(CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210); 1029 cpsw_write_4(CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0); 1030 1031 /* Set ALE port to forwarding(3)*/ 1032 cpsw_write_4(CPSW_ALE_PORTCTL(0), 3); 1033 1034 /* Add own MAC address and broadcast to ALE */ 1035 cpsw_ale_uc_entry_set(sc, 0, sc->mac_addr); 1036 cpsw_ale_mc_entry_set(sc, 7, broadcast_address); 1037 1038 cpsw_write_4(CPSW_SS_PTYPE, 0); 1039 /* Enable statistics for ports 0, 1 and 2 */ 1040 cpsw_write_4(CPSW_SS_STAT_PORT_EN, 7); 1041 1042 /* Reset CPDMA */ 1043 cpsw_write_4(CPSW_CPDMA_SOFT_RESET, 1); 1044 while(cpsw_read_4(CPSW_CPDMA_SOFT_RESET) & 1); 1045 1046 for(i = 0; i < 8; i++) { 1047 cpsw_write_4(CPSW_CPDMA_TX_HDP(i), 0); 1048 cpsw_write_4(CPSW_CPDMA_RX_HDP(i), 0); 1049 cpsw_write_4(CPSW_CPDMA_TX_CP(i), 0); 1050 cpsw_write_4(CPSW_CPDMA_RX_CP(i), 0); 1051 } 1052 1053 cpsw_write_4(CPSW_CPDMA_RX_FREEBUFFER(0), 0); 1054 1055 /* Initialize RX Buffer Descriptors */ 1056 i = CPSW_MAX_RX_BUFFERS; 1057 next_bdp = 0; 1058 while (i--) { 1059 cpsw_new_rxbuf(sc, i, next_bdp); 1060 /* Increment number of free RX buffers */ 1061 //cpsw_write_4(CPSW_CPDMA_RX_FREEBUFFER(0), 1); 1062 next_bdp = cpsw_cpdma_rxbd_paddr(i); 1063 } 1064 1065 sc->rxbd_head = 0; 1066 sc->rxbd_tail = CPSW_MAX_RX_BUFFERS-1; 1067 sc->txbd_head = 0; 1068 sc->eoq = 1; 1069 sc->txbd_queue_size = 0; 1070 1071 /* Make IP hdr aligned with 4 */ 1072 cpsw_write_4(CPSW_CPDMA_RX_BUFFER_OFFSET, 2); 1073 /* Write channel 0 RX HDP */ 1074 cpsw_write_4(CPSW_CPDMA_RX_HDP(0), cpsw_cpdma_rxbd_paddr(0)); 1075 1076 /* Clear all interrupt Masks */ 1077 cpsw_write_4(CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF); 1078 cpsw_write_4(CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF); 1079 1080 /* Enable TX & RX DMA */ 1081 cpsw_write_4(CPSW_CPDMA_TX_CONTROL, 1); 1082 cpsw_write_4(CPSW_CPDMA_RX_CONTROL, 1); 1083 1084 /* Enable TX and RX interrupt receive for core 0 */ 1085 cpsw_write_4(CPSW_WR_C_TX_EN(0), 0xFF); 1086 cpsw_write_4(CPSW_WR_C_RX_EN(0), 0xFF); 1087 //cpsw_write_4(CPSW_WR_C_MISC_EN(0), 0x3F); 1088 1089 /* Enable host Error Interrupt */ 1090 cpsw_write_4(CPSW_CPDMA_DMA_INTMASK_SET, 1); 1091 1092 /* Enable interrupts for TX and RX Channel 0 */ 1093 cpsw_write_4(CPSW_CPDMA_TX_INTMASK_SET, 1); 1094 cpsw_write_4(CPSW_CPDMA_RX_INTMASK_SET, 1); 1095 1096 /* Ack stalled irqs */ 1097 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 0); 1098 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1); 1099 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 2); 1100 cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 3); 1101 1102 /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */ 1103 /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */ 1104 cpsw_write_4(MDIOCONTROL, (1<<30) | (1<<18) | 0xFF); 1105 1106 /* Select MII in GMII_SEL, Internal Delay mode */ 1107 //ti_scm_reg_write_4(0x650, 0); 1108 1109 /* Activate network interface */ 1110 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 1111 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1112 sc->wd_timer = 0; 1113 callout_reset(&sc->wd_callout, hz, cpsw_tick, sc); 1114 } 1115 1116 static void 1117 cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry) 1118 { 1119 cpsw_write_4(CPSW_ALE_TBLCTL, idx & 1023); 1120 ale_entry[0] = cpsw_read_4(CPSW_ALE_TBLW0); 1121 ale_entry[1] = cpsw_read_4(CPSW_ALE_TBLW1); 1122 ale_entry[2] = cpsw_read_4(CPSW_ALE_TBLW2); 1123 } 1124 1125 static void 1126 cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry) 1127 { 1128 cpsw_write_4(CPSW_ALE_TBLW0, ale_entry[0]); 1129 cpsw_write_4(CPSW_ALE_TBLW1, ale_entry[1]); 1130 cpsw_write_4(CPSW_ALE_TBLW2, ale_entry[2]); 1131 cpsw_write_4(CPSW_ALE_TBLCTL, (idx & 1023) | (1 << 31)); 1132 } 1133 1134 static int 1135 cpsw_ale_find_entry_by_mac(struct cpsw_softc *sc, uint8_t *mac) 1136 { 1137 int i; 1138 uint32_t ale_entry[3]; 1139 for(i=0; i< CPSW_MAX_ALE_ENTRIES; i++) { 1140 cpsw_ale_read_entry(sc, i, ale_entry); 1141 if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) && 1142 (((ale_entry[1] >> 0) & 0xFF) == mac[1]) && 1143 (((ale_entry[0] >>24) & 0xFF) == mac[2]) && 1144 (((ale_entry[0] >>16) & 0xFF) == mac[3]) && 1145 (((ale_entry[0] >> 8) & 0xFF) == mac[4]) && 1146 (((ale_entry[0] >> 0) & 0xFF) == mac[5])) { 1147 return (i); 1148 } 1149 } 1150 return CPSW_MAX_ALE_ENTRIES; 1151 } 1152 1153 static int 1154 cpsw_ale_find_free_entry(struct cpsw_softc *sc) 1155 { 1156 int i; 1157 uint32_t ale_entry[3]; 1158 for(i=0; i< CPSW_MAX_ALE_ENTRIES; i++) { 1159 cpsw_ale_read_entry(sc, i, ale_entry); 1160 /* Entry Type[61:60] is 0 for free entry */ 1161 if (((ale_entry[1] >> 28) & 3) == 0) { 1162 return i; 1163 } 1164 } 1165 return CPSW_MAX_ALE_ENTRIES; 1166 } 1167 1168 1169 static int 1170 cpsw_ale_uc_entry_set(struct cpsw_softc *sc, uint8_t port, uint8_t *mac) 1171 { 1172 int i; 1173 uint32_t ale_entry[3]; 1174 1175 if ((i = cpsw_ale_find_entry_by_mac(sc, mac)) == CPSW_MAX_ALE_ENTRIES) { 1176 i = cpsw_ale_find_free_entry(sc); 1177 } 1178 1179 if (i == CPSW_MAX_ALE_ENTRIES) 1180 return (ENOMEM); 1181 1182 /* Set MAC address */ 1183 ale_entry[0] = mac[2]<<24 | mac[3]<<16 | mac[4]<<8 | mac[5]; 1184 ale_entry[1] = mac[0]<<8 | mac[1]; 1185 1186 /* Entry type[61:60] is addr entry(1) */ 1187 ale_entry[1] |= 0x10<<24; 1188 1189 /* Set portmask [67:66] */ 1190 ale_entry[2] = (port & 3) << 2; 1191 1192 cpsw_ale_write_entry(sc, i, ale_entry); 1193 1194 return 0; 1195 } 1196 1197 static int 1198 cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac) 1199 { 1200 int i; 1201 uint32_t ale_entry[3]; 1202 1203 if ((i = cpsw_ale_find_entry_by_mac(sc, mac)) == CPSW_MAX_ALE_ENTRIES) { 1204 i = cpsw_ale_find_free_entry(sc); 1205 } 1206 1207 if (i == CPSW_MAX_ALE_ENTRIES) 1208 return (ENOMEM); 1209 1210 /* Set MAC address */ 1211 ale_entry[0] = mac[2]<<24 | mac[3]<<16 | mac[4]<<8 | mac[5]; 1212 ale_entry[1] = mac[0]<<8 | mac[1]; 1213 1214 /* Entry type[61:60] is addr entry(1), Mcast fwd state[63:62] is fw(3)*/ 1215 ale_entry[1] |= 0xd0<<24; 1216 1217 /* Set portmask [68:66] */ 1218 ale_entry[2] = (portmap & 7) << 2; 1219 1220 cpsw_ale_write_entry(sc, i, ale_entry); 1221 1222 return 0; 1223 } 1224 1225 #ifdef CPSW_DEBUG 1226 static void 1227 cpsw_ale_dump_table(struct cpsw_softc *sc) { 1228 int i; 1229 uint32_t ale_entry[3]; 1230 for(i=0; i< CPSW_MAX_ALE_ENTRIES; i++) { 1231 cpsw_ale_read_entry(sc, i, ale_entry); 1232 if (ale_entry[0] || ale_entry[1] || ale_entry[2]) { 1233 printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[0], 1234 ale_entry[1],ale_entry[2]); 1235 printf("mac: %02x:%02x:%02x:%02x:%02x:%02x ", 1236 (ale_entry[1] >> 8) & 0xFF, 1237 (ale_entry[1] >> 0) & 0xFF, 1238 (ale_entry[0] >>24) & 0xFF, 1239 (ale_entry[0] >>16) & 0xFF, 1240 (ale_entry[0] >> 8) & 0xFF, 1241 (ale_entry[0] >> 0) & 0xFF); 1242 printf( ((ale_entry[1]>>8)&1) ? "mcast " : "ucast "); 1243 printf("type: %u ", (ale_entry[1]>>28)&3); 1244 printf("port: %u ", (ale_entry[2]>>2)&7); 1245 printf("\n"); 1246 } 1247 } 1248 } 1249 #endif 1250