Lines Matching +full:syscon +full:- +full:rgmii +full:- +full:delay
1 /*-
65 #include <dev/syscon/syscon.h>
71 #define RD4(sc, reg) bus_read_4((sc)->res[_RES_EMAC], (reg))
72 #define WR4(sc, reg, val) bus_write_4((sc)->res[_RES_EMAC], (reg), (val))
74 #define AWG_LOCK(sc) mtx_lock(&(sc)->mtx)
75 #define AWG_UNLOCK(sc) mtx_unlock(&(sc)->mtx);
76 #define AWG_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED)
77 #define AWG_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED)
86 #define TX_NEXT(n) (((n) + 1) & (TX_DESC_COUNT - 1))
87 #define TX_SKIP(n, o) (((n) + (o)) & (TX_DESC_COUNT - 1))
88 #define RX_NEXT(n) (((n) + 1) & (RX_DESC_COUNT - 1))
102 /* syscon EMAC clock register */
150 { "allwinner,sun8i-a83t-emac", EMAC_A83T },
151 { "allwinner,sun8i-h3-emac", EMAC_H3 },
152 { "allwinner,sun50i-a64-emac", EMAC_A64 },
153 { "allwinner,sun20i-d1-emac", EMAC_D1 },
203 struct syscon *syscon; member
213 { -1, 0 }
242 (sc->mdc_div_ratio_m << MDC_DIV_RATIO_M_SHIFT) | in awg_miibus_readreg()
246 for (retry = MII_BUSY_RETRY; retry > 0; retry--) { in awg_miibus_readreg()
251 DELAY(10); in awg_miibus_readreg()
271 (sc->mdc_div_ratio_m << MDC_DIV_RATIO_M_SHIFT) | in awg_miibus_writereg()
275 for (retry = MII_BUSY_RETRY; retry > 0; retry--) { in awg_miibus_writereg()
278 DELAY(10); in awg_miibus_writereg()
299 if ((if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) == 0) in awg_miibus_statchg()
301 mii = device_get_softc(sc->miibus); in awg_miibus_statchg()
303 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == in awg_miibus_statchg()
305 switch (IFM_SUBTYPE(mii->mii_media_active)) { in awg_miibus_statchg()
310 sc->link = 1; in awg_miibus_statchg()
313 sc->link = 0; in awg_miibus_statchg()
317 sc->link = 0; in awg_miibus_statchg()
319 if (sc->link == 0) in awg_miibus_statchg()
325 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || in awg_miibus_statchg()
326 IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) in awg_miibus_statchg()
328 else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) in awg_miibus_statchg()
333 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) in awg_miibus_statchg()
340 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) in awg_miibus_statchg()
346 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) in awg_miibus_statchg()
348 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) in awg_miibus_statchg()
364 mii = device_get_softc(sc->miibus); in awg_media_status()
368 ifmr->ifm_active = mii->mii_media_active; in awg_media_status()
369 ifmr->ifm_status = mii->mii_media_status; in awg_media_status()
381 mii = device_get_softc(sc->miibus); in awg_media_change()
394 /* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */
429 ifp = sc->ifp; in awg_setup_rxfilter()
559 if ((if_getcapenable(sc->ifp) & IFCAP_POLLING) == 0) in awg_init_dma()
611 cur = first = sc->tx.cur; in awg_encap()
612 map = sc->tx.buf_map[first].map; in awg_encap()
615 error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m, segs, in awg_encap()
620 device_printf(sc->dev, "awg_encap: m_collapse failed\n"); in awg_encap()
626 error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m, in awg_encap()
634 device_printf(sc->dev, "awg_encap: bus_dmamap_load_mbuf_sg failed\n"); in awg_encap()
643 if (sc->tx.queued + nsegs > TX_DESC_COUNT) { in awg_encap()
644 bus_dmamap_unload(sc->tx.buf_tag, map); in awg_encap()
648 bus_dmamap_sync(sc->tx.buf_tag, map, BUS_DMASYNC_PREWRITE); in awg_encap()
652 if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) { in awg_encap()
653 if ((m->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) != 0) in awg_encap()
661 sc->tx.segs++; in awg_encap()
662 if (i == nsegs - 1) { in awg_encap()
668 if (sc->tx.segs >= awg_tx_interval) { in awg_encap()
669 sc->tx.segs = 0; in awg_encap()
674 sc->tx.desc_ring[cur].addr = htole32((uint32_t)segs[i].ds_addr); in awg_encap()
675 sc->tx.desc_ring[cur].size = htole32(flags | segs[i].ds_len); in awg_encap()
676 sc->tx.desc_ring[cur].status = htole32(status); in awg_encap()
685 ++sc->tx.queued; in awg_encap()
689 sc->tx.cur = cur; in awg_encap()
692 last = TX_SKIP(cur, TX_DESC_COUNT - 1); in awg_encap()
693 sc->tx.buf_map[first].map = sc->tx.buf_map[last].map; in awg_encap()
694 sc->tx.buf_map[last].map = map; in awg_encap()
695 sc->tx.buf_map[last].mbuf = m; in awg_encap()
701 sc->tx.desc_ring[first].status = htole32(TX_DESC_CTL); in awg_encap()
711 --sc->tx.queued; in awg_clean_txbuf()
713 bmap = &sc->tx.buf_map[index]; in awg_clean_txbuf()
714 if (bmap->mbuf != NULL) { in awg_clean_txbuf()
715 bus_dmamap_sync(sc->tx.buf_tag, bmap->map, in awg_clean_txbuf()
717 bus_dmamap_unload(sc->tx.buf_tag, bmap->map); in awg_clean_txbuf()
718 m_freem(bmap->mbuf); in awg_clean_txbuf()
719 bmap->mbuf = NULL; in awg_clean_txbuf()
729 size = MCLBYTES - 1; in awg_setup_rxdesc()
731 sc->rx.desc_ring[index].addr = htole32((uint32_t)paddr); in awg_setup_rxdesc()
732 sc->rx.desc_ring[index].size = htole32(size); in awg_setup_rxdesc()
733 sc->rx.desc_ring[index].status = htole32(status); in awg_setup_rxdesc()
740 sc->rx.desc_ring[index].status = htole32(RX_DESC_CTL); in awg_reuse_rxdesc()
755 m->m_pkthdr.len = m->m_len = m->m_ext.ext_size; in awg_newbuf_rx()
758 if (bus_dmamap_load_mbuf_sg(sc->rx.buf_tag, sc->rx.buf_spare_map, in awg_newbuf_rx()
764 if (sc->rx.buf_map[index].mbuf != NULL) { in awg_newbuf_rx()
765 bus_dmamap_sync(sc->rx.buf_tag, sc->rx.buf_map[index].map, in awg_newbuf_rx()
767 bus_dmamap_unload(sc->rx.buf_tag, sc->rx.buf_map[index].map); in awg_newbuf_rx()
769 map = sc->rx.buf_map[index].map; in awg_newbuf_rx()
770 sc->rx.buf_map[index].map = sc->rx.buf_spare_map; in awg_newbuf_rx()
771 sc->rx.buf_spare_map = map; in awg_newbuf_rx()
772 bus_dmamap_sync(sc->rx.buf_tag, sc->rx.buf_map[index].map, in awg_newbuf_rx()
775 sc->rx.buf_map[index].mbuf = m; in awg_newbuf_rx()
808 &sc->tx.desc_tag); in awg_setup_dma()
814 error = bus_dmamem_alloc(sc->tx.desc_tag, (void **)&sc->tx.desc_ring, in awg_setup_dma()
815 BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->tx.desc_map); in awg_setup_dma()
821 error = bus_dmamap_load(sc->tx.desc_tag, sc->tx.desc_map, in awg_setup_dma()
822 sc->tx.desc_ring, TX_DESC_SIZE, awg_dmamap_cb, in awg_setup_dma()
823 &sc->tx.desc_ring_paddr, 0); in awg_setup_dma()
830 sc->tx.desc_ring[i].next = in awg_setup_dma()
831 htole32(sc->tx.desc_ring_paddr + DESC_OFF(TX_NEXT(i))); in awg_setup_dma()
843 &sc->tx.buf_tag); in awg_setup_dma()
849 sc->tx.queued = 0; in awg_setup_dma()
851 error = bus_dmamap_create(sc->tx.buf_tag, 0, in awg_setup_dma()
852 &sc->tx.buf_map[i].map); in awg_setup_dma()
870 &sc->rx.desc_tag); in awg_setup_dma()
876 error = bus_dmamem_alloc(sc->rx.desc_tag, (void **)&sc->rx.desc_ring, in awg_setup_dma()
877 BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx.desc_map); in awg_setup_dma()
883 error = bus_dmamap_load(sc->rx.desc_tag, sc->rx.desc_map, in awg_setup_dma()
884 sc->rx.desc_ring, RX_DESC_SIZE, awg_dmamap_cb, in awg_setup_dma()
885 &sc->rx.desc_ring_paddr, 0); in awg_setup_dma()
901 &sc->rx.buf_tag); in awg_setup_dma()
907 error = bus_dmamap_create(sc->rx.buf_tag, 0, &sc->rx.buf_spare_map); in awg_setup_dma()
915 sc->rx.desc_ring[i].next = in awg_setup_dma()
916 htole32(sc->rx.desc_ring_paddr + DESC_OFF(RX_NEXT(i))); in awg_setup_dma()
918 error = bus_dmamap_create(sc->rx.buf_tag, 0, in awg_setup_dma()
919 &sc->rx.buf_map[i].map); in awg_setup_dma()
924 sc->rx.buf_map[i].mbuf = NULL; in awg_setup_dma()
931 bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, in awg_setup_dma()
935 WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr); in awg_setup_dma()
936 WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr); in awg_setup_dma()
966 if (!sc->link) in awg_start_locked()
969 ifp = sc->ifp; in awg_start_locked()
992 bus_dmamap_sync(sc->tx.desc_tag, sc->tx.desc_map, in awg_start_locked()
1017 mii = device_get_softc(sc->miibus); in awg_init_locked()
1018 ifp = sc->ifp; in awg_init_locked()
1033 callout_reset(&sc->stat_ch, hz, awg_tick, sc); in awg_init_locked()
1057 ifp = sc->ifp; in awg_stop()
1059 callout_stop(&sc->stat_ch); in awg_stop()
1064 sc->link = 0; in awg_stop()
1070 for (i = sc->tx.next; sc->tx.queued > 0; i = TX_NEXT(i)) { in awg_stop()
1071 val = le32toh(sc->tx.desc_ring[i].status); in awg_stop()
1076 sc->tx.next = i; in awg_stop()
1077 for (; sc->tx.queued > 0; i = TX_NEXT(i)) { in awg_stop()
1078 sc->tx.desc_ring[i].status = 0; in awg_stop()
1081 sc->tx.cur = sc->tx.next; in awg_stop()
1082 bus_dmamap_sync(sc->tx.desc_tag, sc->tx.desc_map, in awg_stop()
1086 bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, in awg_stop()
1089 for (i = sc->rx.cur; ; i = RX_NEXT(i)) { in awg_stop()
1090 val = le32toh(sc->rx.desc_ring[i].status); in awg_stop()
1095 sc->rx.cur = i; in awg_stop()
1096 bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, in awg_stop()
1111 mii = device_get_softc(sc->miibus); in awg_ioctl()
1120 flags = if_getflags(ifp) ^ sc->if_flags; in awg_ioctl()
1129 sc->if_flags = if_getflags(ifp); in awg_ioctl()
1142 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); in awg_ioctl()
1145 mask = ifr->ifr_reqcap ^ if_getcapenable(ifp); in awg_ioctl()
1148 if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) { in awg_ioctl()
1196 ifp = sc->ifp; in awg_rxintr()
1201 bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, in awg_rxintr()
1204 for (index = sc->rx.cur; ; index = RX_NEXT(index)) { in awg_rxintr()
1205 status = le32toh(sc->rx.desc_ring[index].status); in awg_rxintr()
1218 m = sc->rx.buf_map[index].mbuf; in awg_rxintr()
1227 m->m_pkthdr.rcvif = ifp; in awg_rxintr()
1228 m->m_pkthdr.len = len; in awg_rxintr()
1229 m->m_len = len; in awg_rxintr()
1234 m->m_pkthdr.csum_flags = CSUM_IP_CHECKED; in awg_rxintr()
1236 m->m_pkthdr.csum_flags |= CSUM_IP_VALID; in awg_rxintr()
1238 m->m_pkthdr.csum_flags |= in awg_rxintr()
1240 m->m_pkthdr.csum_data = 0xffff; in awg_rxintr()
1244 m->m_nextpkt = NULL; in awg_rxintr()
1248 mt->m_nextpkt = m; in awg_rxintr()
1262 if (index != sc->rx.cur) { in awg_rxintr()
1263 bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, in awg_rxintr()
1273 sc->rx.cur = index; in awg_rxintr()
1288 bus_dmamap_sync(sc->tx.desc_tag, sc->tx.desc_map, in awg_txeof()
1291 ifp = sc->ifp; in awg_txeof()
1294 for (i = sc->tx.next; sc->tx.queued > 0; i = TX_NEXT(i)) { in awg_txeof()
1295 desc = &sc->tx.desc_ring[i]; in awg_txeof()
1296 status = le32toh(desc->status); in awg_txeof()
1299 size = le32toh(desc->size); in awg_txeof()
1311 sc->tx.next = i; in awg_txeof()
1335 if (!if_sendq_empty(sc->ifp)) in awg_intr()
1378 * syscon functions
1386 if (sc->syscon != NULL) in syscon_read_emac_clk_reg()
1387 return (SYSCON_READ_4(sc->syscon, EMAC_CLK_REG)); in syscon_read_emac_clk_reg()
1388 else if (sc->res[_RES_SYSCON] != NULL) in syscon_read_emac_clk_reg()
1389 return (bus_read_4(sc->res[_RES_SYSCON], 0)); in syscon_read_emac_clk_reg()
1400 if (sc->syscon != NULL) in syscon_write_emac_clk_reg()
1401 SYSCON_WRITE_4(sc->syscon, EMAC_CLK_REG, val); in syscon_write_emac_clk_reg()
1402 else if (sc->res[_RES_SYSCON] != NULL) in syscon_write_emac_clk_reg()
1403 bus_write_4(sc->res[_RES_SYSCON], 0, val); in syscon_write_emac_clk_reg()
1417 if (OF_getencprop(node, "phy-handle", (void *)&phy_handle, in awg_get_phy_node()
1431 if (OF_hasprop(node, "allwinner,use-internal-phy")) in awg_has_internal_phy()
1436 "allwinner,sun8i-h3-mdio-internal") != 0); in awg_has_internal_phy()
1443 uint32_t delay; in awg_parse_delay() local
1450 if (OF_getencprop(node, "tx-delay", &delay, sizeof(delay)) >= 0) in awg_parse_delay()
1451 *tx_delay = delay; in awg_parse_delay()
1452 else if (OF_getencprop(node, "allwinner,tx-delay-ps", &delay, in awg_parse_delay()
1453 sizeof(delay)) >= 0) { in awg_parse_delay()
1454 if ((delay % 100) != 0) { in awg_parse_delay()
1455 device_printf(dev, "tx-delay-ps is not a multiple of 100\n"); in awg_parse_delay()
1458 *tx_delay = delay / 100; in awg_parse_delay()
1461 device_printf(dev, "tx-delay out of range\n"); in awg_parse_delay()
1465 if (OF_getencprop(node, "rx-delay", &delay, sizeof(delay)) >= 0) in awg_parse_delay()
1466 *rx_delay = delay; in awg_parse_delay()
1467 else if (OF_getencprop(node, "allwinner,rx-delay-ps", &delay, in awg_parse_delay()
1468 sizeof(delay)) >= 0) { in awg_parse_delay()
1469 if ((delay % 100) != 0) { in awg_parse_delay()
1470 device_printf(dev, "rx-delay-ps is not within documented domain\n"); in awg_parse_delay()
1473 *rx_delay = delay / 100; in awg_parse_delay()
1476 device_printf(dev, "rx-delay out of range\n"); in awg_parse_delay()
1499 if (OF_getprop_alloc(node, "phy-mode", (void **)&phy_type) == 0) in awg_setup_phy()
1502 if (sc->syscon != NULL || sc->res[_RES_SYSCON] != NULL) in awg_setup_phy()
1511 * Abstract away writing to syscon for devices like the pine64. in awg_setup_phy()
1512 * For the pine64, we get dtb from U-Boot and it still uses the in awg_setup_phy()
1513 * legacy setup of specifying syscon register in emac node in awg_setup_phy()
1515 * These abstractions can go away once U-Boot dts is up-to-date. in awg_setup_phy()
1519 if (strncmp(phy_type, "rgmii", 5) == 0) in awg_setup_phy()
1527 * Fail attach if we fail to parse either of the delay in awg_setup_phy()
1528 * parameters. If we don't have the proper delay to write to in awg_setup_phy()
1529 * syscon, then awg likely won't function properly anyways. in awg_setup_phy()
1530 * Lack of delay is not an error! in awg_setup_phy()
1543 if (sc->type == EMAC_H3) { in awg_setup_phy()
1548 "allwinner,leds-active-low")) in awg_setup_phy()
1565 if (strncmp(phy_type, "rgmii", 5) == 0) in awg_setup_phy()
1577 /* Find the desired parent clock based on phy-mode property */ in awg_setup_phy()
1625 if (phy_node == 0 && OF_hasprop(node, "phy-handle")) { in awg_setup_extres()
1655 if (OF_hasprop(node, "syscon") && syscon_get_by_ofw_property(dev, node, in awg_setup_extres()
1656 "syscon", &sc->syscon) != 0) { in awg_setup_extres()
1657 device_printf(dev, "cannot get syscon driver handle\n"); in awg_setup_extres()
1661 /* Configure PHY for MII or RGMII mode */ in awg_setup_extres()
1679 /* De-assert reset */ in awg_setup_extres()
1682 device_printf(dev, "cannot de-assert ahb reset\n"); in awg_setup_extres()
1687 * The ephy reset is left de-asserted by U-Boot. Assert it in awg_setup_extres()
1694 device_printf(dev, "cannot de-assert ephy reset\n"); in awg_setup_extres()
1700 if (regulator_get_by_ofw_property(dev, 0, "phy-supply", ®) == 0) { in awg_setup_extres()
1716 sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_16; in awg_setup_extres()
1718 sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_32; in awg_setup_extres()
1720 sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_64; in awg_setup_extres()
1722 sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_128; in awg_setup_extres()
1731 (uintmax_t)freq, sc->mdc_div_ratio_m); in awg_setup_extres()
1788 device_printf(dev, " %-20s %08x\n", regs[n].name, in awg_dump_regs()
1805 if (OF_getencprop(node, "allwinner,reset-gpio", gpio_prop, in awg_phy_reset()
1809 if (OF_getencprop(node, "allwinner,reset-delays-us", delay_prop, in awg_phy_reset()
1817 if (GPIO_MAP_GPIOS(gpio, node, gpio_node, nitems(gpio_prop) - 1, in awg_phy_reset()
1822 if (OF_hasprop(node, "allwinner,reset-active-low")) in awg_phy_reset()
1830 DELAY(delay_prop[0]); in awg_phy_reset()
1832 DELAY(delay_prop[1]); in awg_phy_reset()
1834 DELAY(delay_prop[2]); in awg_phy_reset()
1856 /* Wait for soft reset bit to self-clear */ in awg_reset()
1857 for (retry = SOFT_RST_RETRY; retry > 0; retry--) { in awg_reset()
1860 DELAY(10); in awg_reset()
1886 ifp = sc->ifp; in awg_tick()
1887 mii = device_get_softc(sc->miibus); in awg_tick()
1894 link = sc->link; in awg_tick()
1896 if (sc->link && !link) in awg_tick()
1899 callout_reset(&sc->stat_ch, hz, awg_tick, sc); in awg_tick()
1912 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) in awg_probe()
1927 sc->dev = dev; in awg_attach()
1928 sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; in awg_attach()
1930 if (bus_alloc_resources(dev, awg_spec, sc->res) != 0) { in awg_attach()
1935 mtx_init(&sc->mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); in awg_attach()
1936 callout_init_mtx(&sc->stat_ch, &sc->mtx, 0); in awg_attach()
1957 error = bus_setup_intr(dev, sc->res[_RES_IRQ], in awg_attach()
1958 INTR_TYPE_NET | INTR_MPSAFE, NULL, awg_intr, sc, &sc->ih); in awg_attach()
1965 sc->ifp = if_alloc(IFT_ETHER); in awg_attach()
1966 if_setsoftc(sc->ifp, sc); in awg_attach()
1967 if_initname(sc->ifp, device_get_name(dev), device_get_unit(dev)); in awg_attach()
1968 if_setflags(sc->ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); in awg_attach()
1969 if_setstartfn(sc->ifp, awg_start); in awg_attach()
1970 if_setioctlfn(sc->ifp, awg_ioctl); in awg_attach()
1971 if_setinitfn(sc->ifp, awg_init); in awg_attach()
1972 if_setsendqlen(sc->ifp, TX_DESC_COUNT - 1); in awg_attach()
1973 if_setsendqready(sc->ifp); in awg_attach()
1974 if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP); in awg_attach()
1975 if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM); in awg_attach()
1976 if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp)); in awg_attach()
1978 if_setcapabilitiesbit(sc->ifp, IFCAP_POLLING, 0); in awg_attach()
1982 error = mii_attach(dev, &sc->miibus, sc->ifp, awg_media_change, in awg_attach()
1991 ether_ifattach(sc->ifp, eaddr); in awg_attach()