1 /* $OpenBSD: if_cpsw.c,v 1.52 2021/10/24 17:52:27 mpi Exp $ */ 2 /* $NetBSD: if_cpsw.c,v 1.3 2013/04/17 14:36:34 bouyer Exp $ */ 3 4 /* 5 * Copyright (c) 2013 Jonathan A. Kollasch 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /*- 31 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions 36 * are met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce the above copyright 40 * notice, this list of conditions and the following disclaimer in the 41 * documentation and/or other materials provided with the distribution. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 */ 55 56 #include "bpfilter.h" 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/sockio.h> 61 #include <sys/mbuf.h> 62 #include <sys/pool.h> 63 #include <sys/queue.h> 64 #include <sys/device.h> 65 #include <sys/timeout.h> 66 67 #include <machine/bus.h> 68 #include <machine/fdt.h> 69 70 #include <net/if.h> 71 #include <net/if_media.h> 72 73 #include <netinet/in.h> 74 #include <netinet/if_ether.h> 75 76 #if NBPFILTER > 0 77 #include <net/bpf.h> 78 #endif 79 80 #include <dev/mii/miivar.h> 81 82 #include <arch/armv7/omap/if_cpswreg.h> 83 84 #include <dev/ofw/openfirm.h> 85 #include <dev/ofw/ofw_clock.h> 86 #include <dev/ofw/ofw_pinctrl.h> 87 #include <dev/ofw/fdt.h> 88 89 #include <uvm/uvm_extern.h> 90 91 #define CPSW_TXFRAGS 16 92 93 #define OMAP2SCM_MAC_ID0_LO 0x630 94 #define OMAP2SCM_MAC_ID0_HI 0x634 95 96 #define CPSW_CPPI_RAM_SIZE (0x2000) 97 #define CPSW_CPPI_RAM_TXDESCS_SIZE (CPSW_CPPI_RAM_SIZE/2) 98 #define CPSW_CPPI_RAM_RXDESCS_SIZE \ 99 (CPSW_CPPI_RAM_SIZE - CPSW_CPPI_RAM_TXDESCS_SIZE) 100 #define CPSW_CPPI_RAM_TXDESCS_BASE (CPSW_CPPI_RAM_OFFSET + 0x0000) 101 #define CPSW_CPPI_RAM_RXDESCS_BASE \ 102 (CPSW_CPPI_RAM_OFFSET + CPSW_CPPI_RAM_TXDESCS_SIZE) 103 104 #define CPSW_NTXDESCS (CPSW_CPPI_RAM_TXDESCS_SIZE/sizeof(struct cpsw_cpdma_bd)) 105 #define CPSW_NRXDESCS (CPSW_CPPI_RAM_RXDESCS_SIZE/sizeof(struct cpsw_cpdma_bd)) 106 107 #define CPSW_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) 108 109 #define TXDESC_NEXT(x) cpsw_txdesc_adjust((x), 1) 110 #define TXDESC_PREV(x) cpsw_txdesc_adjust((x), -1) 111 112 #define RXDESC_NEXT(x) cpsw_rxdesc_adjust((x), 1) 113 #define RXDESC_PREV(x) cpsw_rxdesc_adjust((x), -1) 114 115 struct cpsw_ring_data { 116 bus_dmamap_t tx_dm[CPSW_NTXDESCS]; 117 struct mbuf *tx_mb[CPSW_NTXDESCS]; 118 bus_dmamap_t rx_dm[CPSW_NRXDESCS]; 119 struct mbuf *rx_mb[CPSW_NRXDESCS]; 120 }; 121 122 struct cpsw_port_config { 123 uint8_t enaddr[ETHER_ADDR_LEN]; 124 int phy_id; 125 int rgmii; 126 int vlan; 127 }; 128 129 struct cpsw_softc { 130 struct device sc_dev; 131 bus_space_tag_t sc_bst; 132 bus_space_handle_t sc_bsh; 133 bus_dma_tag_t sc_bdt; 134 bus_space_handle_t sc_bsh_txdescs; 135 bus_space_handle_t sc_bsh_rxdescs; 136 bus_addr_t sc_txdescs_pa; 137 bus_addr_t sc_rxdescs_pa; 138 139 struct arpcom sc_ac; 140 struct mii_data sc_mii; 141 142 struct cpsw_ring_data *sc_rdp; 143 volatile u_int sc_txnext; 144 volatile u_int sc_txhead; 145 volatile u_int sc_rxhead; 146 147 void *sc_rxthih; 148 void *sc_rxih; 149 void *sc_txih; 150 void *sc_miscih; 151 152 void *sc_txpad; 153 bus_dmamap_t sc_txpad_dm; 154 #define sc_txpad_pa sc_txpad_dm->dm_segs[0].ds_addr 155 156 volatile bool sc_txrun; 157 volatile bool sc_rxrun; 158 volatile bool sc_txeoq; 159 volatile bool sc_rxeoq; 160 struct timeout sc_tick; 161 int sc_active_port; 162 163 struct cpsw_port_config sc_port_config[2]; 164 }; 165 166 #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname) 167 168 int cpsw_match(struct device *, void *, void *); 169 void cpsw_attach(struct device *, struct device *, void *); 170 171 void cpsw_start(struct ifnet *); 172 int cpsw_ioctl(struct ifnet *, u_long, caddr_t); 173 void cpsw_watchdog(struct ifnet *); 174 int cpsw_init(struct ifnet *); 175 void cpsw_stop(struct ifnet *); 176 177 int cpsw_mii_readreg(struct device *, int, int); 178 void cpsw_mii_writereg(struct device *, int, int, int); 179 void cpsw_mii_statchg(struct device *); 180 181 void cpsw_tick(void *); 182 183 int cpsw_new_rxbuf(struct cpsw_softc * const, const u_int); 184 int cpsw_mediachange(struct ifnet *); 185 void cpsw_mediastatus(struct ifnet *, struct ifmediareq *); 186 187 int cpsw_rxthintr(void *); 188 int cpsw_rxintr(void *); 189 int cpsw_txintr(void *); 190 int cpsw_miscintr(void *); 191 192 void cpsw_get_port_config(struct cpsw_port_config *, int); 193 194 const struct cfattach cpsw_ca = { 195 sizeof(struct cpsw_softc), 196 cpsw_match, 197 cpsw_attach 198 }; 199 200 struct cfdriver cpsw_cd = { 201 NULL, 202 "cpsw", 203 DV_IFNET 204 }; 205 206 static inline u_int 207 cpsw_txdesc_adjust(u_int x, int y) 208 { 209 return (((x) + y) & (CPSW_NTXDESCS - 1)); 210 } 211 212 static inline u_int 213 cpsw_rxdesc_adjust(u_int x, int y) 214 { 215 return (((x) + y) & (CPSW_NRXDESCS - 1)); 216 } 217 218 static inline void 219 cpsw_set_txdesc_next(struct cpsw_softc * const sc, const u_int i, uint32_t n) 220 { 221 const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i + 0; 222 bus_space_write_4(sc->sc_bst, sc->sc_bsh_txdescs, o, n); 223 } 224 225 static inline void 226 cpsw_set_rxdesc_next(struct cpsw_softc * const sc, const u_int i, uint32_t n) 227 { 228 const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i + 0; 229 bus_space_write_4(sc->sc_bst, sc->sc_bsh_rxdescs, o, n); 230 } 231 232 static inline void 233 cpsw_get_txdesc(struct cpsw_softc * const sc, const u_int i, 234 struct cpsw_cpdma_bd * const bdp) 235 { 236 const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i; 237 bus_space_read_region_4(sc->sc_bst, sc->sc_bsh_txdescs, o, 238 (uint32_t *)bdp, 4); 239 } 240 241 static inline void 242 cpsw_set_txdesc(struct cpsw_softc * const sc, const u_int i, 243 struct cpsw_cpdma_bd * const bdp) 244 { 245 const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i; 246 bus_space_write_region_4(sc->sc_bst, sc->sc_bsh_txdescs, o, 247 (uint32_t *)bdp, 4); 248 } 249 250 static inline void 251 cpsw_get_rxdesc(struct cpsw_softc * const sc, const u_int i, 252 struct cpsw_cpdma_bd * const bdp) 253 { 254 const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i; 255 bus_space_read_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, o, 256 (uint32_t *)bdp, 4); 257 } 258 259 static inline void 260 cpsw_set_rxdesc(struct cpsw_softc * const sc, const u_int i, 261 struct cpsw_cpdma_bd * const bdp) 262 { 263 const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i; 264 bus_space_write_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, o, 265 (uint32_t *)bdp, 4); 266 } 267 268 static inline bus_addr_t 269 cpsw_txdesc_paddr(struct cpsw_softc * const sc, u_int x) 270 { 271 KASSERT(x < CPSW_NTXDESCS); 272 return sc->sc_txdescs_pa + sizeof(struct cpsw_cpdma_bd) * x; 273 } 274 275 static inline bus_addr_t 276 cpsw_rxdesc_paddr(struct cpsw_softc * const sc, u_int x) 277 { 278 KASSERT(x < CPSW_NRXDESCS); 279 return sc->sc_rxdescs_pa + sizeof(struct cpsw_cpdma_bd) * x; 280 } 281 282 static void 283 cpsw_mdio_init(struct cpsw_softc *sc) 284 { 285 uint32_t alive, link; 286 u_int tries; 287 288 sc->sc_active_port = 0; 289 290 /* Initialize MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */ 291 /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */ 292 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOCONTROL, 293 (1<<30) | (1<<18) | 0xFF); 294 295 for(tries = 0; tries < 1000; tries++) { 296 alive = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOALIVE) & 3; 297 if (alive) 298 break; 299 delay(1); 300 } 301 302 if (alive == 0) { 303 printf("%s: no PHY is alive\n", DEVNAME(sc)); 304 return; 305 } 306 307 link = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOLINK) & 3; 308 309 if (alive == 3) { 310 /* both ports are alive, prefer one with link */ 311 if (link == 2) 312 sc->sc_active_port = 1; 313 } else if (alive == 2) 314 sc->sc_active_port = 1; 315 316 /* Select the port to monitor */ 317 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERPHYSEL0, 318 sc->sc_active_port); 319 } 320 321 int 322 cpsw_match(struct device *parent, void *match, void *aux) 323 { 324 struct fdt_attach_args *faa = aux; 325 326 return OF_is_compatible(faa->fa_node, "ti,cpsw"); 327 } 328 329 void 330 cpsw_attach(struct device *parent, struct device *self, void *aux) 331 { 332 struct cpsw_softc *sc = (struct cpsw_softc *)self; 333 struct fdt_attach_args *faa = aux; 334 struct arpcom * const ac = &sc->sc_ac; 335 struct ifnet * const ifp = &ac->ac_if; 336 void *descs; 337 u_int32_t idver; 338 int error; 339 int node; 340 u_int i; 341 uint32_t memsize; 342 343 if (faa->fa_nreg < 1) 344 return; 345 346 /* 347 * fa_reg[0].size is size of CPSW_SS and CPSW_PORT 348 * fa_reg[1].size is size of CPSW_WR 349 * we map a size that is a superset of both 350 */ 351 memsize = 0x4000; 352 353 pinctrl_byname(faa->fa_node, "default"); 354 355 for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) { 356 if (OF_is_compatible(node, "ti,davinci_mdio")) { 357 clock_enable(node, "fck"); 358 pinctrl_byname(node, "default"); 359 } 360 } 361 362 timeout_set(&sc->sc_tick, cpsw_tick, sc); 363 364 cpsw_get_port_config(sc->sc_port_config, faa->fa_node); 365 memcpy(sc->sc_ac.ac_enaddr, sc->sc_port_config[0].enaddr, 366 ETHER_ADDR_LEN); 367 368 sc->sc_rxthih = arm_intr_establish_fdt_idx(faa->fa_node, 0, IPL_NET, 369 cpsw_rxthintr, sc, DEVNAME(sc)); 370 sc->sc_rxih = arm_intr_establish_fdt_idx(faa->fa_node, 1, IPL_NET, 371 cpsw_rxintr, sc, DEVNAME(sc)); 372 sc->sc_txih = arm_intr_establish_fdt_idx(faa->fa_node, 2, IPL_NET, 373 cpsw_txintr, sc, DEVNAME(sc)); 374 sc->sc_miscih = arm_intr_establish_fdt_idx(faa->fa_node, 3, IPL_NET, 375 cpsw_miscintr, sc, DEVNAME(sc)); 376 377 sc->sc_bst = faa->fa_iot; 378 sc->sc_bdt = faa->fa_dmat; 379 380 error = bus_space_map(sc->sc_bst, faa->fa_reg[0].addr, 381 memsize, BUS_SPACE_MAP_LINEAR, &sc->sc_bsh); 382 if (error) { 383 printf("can't map registers: %d\n", error); 384 return; 385 } 386 387 error = bus_space_subregion(sc->sc_bst, sc->sc_bsh, 388 CPSW_CPPI_RAM_TXDESCS_BASE, CPSW_CPPI_RAM_TXDESCS_SIZE, 389 &sc->sc_bsh_txdescs); 390 if (error) { 391 printf("can't subregion tx ring SRAM: %d\n", error); 392 return; 393 } 394 descs = bus_space_vaddr(sc->sc_bst, sc->sc_bsh_txdescs); 395 pmap_extract(pmap_kernel(), (vaddr_t)descs, &sc->sc_txdescs_pa); 396 397 error = bus_space_subregion(sc->sc_bst, sc->sc_bsh, 398 CPSW_CPPI_RAM_RXDESCS_BASE, CPSW_CPPI_RAM_RXDESCS_SIZE, 399 &sc->sc_bsh_rxdescs); 400 if (error) { 401 printf("can't subregion rx ring SRAM: %d\n", error); 402 return; 403 } 404 descs = bus_space_vaddr(sc->sc_bst, sc->sc_bsh_rxdescs); 405 pmap_extract(pmap_kernel(), (vaddr_t)descs, &sc->sc_rxdescs_pa); 406 407 sc->sc_rdp = malloc(sizeof(*sc->sc_rdp), M_TEMP, M_WAITOK); 408 KASSERT(sc->sc_rdp != NULL); 409 410 for (i = 0; i < CPSW_NTXDESCS; i++) { 411 if ((error = bus_dmamap_create(sc->sc_bdt, MCLBYTES, 412 CPSW_TXFRAGS, MCLBYTES, 0, 0, 413 &sc->sc_rdp->tx_dm[i])) != 0) { 414 printf("unable to create tx DMA map: %d\n", error); 415 } 416 sc->sc_rdp->tx_mb[i] = NULL; 417 } 418 419 for (i = 0; i < CPSW_NRXDESCS; i++) { 420 if ((error = bus_dmamap_create(sc->sc_bdt, MCLBYTES, 1, 421 MCLBYTES, 0, 0, &sc->sc_rdp->rx_dm[i])) != 0) { 422 printf("unable to create rx DMA map: %d\n", error); 423 } 424 sc->sc_rdp->rx_mb[i] = NULL; 425 } 426 427 sc->sc_txpad = dma_alloc(ETHER_MIN_LEN, PR_WAITOK | PR_ZERO); 428 KASSERT(sc->sc_txpad != NULL); 429 bus_dmamap_create(sc->sc_bdt, ETHER_MIN_LEN, 1, ETHER_MIN_LEN, 0, 430 BUS_DMA_WAITOK, &sc->sc_txpad_dm); 431 bus_dmamap_load(sc->sc_bdt, sc->sc_txpad_dm, sc->sc_txpad, 432 ETHER_MIN_LEN, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE); 433 bus_dmamap_sync(sc->sc_bdt, sc->sc_txpad_dm, 0, ETHER_MIN_LEN, 434 BUS_DMASYNC_PREWRITE); 435 436 idver = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_IDVER); 437 printf(": version %d.%d (%d), address %s\n", 438 CPSW_SS_IDVER_MAJ(idver), CPSW_SS_IDVER_MIN(idver), 439 CPSW_SS_IDVER_RTL(idver), ether_sprintf(ac->ac_enaddr)); 440 441 ifp->if_softc = sc; 442 ifp->if_capabilities = IFCAP_VLAN_MTU; 443 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 444 ifp->if_start = cpsw_start; 445 ifp->if_ioctl = cpsw_ioctl; 446 ifp->if_watchdog = cpsw_watchdog; 447 ifq_set_maxlen(&ifp->if_snd, CPSW_NTXDESCS - 1); 448 memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); 449 450 cpsw_stop(ifp); 451 452 sc->sc_mii.mii_ifp = ifp; 453 sc->sc_mii.mii_readreg = cpsw_mii_readreg; 454 sc->sc_mii.mii_writereg = cpsw_mii_writereg; 455 sc->sc_mii.mii_statchg = cpsw_mii_statchg; 456 457 cpsw_mdio_init(sc); 458 459 ifmedia_init(&sc->sc_mii.mii_media, 0, cpsw_mediachange, 460 cpsw_mediastatus); 461 mii_attach(self, &sc->sc_mii, 0xffffffff, 462 sc->sc_port_config[0].phy_id, MII_OFFSET_ANY, 0); 463 if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { 464 printf("no PHY found!\n"); 465 ifmedia_add(&sc->sc_mii.mii_media, 466 IFM_ETHER|IFM_MANUAL, 0, NULL); 467 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL); 468 } else { 469 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); 470 } 471 472 if_attach(ifp); 473 ether_ifattach(ifp); 474 475 return; 476 } 477 478 int 479 cpsw_mediachange(struct ifnet *ifp) 480 { 481 struct cpsw_softc *sc = ifp->if_softc; 482 483 if (LIST_FIRST(&sc->sc_mii.mii_phys)) 484 mii_mediachg(&sc->sc_mii); 485 486 return (0); 487 } 488 489 void 490 cpsw_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 491 { 492 struct cpsw_softc *sc = ifp->if_softc; 493 494 if (LIST_FIRST(&sc->sc_mii.mii_phys)) { 495 mii_pollstat(&sc->sc_mii); 496 ifmr->ifm_active = sc->sc_mii.mii_media_active; 497 ifmr->ifm_status = sc->sc_mii.mii_media_status; 498 } 499 } 500 501 void 502 cpsw_start(struct ifnet *ifp) 503 { 504 struct cpsw_softc * const sc = ifp->if_softc; 505 struct cpsw_ring_data * const rdp = sc->sc_rdp; 506 struct cpsw_cpdma_bd bd; 507 struct mbuf *m; 508 bus_dmamap_t dm; 509 u_int eopi = ~0; 510 u_int seg; 511 u_int txfree; 512 int txstart = -1; 513 int error; 514 bool pad; 515 u_int mlen; 516 517 if (!ISSET(ifp->if_flags, IFF_RUNNING) || 518 ifq_is_oactive(&ifp->if_snd) || 519 ifq_empty(&ifp->if_snd)) 520 return; 521 522 if (sc->sc_txnext >= sc->sc_txhead) 523 txfree = CPSW_NTXDESCS - 1 + sc->sc_txhead - sc->sc_txnext; 524 else 525 txfree = sc->sc_txhead - sc->sc_txnext - 1; 526 527 for (;;) { 528 if (txfree <= CPSW_TXFRAGS) { 529 ifq_set_oactive(&ifp->if_snd); 530 break; 531 } 532 533 m = ifq_dequeue(&ifp->if_snd); 534 if (m == NULL) 535 break; 536 537 dm = rdp->tx_dm[sc->sc_txnext]; 538 error = bus_dmamap_load_mbuf(sc->sc_bdt, dm, m, BUS_DMA_NOWAIT); 539 switch (error) { 540 case 0: 541 break; 542 543 case EFBIG: /* mbuf chain is too fragmented */ 544 if (m_defrag(m, M_DONTWAIT) == 0 && 545 bus_dmamap_load_mbuf(sc->sc_bdt, dm, m, 546 BUS_DMA_NOWAIT) == 0) 547 break; 548 549 /* FALLTHROUGH */ 550 default: 551 m_freem(m); 552 ifp->if_oerrors++; 553 continue; 554 } 555 556 mlen = dm->dm_mapsize; 557 pad = mlen < CPSW_PAD_LEN; 558 559 KASSERT(rdp->tx_mb[sc->sc_txnext] == NULL); 560 rdp->tx_mb[sc->sc_txnext] = m; 561 562 #if NBPFILTER > 0 563 if (ifp->if_bpf) 564 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 565 #endif 566 567 bus_dmamap_sync(sc->sc_bdt, dm, 0, dm->dm_mapsize, 568 BUS_DMASYNC_PREWRITE); 569 570 if (txstart == -1) 571 txstart = sc->sc_txnext; 572 eopi = sc->sc_txnext; 573 for (seg = 0; seg < dm->dm_nsegs; seg++) { 574 bd.next = cpsw_txdesc_paddr(sc, 575 TXDESC_NEXT(sc->sc_txnext)); 576 bd.bufptr = dm->dm_segs[seg].ds_addr; 577 bd.bufoff = 0; 578 bd.buflen = dm->dm_segs[seg].ds_len; 579 bd.pktlen = 0; 580 bd.flags = 0; 581 582 if (seg == 0) { 583 bd.flags = CPDMA_BD_OWNER | CPDMA_BD_SOP; 584 bd.pktlen = MAX(mlen, CPSW_PAD_LEN); 585 } 586 587 if (seg == dm->dm_nsegs - 1 && !pad) 588 bd.flags |= CPDMA_BD_EOP; 589 590 cpsw_set_txdesc(sc, sc->sc_txnext, &bd); 591 txfree--; 592 eopi = sc->sc_txnext; 593 sc->sc_txnext = TXDESC_NEXT(sc->sc_txnext); 594 } 595 if (pad) { 596 bd.next = cpsw_txdesc_paddr(sc, 597 TXDESC_NEXT(sc->sc_txnext)); 598 bd.bufptr = sc->sc_txpad_pa; 599 bd.bufoff = 0; 600 bd.buflen = CPSW_PAD_LEN - mlen; 601 bd.pktlen = 0; 602 bd.flags = CPDMA_BD_EOP; 603 604 cpsw_set_txdesc(sc, sc->sc_txnext, &bd); 605 txfree--; 606 eopi = sc->sc_txnext; 607 sc->sc_txnext = TXDESC_NEXT(sc->sc_txnext); 608 } 609 } 610 611 if (txstart >= 0) { 612 ifp->if_timer = 5; 613 /* terminate the new chain */ 614 KASSERT(eopi == TXDESC_PREV(sc->sc_txnext)); 615 cpsw_set_txdesc_next(sc, TXDESC_PREV(sc->sc_txnext), 0); 616 617 /* link the new chain on */ 618 cpsw_set_txdesc_next(sc, TXDESC_PREV(txstart), 619 cpsw_txdesc_paddr(sc, txstart)); 620 if (sc->sc_txeoq) { 621 /* kick the dma engine */ 622 sc->sc_txeoq = false; 623 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0), 624 cpsw_txdesc_paddr(sc, txstart)); 625 } 626 } 627 } 628 629 int 630 cpsw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 631 { 632 struct cpsw_softc *sc = ifp->if_softc; 633 struct ifreq *ifr = (struct ifreq *)data; 634 int s = splnet(); 635 int error = 0; 636 637 switch (cmd) { 638 case SIOCSIFADDR: 639 ifp->if_flags |= IFF_UP; 640 /* FALLTHROUGH */ 641 case SIOCSIFFLAGS: 642 if (ifp->if_flags & IFF_UP) { 643 if (ifp->if_flags & IFF_RUNNING) 644 error = ENETRESET; 645 else 646 cpsw_init(ifp); 647 } else { 648 if (ifp->if_flags & IFF_RUNNING) 649 cpsw_stop(ifp); 650 } 651 break; 652 case SIOCSIFMEDIA: 653 ifr->ifr_media &= ~IFM_ETH_FMASK; 654 /* FALLTHROUGH */ 655 case SIOCGIFMEDIA: 656 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); 657 break; 658 default: 659 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 660 break; 661 } 662 if (error == ENETRESET) { 663 if (ifp->if_flags & IFF_RUNNING) 664 cpsw_init(ifp); 665 error = 0; 666 } 667 668 splx(s); 669 670 return error; 671 } 672 673 void 674 cpsw_watchdog(struct ifnet *ifp) 675 { 676 printf("%s: device timeout\n", ifp->if_xname); 677 678 ifp->if_oerrors++; 679 cpsw_init(ifp); 680 cpsw_start(ifp); 681 } 682 683 static int 684 cpsw_mii_wait(struct cpsw_softc * const sc, int reg) 685 { 686 u_int tries; 687 688 for(tries = 0; tries < 1000; tries++) { 689 if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg) & (1U << 31)) == 0) 690 return 0; 691 delay(1); 692 } 693 return ETIMEDOUT; 694 } 695 696 int 697 cpsw_mii_readreg(struct device *dev, int phy, int reg) 698 { 699 struct cpsw_softc * const sc = (struct cpsw_softc *)dev; 700 uint32_t v; 701 702 if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0) 703 return 0; 704 705 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0, (1U << 31) | 706 ((reg & 0x1F) << 21) | ((phy & 0x1F) << 16)); 707 708 if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0) 709 return 0; 710 711 v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0); 712 if (v & (1 << 29)) 713 return v & 0xffff; 714 else 715 return 0; 716 } 717 718 void 719 cpsw_mii_writereg(struct device *dev, int phy, int reg, int val) 720 { 721 struct cpsw_softc * const sc = (struct cpsw_softc *)dev; 722 uint32_t v; 723 724 KASSERT((val & 0xffff0000UL) == 0); 725 726 if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0) 727 goto out; 728 729 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0, (1U << 31) | (1 << 30) | 730 ((reg & 0x1F) << 21) | ((phy & 0x1F) << 16) | val); 731 732 if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0) 733 goto out; 734 735 v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0); 736 if ((v & (1 << 29)) == 0) 737 out: 738 printf("%s error\n", __func__); 739 740 } 741 742 void 743 cpsw_mii_statchg(struct device *self) 744 { 745 return; 746 } 747 748 int 749 cpsw_new_rxbuf(struct cpsw_softc * const sc, const u_int i) 750 { 751 struct cpsw_ring_data * const rdp = sc->sc_rdp; 752 const u_int h = RXDESC_PREV(i); 753 struct cpsw_cpdma_bd bd; 754 struct mbuf *m; 755 int error = ENOBUFS; 756 757 MGETHDR(m, M_DONTWAIT, MT_DATA); 758 if (m == NULL) { 759 goto reuse; 760 } 761 762 MCLGET(m, M_DONTWAIT); 763 if ((m->m_flags & M_EXT) == 0) { 764 m_freem(m); 765 goto reuse; 766 } 767 768 /* We have a new buffer, prepare it for the ring. */ 769 770 if (rdp->rx_mb[i] != NULL) 771 bus_dmamap_unload(sc->sc_bdt, rdp->rx_dm[i]); 772 773 m->m_len = m->m_pkthdr.len = MCLBYTES; 774 775 rdp->rx_mb[i] = m; 776 777 error = bus_dmamap_load_mbuf(sc->sc_bdt, rdp->rx_dm[i], rdp->rx_mb[i], 778 BUS_DMA_READ|BUS_DMA_NOWAIT); 779 if (error) { 780 printf("can't load rx DMA map %d: %d\n", i, error); 781 } 782 783 bus_dmamap_sync(sc->sc_bdt, rdp->rx_dm[i], 784 0, rdp->rx_dm[i]->dm_mapsize, BUS_DMASYNC_PREREAD); 785 786 error = 0; 787 788 reuse: 789 /* (re-)setup the descriptor */ 790 bd.next = 0; 791 bd.bufptr = rdp->rx_dm[i]->dm_segs[0].ds_addr; 792 bd.bufoff = 0; 793 bd.buflen = MIN(0x7ff, rdp->rx_dm[i]->dm_segs[0].ds_len); 794 bd.pktlen = 0; 795 bd.flags = CPDMA_BD_OWNER; 796 797 cpsw_set_rxdesc(sc, i, &bd); 798 /* and link onto ring */ 799 cpsw_set_rxdesc_next(sc, h, cpsw_rxdesc_paddr(sc, i)); 800 801 return error; 802 } 803 804 int 805 cpsw_init(struct ifnet *ifp) 806 { 807 struct cpsw_softc * const sc = ifp->if_softc; 808 struct arpcom *ac = &sc->sc_ac; 809 struct mii_data * const mii = &sc->sc_mii; 810 int i; 811 812 cpsw_stop(ifp); 813 814 sc->sc_txnext = 0; 815 sc->sc_txhead = 0; 816 817 /* Reset wrapper */ 818 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET, 1); 819 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET) & 1); 820 821 /* Reset SS */ 822 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET, 1); 823 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET) & 1); 824 825 /* Clear table (30) and enable ALE(31) and set passthrough (4) */ 826 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_CONTROL, (3 << 30) | 0x10); 827 828 /* Reset and init Sliver port 1 and 2 */ 829 for (i = 0; i < 2; i++) { 830 /* Reset */ 831 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i), 1); 832 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i)) & 1); 833 /* Set Slave Mapping */ 834 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_RX_PRI_MAP(i), 0x76543210); 835 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_TX_PRI_MAP(i+1), 0x33221100); 836 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_RX_MAXLEN(i), 0x5f2); 837 /* Set MAC Address */ 838 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_HI(i+1), 839 ac->ac_enaddr[0] | (ac->ac_enaddr[1] << 8) | 840 (ac->ac_enaddr[2] << 16) | (ac->ac_enaddr[3] << 24)); 841 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_LO(i+1), 842 ac->ac_enaddr[4] | (ac->ac_enaddr[5] << 8)); 843 844 /* Set MACCONTROL for ports 0,1: FULLDUPLEX(0), GMII_EN(5), 845 IFCTL_A(15), IFCTL_B(16) FIXME */ 846 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_MACCONTROL(i), 847 1 | (1<<5) | (1<<15) | (1<<16)); 848 849 /* Set ALE port to forwarding(3) on the active port */ 850 if (i == sc->sc_active_port) 851 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(i+1), 3); 852 } 853 854 /* Set Host Port Mapping */ 855 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210); 856 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0); 857 858 /* Set ALE port to forwarding(3) */ 859 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(0), 3); 860 861 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_PTYPE, 0); 862 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_STAT_PORT_EN, 7); 863 864 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET, 1); 865 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET) & 1); 866 867 for (i = 0; i < 8; i++) { 868 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(i), 0); 869 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(i), 0); 870 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(i), 0); 871 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(i), 0); 872 } 873 874 bus_space_set_region_4(sc->sc_bst, sc->sc_bsh_txdescs, 0, 0, 875 CPSW_CPPI_RAM_TXDESCS_SIZE/4); 876 877 sc->sc_txhead = 0; 878 sc->sc_txnext = 0; 879 880 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_FREEBUFFER(0), 0); 881 882 bus_space_set_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, 0, 0, 883 CPSW_CPPI_RAM_RXDESCS_SIZE/4); 884 885 /* Initialize RX Buffer Descriptors */ 886 cpsw_set_rxdesc_next(sc, RXDESC_PREV(0), 0); 887 for (i = 0; i < CPSW_NRXDESCS; i++) { 888 cpsw_new_rxbuf(sc, i); 889 } 890 sc->sc_rxhead = 0; 891 892 /* align layer 3 header to 32-bit */ 893 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_BUFFER_OFFSET, ETHER_ALIGN); 894 895 /* Clear all interrupt Masks */ 896 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF); 897 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF); 898 899 /* Enable TX & RX DMA */ 900 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CONTROL, 1); 901 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CONTROL, 1); 902 903 /* Enable interrupt pacing for C0 RX/TX (IMAX set to max intr/ms allowed) */ 904 #define CPSW_VBUSP_CLK_MHZ 2400 /* hardcoded for BBB */ 905 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_IMAX(0), 2); 906 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_IMAX(0), 2); 907 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_INT_CONTROL, 3 << 16 | CPSW_VBUSP_CLK_MHZ/4); 908 909 /* Enable TX and RX interrupt receive for core 0 */ 910 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_EN(0), 1); 911 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_EN(0), 1); 912 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_EN(0), 0x1F); 913 914 /* Enable host Error Interrupt */ 915 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTMASK_SET, 2); 916 917 /* Enable interrupts for TX and RX Channel 0 */ 918 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_SET, 1); 919 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_SET, 1); 920 921 /* Ack stalled irqs */ 922 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RXTH); 923 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RX); 924 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_TX); 925 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_MISC); 926 927 cpsw_mdio_init(sc); 928 929 mii_mediachg(mii); 930 931 /* Write channel 0 RX HDP */ 932 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0), cpsw_rxdesc_paddr(sc, 0)); 933 sc->sc_rxrun = true; 934 sc->sc_rxeoq = false; 935 936 sc->sc_txrun = true; 937 sc->sc_txeoq = true; 938 939 ifp->if_flags |= IFF_RUNNING; 940 ifq_clr_oactive(&ifp->if_snd); 941 942 timeout_add_sec(&sc->sc_tick, 1); 943 944 return 0; 945 } 946 947 void 948 cpsw_stop(struct ifnet *ifp) 949 { 950 struct cpsw_softc * const sc = ifp->if_softc; 951 struct cpsw_ring_data * const rdp = sc->sc_rdp; 952 u_int i; 953 954 #if 0 955 /* XXX find where disable comes from */ 956 printf("%s: ifp %p disable %d\n", __func__, ifp, disable); 957 #endif 958 if ((ifp->if_flags & IFF_RUNNING) == 0) 959 return; 960 961 timeout_del(&sc->sc_tick); 962 963 mii_down(&sc->sc_mii); 964 965 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_CLEAR, 1); 966 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_CLEAR, 1); 967 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_EN(0), 0x0); 968 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_EN(0), 0x0); 969 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_EN(0), 0x1F); 970 971 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_TEARDOWN, 0); 972 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_TEARDOWN, 0); 973 i = 0; 974 while ((sc->sc_txrun || sc->sc_rxrun) && i < 10000) { 975 delay(10); 976 if ((sc->sc_txrun == true) && cpsw_txintr(sc) == 0) 977 sc->sc_txrun = false; 978 if ((sc->sc_rxrun == true) && cpsw_rxintr(sc) == 0) 979 sc->sc_rxrun = false; 980 i++; 981 } 982 /* printf("%s toredown complete in %u\n", __func__, i); */ 983 984 /* Reset wrapper */ 985 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET, 1); 986 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET) & 1); 987 988 /* Reset SS */ 989 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET, 1); 990 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET) & 1); 991 992 for (i = 0; i < 2; i++) { 993 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i), 1); 994 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i)) & 1); 995 } 996 997 /* Reset CPDMA */ 998 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET, 1); 999 while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET) & 1); 1000 1001 /* Release any queued transmit buffers. */ 1002 for (i = 0; i < CPSW_NTXDESCS; i++) { 1003 bus_dmamap_unload(sc->sc_bdt, rdp->tx_dm[i]); 1004 m_freem(rdp->tx_mb[i]); 1005 rdp->tx_mb[i] = NULL; 1006 } 1007 1008 ifp->if_flags &= ~IFF_RUNNING; 1009 ifp->if_timer = 0; 1010 ifq_clr_oactive(&ifp->if_snd); 1011 1012 /* XXX Not sure what this is doing calling disable here 1013 where is disable set? 1014 */ 1015 #if 0 1016 if (!disable) 1017 return; 1018 #endif 1019 1020 for (i = 0; i < CPSW_NRXDESCS; i++) { 1021 bus_dmamap_unload(sc->sc_bdt, rdp->rx_dm[i]); 1022 m_freem(rdp->rx_mb[i]); 1023 rdp->rx_mb[i] = NULL; 1024 } 1025 } 1026 1027 int 1028 cpsw_rxthintr(void *arg) 1029 { 1030 struct cpsw_softc * const sc = arg; 1031 1032 /* this won't deassert the interrupt though */ 1033 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RXTH); 1034 1035 return 1; 1036 } 1037 1038 int 1039 cpsw_rxintr(void *arg) 1040 { 1041 struct cpsw_softc * const sc = arg; 1042 struct ifnet * const ifp = &sc->sc_ac.ac_if; 1043 struct cpsw_ring_data * const rdp = sc->sc_rdp; 1044 struct cpsw_cpdma_bd bd; 1045 bus_dmamap_t dm; 1046 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 1047 struct mbuf *m; 1048 u_int i; 1049 u_int len, off; 1050 1051 sc->sc_rxeoq = false; 1052 1053 for (;;) { 1054 KASSERT(sc->sc_rxhead < CPSW_NRXDESCS); 1055 1056 i = sc->sc_rxhead; 1057 dm = rdp->rx_dm[i]; 1058 m = rdp->rx_mb[i]; 1059 1060 KASSERT(dm != NULL); 1061 KASSERT(m != NULL); 1062 1063 cpsw_get_rxdesc(sc, i, &bd); 1064 1065 if (bd.flags & CPDMA_BD_OWNER) 1066 break; 1067 1068 if (bd.flags & CPDMA_BD_TDOWNCMPLT) { 1069 sc->sc_rxrun = false; 1070 goto done; 1071 } 1072 1073 bus_dmamap_sync(sc->sc_bdt, dm, 0, dm->dm_mapsize, 1074 BUS_DMASYNC_POSTREAD); 1075 1076 if (cpsw_new_rxbuf(sc, i) != 0) { 1077 /* drop current packet, reuse buffer for new */ 1078 ifp->if_ierrors++; 1079 goto next; 1080 } 1081 1082 if ((bd.flags & (CPDMA_BD_SOP|CPDMA_BD_EOP)) != 1083 (CPDMA_BD_SOP|CPDMA_BD_EOP)) { 1084 if (bd.flags & CPDMA_BD_SOP) { 1085 printf("cpsw: rx packet too large\n"); 1086 ifp->if_ierrors++; 1087 } 1088 m_freem(m); 1089 goto next; 1090 } 1091 1092 off = bd.bufoff; 1093 len = bd.pktlen; 1094 1095 if (bd.flags & CPDMA_BD_PASSCRC) 1096 len -= ETHER_CRC_LEN; 1097 1098 m->m_pkthdr.len = m->m_len = len; 1099 m->m_data += off; 1100 1101 ml_enqueue(&ml, m); 1102 1103 next: 1104 sc->sc_rxhead = RXDESC_NEXT(sc->sc_rxhead); 1105 if (bd.flags & CPDMA_BD_EOQ) { 1106 sc->sc_rxeoq = true; 1107 sc->sc_rxrun = false; 1108 } 1109 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(0), 1110 cpsw_rxdesc_paddr(sc, i)); 1111 } 1112 1113 if (sc->sc_rxeoq) { 1114 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0), 1115 cpsw_rxdesc_paddr(sc, sc->sc_rxhead)); 1116 sc->sc_rxrun = true; 1117 sc->sc_rxeoq = false; 1118 } 1119 1120 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, 1121 CPSW_INTROFF_RX); 1122 1123 done: 1124 if_input(ifp, &ml); 1125 1126 return 1; 1127 } 1128 1129 void 1130 cpsw_tick(void *arg) 1131 { 1132 struct cpsw_softc *sc = arg; 1133 int s; 1134 1135 s = splnet(); 1136 mii_tick(&sc->sc_mii); 1137 splx(s); 1138 1139 timeout_add_sec(&sc->sc_tick, 1); 1140 } 1141 1142 int 1143 cpsw_txintr(void *arg) 1144 { 1145 struct cpsw_softc * const sc = arg; 1146 struct ifnet * const ifp = &sc->sc_ac.ac_if; 1147 struct cpsw_ring_data * const rdp = sc->sc_rdp; 1148 struct cpsw_cpdma_bd bd; 1149 bool handled = false; 1150 uint32_t tx0_cp; 1151 u_int cpi; 1152 1153 KASSERT(sc->sc_txrun); 1154 1155 tx0_cp = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0)); 1156 1157 if (tx0_cp == 0xfffffffc) { 1158 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0), 0xfffffffc); 1159 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0), 0); 1160 sc->sc_txrun = false; 1161 return 0; 1162 } 1163 1164 for (;;) { 1165 tx0_cp = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0)); 1166 cpi = (tx0_cp - sc->sc_txdescs_pa) / 1167 sizeof(struct cpsw_cpdma_bd); 1168 KASSERT(sc->sc_txhead < CPSW_NTXDESCS); 1169 1170 cpsw_get_txdesc(sc, sc->sc_txhead, &bd); 1171 1172 if (bd.buflen == 0) { 1173 /* db_enter(); */ 1174 } 1175 1176 if ((bd.flags & CPDMA_BD_SOP) == 0) 1177 goto next; 1178 1179 if (bd.flags & CPDMA_BD_OWNER) { 1180 printf("pwned %x %x %x\n", cpi, sc->sc_txhead, 1181 sc->sc_txnext); 1182 break; 1183 } 1184 1185 if (bd.flags & CPDMA_BD_TDOWNCMPLT) { 1186 sc->sc_txrun = false; 1187 return 1; 1188 } 1189 1190 bus_dmamap_sync(sc->sc_bdt, rdp->tx_dm[sc->sc_txhead], 1191 0, rdp->tx_dm[sc->sc_txhead]->dm_mapsize, 1192 BUS_DMASYNC_POSTWRITE); 1193 bus_dmamap_unload(sc->sc_bdt, rdp->tx_dm[sc->sc_txhead]); 1194 1195 m_freem(rdp->tx_mb[sc->sc_txhead]); 1196 rdp->tx_mb[sc->sc_txhead] = NULL; 1197 1198 handled = true; 1199 1200 ifq_clr_oactive(&ifp->if_snd); 1201 1202 next: 1203 if ((bd.flags & (CPDMA_BD_EOP|CPDMA_BD_EOQ)) == 1204 (CPDMA_BD_EOP|CPDMA_BD_EOQ)) 1205 sc->sc_txeoq = true; 1206 1207 if (sc->sc_txhead == cpi) { 1208 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0), 1209 cpsw_txdesc_paddr(sc, cpi)); 1210 sc->sc_txhead = TXDESC_NEXT(sc->sc_txhead); 1211 break; 1212 } 1213 sc->sc_txhead = TXDESC_NEXT(sc->sc_txhead); 1214 if (sc->sc_txeoq == true) 1215 break; 1216 } 1217 1218 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_TX); 1219 1220 if ((sc->sc_txnext != sc->sc_txhead) && sc->sc_txeoq) { 1221 if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0)) == 0) { 1222 sc->sc_txeoq = false; 1223 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0), 1224 cpsw_txdesc_paddr(sc, sc->sc_txhead)); 1225 } 1226 } 1227 1228 if (handled && sc->sc_txnext == sc->sc_txhead) 1229 ifp->if_timer = 0; 1230 1231 if (handled) 1232 cpsw_start(ifp); 1233 1234 return handled; 1235 } 1236 1237 int 1238 cpsw_miscintr(void *arg) 1239 { 1240 struct cpsw_softc * const sc = arg; 1241 uint32_t miscstat; 1242 uint32_t dmastat; 1243 uint32_t stat; 1244 1245 miscstat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_STAT(0)); 1246 printf("%s %x FIRE\n", __func__, miscstat); 1247 1248 if (miscstat & CPSW_MISC_HOST_PEND) { 1249 /* Host Error */ 1250 dmastat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTSTAT_MASKED); 1251 printf("CPSW_CPDMA_DMA_INTSTAT_MASKED %x\n", dmastat); 1252 1253 printf("rxhead %02x\n", sc->sc_rxhead); 1254 1255 stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMASTATUS); 1256 printf("CPSW_CPDMA_DMASTATUS %x\n", stat); 1257 stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0)); 1258 printf("CPSW_CPDMA_TX0_HDP %x\n", stat); 1259 stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0)); 1260 printf("CPSW_CPDMA_TX0_CP %x\n", stat); 1261 stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0)); 1262 printf("CPSW_CPDMA_RX0_HDP %x\n", stat); 1263 stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(0)); 1264 printf("CPSW_CPDMA_RX0_CP %x\n", stat); 1265 1266 /* db_enter(); */ 1267 1268 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTMASK_CLEAR, dmastat); 1269 dmastat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTSTAT_MASKED); 1270 printf("CPSW_CPDMA_DMA_INTSTAT_MASKED %x\n", dmastat); 1271 } 1272 1273 bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_MISC); 1274 1275 return 1; 1276 } 1277 1278 void 1279 cpsw_get_port_config(struct cpsw_port_config *conf, int pnode) 1280 { 1281 char mode[32]; 1282 uint32_t phy_id[2]; 1283 int node, phy_handle, phy_node; 1284 int port = 0; 1285 1286 for (node = OF_child(pnode); node; node = OF_peer(node)) { 1287 if (OF_getprop(node, "local-mac-address", conf[port].enaddr, 1288 sizeof(conf[port].enaddr)) != sizeof(conf[port].enaddr)) 1289 continue; 1290 1291 conf[port].vlan = OF_getpropint(node, "dual_emac_res_vlan", 0); 1292 1293 if (OF_getpropintarray(node, "phy_id", phy_id, 1294 sizeof(phy_id)) == sizeof(phy_id)) 1295 conf[port].phy_id = phy_id[1]; 1296 else if ((phy_handle = 1297 OF_getpropint(node, "phy-handle", 0)) != 0) { 1298 phy_node = OF_getnodebyphandle(phy_handle); 1299 if (phy_node) 1300 conf[port].phy_id = OF_getpropint(phy_node, 1301 "reg", MII_PHY_ANY); 1302 } 1303 1304 if (OF_getprop(node, "phy-mode", mode, sizeof(mode)) > 0 && 1305 !strcmp(mode, "rgmii")) 1306 conf[port].rgmii = 1; 1307 else 1308 conf[port].rgmii = 0; 1309 1310 if (port == 0) 1311 port = 1; 1312 } 1313 } 1314