Date: Thu, 24 Dec 2015 18:41:17 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292704 - head/sys/dev/rt Message-ID: <201512241841.tBOIfHFe064302@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Thu Dec 24 18:41:16 2015 New Revision: 292704 URL: https://svnweb.freebsd.org/changeset/base/292704 Log: [rt] add support for the RT5350 and MT7620 SoCs. This is a work in progress; bringing the interface down stops further use. It only happens on RT5350/MT7620. This is based on work by Alexander A. Mityaev <sansan@adm.ua>. Submitted by: Stanislav Galabov <galabov@gmail.com> Modified: head/sys/dev/rt/if_rt.c head/sys/dev/rt/if_rtreg.h head/sys/dev/rt/if_rtvar.h Modified: head/sys/dev/rt/if_rt.c ============================================================================== --- head/sys/dev/rt/if_rt.c Thu Dec 24 18:40:10 2015 (r292703) +++ head/sys/dev/rt/if_rt.c Thu Dec 24 18:41:16 2015 (r292704) @@ -1,4 +1,6 @@ /*- + * Copyright (c) 2015, Stanislav Galabov + * Copyright (c) 2014, Aleksandr A. Mityaev * Copyright (c) 2011, Aleksandr Rybalko * based on hard work * by Alexander Egorenkov <egorenar@gmail.com> @@ -56,6 +58,15 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/rman.h> +#include "opt_platform.h" +#include "opt_rt305x.h" + +#ifdef FDT +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#endif + #include <dev/mii/mii.h> #include <dev/mii/miivar.h> @@ -78,6 +89,23 @@ __FBSDID("$FreeBSD$"); #define RT_TX_WATCHDOG_TIMEOUT 5 +#define RT_CHIPID_RT3050 0x3050 +#define RT_CHIPID_RT3052 0x3052 +#define RT_CHIPID_RT5350 0x5350 +#define RT_CHIPID_RT6855 0x6855 +#define RT_CHIPID_MT7620 0x7620 + +#ifdef FDT +/* more specific and new models should go first */ +static const struct ofw_compat_data rt_compat_data[] = { + { "ralink,rt6855-eth", (uintptr_t)RT_CHIPID_RT6855 }, + { "ralink,rt5350-eth", (uintptr_t)RT_CHIPID_RT5350 }, + { "ralink,rt3052-eth", (uintptr_t)RT_CHIPID_RT3052 }, + { "ralink,rt305x-eth", (uintptr_t)RT_CHIPID_RT3050 }, + { NULL, (uintptr_t)NULL } +}; +#endif + /* * Static function prototypes */ @@ -96,16 +124,18 @@ static int rt_ioctl(struct ifnet *ifp, u static void rt_periodic(void *arg); static void rt_tx_watchdog(void *arg); static void rt_intr(void *arg); +static void rt_rt5350_intr(void *arg); static void rt_tx_coherent_intr(struct rt_softc *sc); static void rt_rx_coherent_intr(struct rt_softc *sc); static void rt_rx_delay_intr(struct rt_softc *sc); static void rt_tx_delay_intr(struct rt_softc *sc); -static void rt_rx_intr(struct rt_softc *sc); +static void rt_rx_intr(struct rt_softc *sc, int qid); static void rt_tx_intr(struct rt_softc *sc, int qid); static void rt_rx_done_task(void *context, int pending); static void rt_tx_done_task(void *context, int pending); static void rt_periodic_task(void *context, int pending); -static int rt_rx_eof(struct rt_softc *sc, int limit); +static int rt_rx_eof(struct rt_softc *sc, + struct rt_softc_rx_ring *ring, int limit); static void rt_tx_eof(struct rt_softc *sc, struct rt_softc_tx_ring *ring); static void rt_update_stats(struct rt_softc *sc); @@ -115,7 +145,7 @@ static void rt_intr_enable(struct rt_sof static void rt_intr_disable(struct rt_softc *sc, uint32_t intr_mask); static int rt_txrx_enable(struct rt_softc *sc); static int rt_alloc_rx_ring(struct rt_softc *sc, - struct rt_softc_rx_ring *ring); + struct rt_softc_rx_ring *ring, int qid); static void rt_reset_rx_ring(struct rt_softc *sc, struct rt_softc_rx_ring *ring); static void rt_free_rx_ring(struct rt_softc *sc, @@ -147,8 +177,29 @@ SYSCTL_INT(_hw_rt, OID_AUTO, debug, CTLF static int rt_probe(device_t dev) { - device_set_desc(dev, "Ralink RT305XF onChip Ethernet MAC"); - return (BUS_PROBE_NOWILDCARD); + struct rt_softc *sc = device_get_softc(dev); + char buf[80]; +#ifdef FDT + const struct ofw_compat_data * cd; + + cd = ofw_bus_search_compatible(dev, rt_compat_data); + if (cd->ocd_data == (uintptr_t)NULL) + return (ENXIO); + + sc->rt_chipid = (unsigned int)(cd->ocd_data); +#else +#if defined(MT7620) + sc->rt_chipid = RT_CHIPID_MT7620; +#elif defined(RT5350) + sc->rt_chipid = RT_CHIPID_RT5350; +#else + sc->rt_chipid = RT_CHIPID_RT3050; +#endif +#endif + snprintf(buf, sizeof(buf), "Ralink RT%x onChip Ethernet driver", + sc->rt_chipid); + device_set_desc_copy(dev, buf); + return (BUS_PROBE_GENERIC); } /* @@ -240,7 +291,7 @@ ether_request_mac(device_t dev, uint8_t * "ethaddr" is passed via envp on RedBoot platforms * "kmac" is passed via argv on RouterBOOT platforms */ -#if defined(__U_BOOT__) || defined(__REDBOOT__) || defined(__ROUTERBOOT__) +#if defined(RT305X_UBOOT) || defined(__REDBOOT__) || defined(__ROUTERBOOT__) if ((var = kern_getenv("ethaddr")) != NULL || (var = kern_getenv("kmac")) != NULL ) { @@ -288,6 +339,16 @@ ether_request_mac(device_t dev, uint8_t return (0); } +/* + * Reset hardware + */ +static void +reset_freng(struct rt_softc *sc) +{ + /* XXX hard reset kills everything so skip it ... */ + return; +} + static int rt_attach(device_t dev) { @@ -331,23 +392,80 @@ rt_attach(device_t dev) "debug", CTLFLAG_RW, &sc->debug, 0, "rt debug level"); #endif - device_printf(dev, "RT305XF Ethernet MAC (rev 0x%08x)\n", - sc->mac_rev); - /* Reset hardware */ - RT_WRITE(sc, GE_PORT_BASE + FE_RST_GLO, PSE_RESET); - - RT_WRITE(sc, GDMA1_BASE + GDMA_FWD_CFG, - ( - GDM_ICS_EN | /* Enable IP Csum */ - GDM_TCS_EN | /* Enable TCP Csum */ - GDM_UCS_EN | /* Enable UDP Csum */ - GDM_STRPCRC | /* Strip CRC from packet */ - GDM_DST_PORT_CPU << GDM_UFRC_P_SHIFT | /* Forward UCast to CPU */ - GDM_DST_PORT_CPU << GDM_BFRC_P_SHIFT | /* Forward BCast to CPU */ - GDM_DST_PORT_CPU << GDM_MFRC_P_SHIFT | /* Forward MCast to CPU */ - GDM_DST_PORT_CPU << GDM_OFRC_P_SHIFT /* Forward Other to CPU */ - )); + reset_freng(sc); + + /* Fill in soc-specific registers map */ + switch(sc->rt_chipid) { + case RT_CHIPID_MT7620: + case RT_CHIPID_RT5350: + device_printf(dev, "RT%x Ethernet MAC (rev 0x%08x)\n", + sc->rt_chipid, sc->mac_rev); + /* RT5350: No GDMA, PSE, CDMA, PPE */ + RT_WRITE(sc, GE_PORT_BASE + 0x0C00, // UDPCS, TCPCS, IPCS=1 + RT_READ(sc, GE_PORT_BASE + 0x0C00) | (0x7<<16)); + sc->delay_int_cfg=RT5350_PDMA_BASE+RT5350_DELAY_INT_CFG; + sc->fe_int_status=RT5350_FE_INT_STATUS; + sc->fe_int_enable=RT5350_FE_INT_ENABLE; + sc->pdma_glo_cfg=RT5350_PDMA_BASE+RT5350_PDMA_GLO_CFG; + sc->pdma_rst_idx=RT5350_PDMA_BASE+RT5350_PDMA_RST_IDX; + for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { + sc->tx_base_ptr[i]=RT5350_PDMA_BASE+RT5350_TX_BASE_PTR(i); + sc->tx_max_cnt[i]=RT5350_PDMA_BASE+RT5350_TX_MAX_CNT(i); + sc->tx_ctx_idx[i]=RT5350_PDMA_BASE+RT5350_TX_CTX_IDX(i); + sc->tx_dtx_idx[i]=RT5350_PDMA_BASE+RT5350_TX_DTX_IDX(i); + } + sc->rx_ring_count=2; + sc->rx_base_ptr[0]=RT5350_PDMA_BASE+RT5350_RX_BASE_PTR0; + sc->rx_max_cnt[0]=RT5350_PDMA_BASE+RT5350_RX_MAX_CNT0; + sc->rx_calc_idx[0]=RT5350_PDMA_BASE+RT5350_RX_CALC_IDX0; + sc->rx_drx_idx[0]=RT5350_PDMA_BASE+RT5350_RX_DRX_IDX0; + sc->rx_base_ptr[1]=RT5350_PDMA_BASE+RT5350_RX_BASE_PTR1; + sc->rx_max_cnt[1]=RT5350_PDMA_BASE+RT5350_RX_MAX_CNT1; + sc->rx_calc_idx[1]=RT5350_PDMA_BASE+RT5350_RX_CALC_IDX1; + sc->rx_drx_idx[1]=RT5350_PDMA_BASE+RT5350_RX_DRX_IDX1; + sc->int_rx_done_mask=RT5350_INT_RXQ0_DONE; + sc->int_tx_done_mask=RT5350_INT_TXQ0_DONE; + break; + case RT_CHIPID_RT6855: + device_printf(dev, "RT6855 Ethernet MAC (rev 0x%08x)\n", + sc->mac_rev); + break; + default: + device_printf(dev, "RT305XF Ethernet MAC (rev 0x%08x)\n", + sc->mac_rev); + RT_WRITE(sc, GDMA1_BASE + GDMA_FWD_CFG, + ( + GDM_ICS_EN | /* Enable IP Csum */ + GDM_TCS_EN | /* Enable TCP Csum */ + GDM_UCS_EN | /* Enable UDP Csum */ + GDM_STRPCRC | /* Strip CRC from packet */ + GDM_DST_PORT_CPU << GDM_UFRC_P_SHIFT | /* fwd UCast to CPU */ + GDM_DST_PORT_CPU << GDM_BFRC_P_SHIFT | /* fwd BCast to CPU */ + GDM_DST_PORT_CPU << GDM_MFRC_P_SHIFT | /* fwd MCast to CPU */ + GDM_DST_PORT_CPU << GDM_OFRC_P_SHIFT /* fwd Other to CPU */ + )); + + sc->delay_int_cfg=PDMA_BASE+DELAY_INT_CFG; + sc->fe_int_status=GE_PORT_BASE+FE_INT_STATUS; + sc->fe_int_enable=GE_PORT_BASE+FE_INT_ENABLE; + sc->pdma_glo_cfg=PDMA_BASE+PDMA_GLO_CFG; + sc->pdma_glo_cfg=PDMA_BASE+PDMA_GLO_CFG; + sc->pdma_rst_idx=PDMA_BASE+PDMA_RST_IDX; + for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { + sc->tx_base_ptr[i]=PDMA_BASE+TX_BASE_PTR(i); + sc->tx_max_cnt[i]=PDMA_BASE+TX_MAX_CNT(i); + sc->tx_ctx_idx[i]=PDMA_BASE+TX_CTX_IDX(i); + sc->tx_dtx_idx[i]=PDMA_BASE+TX_DTX_IDX(i); + } + sc->rx_ring_count=1; + sc->rx_base_ptr[0]=PDMA_BASE+RX_BASE_PTR0; + sc->rx_max_cnt[0]=PDMA_BASE+RX_MAX_CNT0; + sc->rx_calc_idx[0]=PDMA_BASE+RX_CALC_IDX0; + sc->rx_drx_idx[0]=PDMA_BASE+RX_DRX_IDX0; + sc->int_rx_done_mask=INT_RX_DONE; + sc->int_tx_done_mask=INT_TXQ0_DONE; + }; /* allocate Tx and Rx rings */ for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { @@ -360,11 +478,12 @@ rt_attach(device_t dev) } sc->tx_ring_mgtqid = 5; - - error = rt_alloc_rx_ring(sc, &sc->rx_ring); - if (error != 0) { - device_printf(dev, "could not allocate Rx ring\n"); - goto fail; + for (i = 0; i < sc->rx_ring_count; i++) { + error = rt_alloc_rx_ring(sc, &sc->rx_ring[i], i); + if (error != 0) { + device_printf(dev, "could not allocate Rx ring\n"); + goto fail; + } } callout_init(&sc->periodic_ch, 0); @@ -434,7 +553,9 @@ rt_attach(device_t dev) /* set up interrupt */ error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, - NULL, rt_intr, sc, &sc->irqh); + NULL, (sc->rt_chipid == RT_CHIPID_RT5350 || + sc->rt_chipid == RT_CHIPID_MT7620) ? rt_rt5350_intr : rt_intr, + sc, &sc->irqh); if (error != 0) { printf("%s: could not set up interrupt\n", device_get_nameunit(dev)); @@ -451,7 +572,8 @@ fail: for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) rt_free_tx_ring(sc, &sc->tx_ring[i]); - rt_free_rx_ring(sc, &sc->rx_ring); + for (i = 0; i < sc->rx_ring_count; i++) + rt_free_rx_ring(sc, &sc->rx_ring[i]); mtx_destroy(&sc->lock); @@ -567,8 +689,8 @@ rt_detach(device_t dev) /* free Tx and Rx rings */ for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) rt_free_tx_ring(sc, &sc->tx_ring[i]); - - rt_free_rx_ring(sc, &sc->rx_ring); + for (i = 0; i < sc->rx_ring_count; i++) + rt_free_rx_ring(sc, &sc->rx_ring[i]); RT_SOFTC_UNLOCK(sc); @@ -658,11 +780,12 @@ rt_init_locked(void *priv) RT_SOFTC_ASSERT_LOCKED(sc); /* hardware reset */ - RT_WRITE(sc, GE_PORT_BASE + FE_RST_GLO, PSE_RESET); - rt305x_sysctl_set(SYSCTL_RSTCTRL, SYSCTL_RSTCTRL_FRENG); + //RT_WRITE(sc, GE_PORT_BASE + FE_RST_GLO, PSE_RESET); + //rt305x_sysctl_set(SYSCTL_RSTCTRL, SYSCTL_RSTCTRL_FRENG); /* Fwd to CPU (uni|broad|multi)cast and Unknown */ - RT_WRITE(sc, GDMA1_BASE + GDMA_FWD_CFG, + if(sc->rt_chipid == RT_CHIPID_RT3050 || sc->rt_chipid == RT_CHIPID_RT3052) + RT_WRITE(sc, GDMA1_BASE + GDMA_FWD_CFG, ( GDM_ICS_EN | /* Enable IP Csum */ GDM_TCS_EN | /* Enable TCP Csum */ @@ -675,12 +798,12 @@ rt_init_locked(void *priv) )); /* disable DMA engine */ - RT_WRITE(sc, PDMA_BASE + PDMA_GLO_CFG, 0); - RT_WRITE(sc, PDMA_BASE + PDMA_RST_IDX, 0xffffffff); + RT_WRITE(sc, sc->pdma_glo_cfg, 0); + RT_WRITE(sc, sc->pdma_rst_idx, 0xffffffff); /* wait while DMA engine is busy */ for (ntries = 0; ntries < 100; ntries++) { - tmp = RT_READ(sc, PDMA_BASE + PDMA_GLO_CFG); + tmp = RT_READ(sc, sc->pdma_glo_cfg); if (!(tmp & (FE_TX_DMA_BUSY | FE_RX_DMA_BUSY))) break; DELAY(1000); @@ -698,7 +821,7 @@ rt_init_locked(void *priv) FE_RST_DTX_IDX1 | FE_RST_DTX_IDX0; - RT_WRITE(sc, PDMA_BASE + PDMA_RST_IDX, tmp); + RT_WRITE(sc, sc->pdma_rst_idx, tmp); /* XXX switch set mac address */ for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) @@ -706,36 +829,52 @@ rt_init_locked(void *priv) for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { /* update TX_BASE_PTRx */ - RT_WRITE(sc, PDMA_BASE + TX_BASE_PTR(i), + RT_WRITE(sc, sc->tx_base_ptr[i], sc->tx_ring[i].desc_phys_addr); - RT_WRITE(sc, PDMA_BASE + TX_MAX_CNT(i), + RT_WRITE(sc, sc->tx_max_cnt[i], RT_SOFTC_TX_RING_DESC_COUNT); - RT_WRITE(sc, PDMA_BASE + TX_CTX_IDX(i), 0); + RT_WRITE(sc, sc->tx_ctx_idx[i], 0); } /* init Rx ring */ - rt_reset_rx_ring(sc, &sc->rx_ring); + for (i = 0; i < sc->rx_ring_count; i++) + rt_reset_rx_ring(sc, &sc->rx_ring[i]); - /* update RX_BASE_PTR0 */ - RT_WRITE(sc, PDMA_BASE + RX_BASE_PTR0, - sc->rx_ring.desc_phys_addr); - RT_WRITE(sc, PDMA_BASE + RX_MAX_CNT0, - RT_SOFTC_RX_RING_DATA_COUNT); - RT_WRITE(sc, PDMA_BASE + RX_CALC_IDX0, - RT_SOFTC_RX_RING_DATA_COUNT - 1); + /* update RX_BASE_PTRx */ + for (i = 0; i < sc->rx_ring_count; i++) { + RT_WRITE(sc, sc->rx_base_ptr[i], + sc->rx_ring[i].desc_phys_addr); + RT_WRITE(sc, sc->rx_max_cnt[i], + RT_SOFTC_RX_RING_DATA_COUNT); + RT_WRITE(sc, sc->rx_calc_idx[i], + RT_SOFTC_RX_RING_DATA_COUNT - 1); + } /* write back DDONE, 16byte burst enable RX/TX DMA */ - RT_WRITE(sc, PDMA_BASE + PDMA_GLO_CFG, - FE_TX_WB_DDONE | FE_DMA_BT_SIZE16 | FE_RX_DMA_EN | FE_TX_DMA_EN); + tmp = FE_TX_WB_DDONE | FE_DMA_BT_SIZE16 | FE_RX_DMA_EN | FE_TX_DMA_EN; + if (sc->rt_chipid == RT_CHIPID_MT7620) + tmp |= (1<<31); + RT_WRITE(sc, sc->pdma_glo_cfg, tmp); /* disable interrupts mitigation */ - RT_WRITE(sc, PDMA_BASE + DELAY_INT_CFG, 0); + RT_WRITE(sc, sc->delay_int_cfg, 0); /* clear pending interrupts */ - RT_WRITE(sc, GE_PORT_BASE + FE_INT_STATUS, 0xffffffff); + RT_WRITE(sc, sc->fe_int_status, 0xffffffff); /* enable interrupts */ - tmp = CNT_PPE_AF | + if (sc->rt_chipid == RT_CHIPID_RT5350 || + sc->rt_chipid == RT_CHIPID_MT7620) + tmp = RT5350_INT_TX_COHERENT | + RT5350_INT_RX_COHERENT | + RT5350_INT_TXQ3_DONE | + RT5350_INT_TXQ2_DONE | + RT5350_INT_TXQ1_DONE | + RT5350_INT_TXQ0_DONE | + RT5350_INT_RXQ1_DONE | + RT5350_INT_RXQ0_DONE; + else + tmp = CNT_PPE_AF | CNT_GDM_AF | PSE_P2_FC | GDM_CRC_DROP | @@ -754,7 +893,7 @@ rt_init_locked(void *priv) sc->intr_enable_mask = tmp; - RT_WRITE(sc, GE_PORT_BASE + FE_INT_ENABLE, tmp); + RT_WRITE(sc, sc->fe_int_enable, tmp); if (rt_txrx_enable(sc) != 0) goto fail; @@ -824,12 +963,15 @@ rt_stop_locked(void *priv) RT_SOFTC_LOCK(sc); /* disable interrupts */ - RT_WRITE(sc, GE_PORT_BASE + FE_INT_ENABLE, 0); - - /* reset adapter */ - RT_WRITE(sc, GE_PORT_BASE + FE_RST_GLO, PSE_RESET); + RT_WRITE(sc, sc->fe_int_enable, 0); + + if(sc->rt_chipid == RT_CHIPID_RT5350 || + sc->rt_chipid == RT_CHIPID_MT7620) { + } else { + /* reset adapter */ + RT_WRITE(sc, GE_PORT_BASE + FE_RST_GLO, PSE_RESET); - RT_WRITE(sc, GDMA1_BASE + GDMA_FWD_CFG, + RT_WRITE(sc, GDMA1_BASE + GDMA_FWD_CFG, ( GDM_ICS_EN | /* Enable IP Csum */ GDM_TCS_EN | /* Enable TCP Csum */ @@ -840,6 +982,7 @@ rt_stop_locked(void *priv) GDM_DST_PORT_CPU << GDM_MFRC_P_SHIFT | /* Forward MCast to CPU */ GDM_DST_PORT_CPU << GDM_OFRC_P_SHIFT /* Forward Other to CPU */ )); + } } static void @@ -930,8 +1073,16 @@ rt_tx_data(struct rt_softc *sc, struct m /* set up Tx descs */ for (i = 0; i < ndmasegs; i += 2) { - /* Set destenation */ - desc->dst = (TXDSCR_DST_PORT_GDMA1); + + /* TODO: this needs to be refined as MT7620 for example has + * a different word3 layout than RT305x and RT5350 (the last + * one doesn't use word3 at all). + */ + + /* Set destination */ + if (sc->rt_chipid != RT_CHIPID_MT7620) + desc->dst = (TXDSCR_DST_PORT_GDMA1); + if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) desc->dst |= (TXDSCR_IP_CSUM_GEN|TXDSCR_UDP_CSUM_GEN| TXDSCR_TCP_CSUM_GEN); @@ -986,7 +1137,7 @@ rt_tx_data(struct rt_softc *sc, struct m ring->data_cur = (ring->data_cur + 1) % RT_SOFTC_TX_RING_DATA_COUNT; /* kick Tx */ - RT_WRITE(sc, PDMA_BASE + TX_CTX_IDX(qid), ring->desc_cur); + RT_WRITE(sc, sc->tx_ctx_idx[qid], ring->desc_cur); return (0); } @@ -1272,8 +1423,8 @@ rt_intr(void *arg) ifp = sc->ifp; /* acknowledge interrupts */ - status = RT_READ(sc, GE_PORT_BASE + FE_INT_STATUS); - RT_WRITE(sc, GE_PORT_BASE + FE_INT_STATUS, status); + status = RT_READ(sc, sc->fe_int_status); + RT_WRITE(sc, sc->fe_int_status, status); RT_DPRINTF(sc, RT_DEBUG_INTR, "interrupt: status=0x%08x\n", status); @@ -1326,7 +1477,7 @@ rt_intr(void *arg) rt_tx_delay_intr(sc); if (status & INT_RX_DONE) - rt_rx_intr(sc); + rt_rx_intr(sc, 0); if (status & INT_TXQ3_DONE) rt_tx_intr(sc, 3); @@ -1341,6 +1492,56 @@ rt_intr(void *arg) rt_tx_intr(sc, 0); } +/* + * rt_rt5350_intr - main ISR for Ralink 5350 SoC + */ +static void +rt_rt5350_intr(void *arg) +{ + struct rt_softc *sc; + struct ifnet *ifp; + uint32_t status; + + sc = arg; + ifp = sc->ifp; + + /* acknowledge interrupts */ + status = RT_READ(sc, sc->fe_int_status); + RT_WRITE(sc, sc->fe_int_status, status); + + RT_DPRINTF(sc, RT_DEBUG_INTR, "interrupt: status=0x%08x\n", status); + + if (status == 0xffffffff || /* device likely went away */ + status == 0) /* not for us */ + return; + + sc->interrupts++; + + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + return; + + if (status & RT5350_INT_TX_COHERENT) + rt_tx_coherent_intr(sc); + if (status & RT5350_INT_RX_COHERENT) + rt_rx_coherent_intr(sc); + if (status & RT5350_RX_DLY_INT) + rt_rx_delay_intr(sc); + if (status & RT5350_TX_DLY_INT) + rt_tx_delay_intr(sc); + if (status & RT5350_INT_RXQ1_DONE) + rt_rx_intr(sc, 1); + if (status & RT5350_INT_RXQ0_DONE) + rt_rx_intr(sc, 0); + if (status & RT5350_INT_TXQ3_DONE) + rt_tx_intr(sc, 3); + if (status & RT5350_INT_TXQ2_DONE) + rt_tx_intr(sc, 2); + if (status & RT5350_INT_TXQ1_DONE) + rt_tx_intr(sc, 1); + if (status & RT5350_INT_TXQ0_DONE) + rt_tx_intr(sc, 0); +} + static void rt_tx_coherent_intr(struct rt_softc *sc) { @@ -1352,19 +1553,19 @@ rt_tx_coherent_intr(struct rt_softc *sc) sc->tx_coherent_interrupts++; /* restart DMA engine */ - tmp = RT_READ(sc, PDMA_BASE + PDMA_GLO_CFG); + tmp = RT_READ(sc, sc->pdma_glo_cfg); tmp &= ~(FE_TX_WB_DDONE | FE_TX_DMA_EN); - RT_WRITE(sc, PDMA_BASE + PDMA_GLO_CFG, tmp); + RT_WRITE(sc, sc->pdma_glo_cfg, tmp); for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) rt_reset_tx_ring(sc, &sc->tx_ring[i]); for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { - RT_WRITE(sc, PDMA_BASE + TX_BASE_PTR(i), + RT_WRITE(sc, sc->tx_base_ptr[i], sc->tx_ring[i].desc_phys_addr); - RT_WRITE(sc, PDMA_BASE + TX_MAX_CNT(i), + RT_WRITE(sc, sc->tx_max_cnt[i], RT_SOFTC_TX_RING_DESC_COUNT); - RT_WRITE(sc, PDMA_BASE + TX_CTX_IDX(i), 0); + RT_WRITE(sc, sc->tx_ctx_idx[i], 0); } rt_txrx_enable(sc); @@ -1377,24 +1578,29 @@ static void rt_rx_coherent_intr(struct rt_softc *sc) { uint32_t tmp; + int i; RT_DPRINTF(sc, RT_DEBUG_INTR, "Rx coherent interrupt\n"); sc->rx_coherent_interrupts++; /* restart DMA engine */ - tmp = RT_READ(sc, PDMA_BASE + PDMA_GLO_CFG); + tmp = RT_READ(sc, sc->pdma_glo_cfg); tmp &= ~(FE_RX_DMA_EN); - RT_WRITE(sc, PDMA_BASE + PDMA_GLO_CFG, tmp); + RT_WRITE(sc, sc->pdma_glo_cfg, tmp); /* init Rx ring */ - rt_reset_rx_ring(sc, &sc->rx_ring); - RT_WRITE(sc, PDMA_BASE + RX_BASE_PTR0, - sc->rx_ring.desc_phys_addr); - RT_WRITE(sc, PDMA_BASE + RX_MAX_CNT0, - RT_SOFTC_RX_RING_DATA_COUNT); - RT_WRITE(sc, PDMA_BASE + RX_CALC_IDX0, - RT_SOFTC_RX_RING_DATA_COUNT - 1); + for (i = 0; i < sc->rx_ring_count; i++) + rt_reset_rx_ring(sc, &sc->rx_ring[i]); + + for (i = 0; i < sc->rx_ring_count; i++) { + RT_WRITE(sc, sc->rx_base_ptr[i], + sc->rx_ring[i].desc_phys_addr); + RT_WRITE(sc, sc->rx_max_cnt[i], + RT_SOFTC_RX_RING_DATA_COUNT); + RT_WRITE(sc, sc->rx_calc_idx[i], + RT_SOFTC_RX_RING_DATA_COUNT - 1); + } rt_txrx_enable(sc); } @@ -1403,19 +1609,22 @@ rt_rx_coherent_intr(struct rt_softc *sc) * rt_rx_intr - a packet received */ static void -rt_rx_intr(struct rt_softc *sc) +rt_rx_intr(struct rt_softc *sc, int qid) { + KASSERT(qid >= 0 && qid < sc->rx_ring_count, + ("%s: Rx interrupt: invalid qid=%d\n", + device_get_nameunit(sc->dev), qid)); RT_DPRINTF(sc, RT_DEBUG_INTR, "Rx interrupt\n"); - sc->rx_interrupts++; + sc->rx_interrupts[qid]++; RT_SOFTC_LOCK(sc); - if (!(sc->intr_disable_mask & INT_RX_DONE)) { - rt_intr_disable(sc, INT_RX_DONE); + if (!(sc->intr_disable_mask & (sc->int_rx_done_mask << qid))) { + rt_intr_disable(sc, (sc->int_rx_done_mask << qid)); taskqueue_enqueue(sc->taskqueue, &sc->rx_done_task); } - sc->intr_pending_mask |= INT_RX_DONE; + sc->intr_pending_mask |= (sc->int_rx_done_mask << qid); RT_SOFTC_UNLOCK(sc); } @@ -1451,12 +1660,12 @@ rt_tx_intr(struct rt_softc *sc, int qid) sc->tx_interrupts[qid]++; RT_SOFTC_LOCK(sc); - if (!(sc->intr_disable_mask & (INT_TXQ0_DONE << qid))) { - rt_intr_disable(sc, (INT_TXQ0_DONE << qid)); + if (!(sc->intr_disable_mask & (sc->int_tx_done_mask << qid))) { + rt_intr_disable(sc, (sc->int_tx_done_mask << qid)); taskqueue_enqueue(sc->taskqueue, &sc->tx_done_task); } - sc->intr_pending_mask |= (INT_TXQ0_DONE << qid); + sc->intr_pending_mask |= (sc->int_tx_done_mask << qid); RT_SOFTC_UNLOCK(sc); } @@ -1478,18 +1687,18 @@ rt_rx_done_task(void *context, int pendi if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) return; - sc->intr_pending_mask &= ~INT_RX_DONE; + sc->intr_pending_mask &= ~sc->int_rx_done_mask; - again = rt_rx_eof(sc, sc->rx_process_limit); + again = rt_rx_eof(sc, &sc->rx_ring[0], sc->rx_process_limit); RT_SOFTC_LOCK(sc); - if ((sc->intr_pending_mask & INT_RX_DONE) || again) { + if ((sc->intr_pending_mask & sc->int_rx_done_mask) || again) { RT_DPRINTF(sc, RT_DEBUG_RX, "Rx done task: scheduling again\n"); taskqueue_enqueue(sc->taskqueue, &sc->rx_done_task); } else { - rt_intr_enable(sc, INT_RX_DONE); + rt_intr_enable(sc, sc->int_rx_done_mask); } RT_SOFTC_UNLOCK(sc); @@ -1515,8 +1724,8 @@ rt_tx_done_task(void *context, int pendi return; for (i = RT_SOFTC_TX_RING_COUNT - 1; i >= 0; i--) { - if (sc->intr_pending_mask & (INT_TXQ0_DONE << i)) { - sc->intr_pending_mask &= ~(INT_TXQ0_DONE << i); + if (sc->intr_pending_mask & (sc->int_tx_done_mask << i)) { + sc->intr_pending_mask &= ~(sc->int_tx_done_mask << i); rt_tx_eof(sc, &sc->tx_ring[i]); } } @@ -1525,7 +1734,15 @@ rt_tx_done_task(void *context, int pendi ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - intr_mask = ( + if(sc->rt_chipid == RT_CHIPID_RT5350 || + sc->rt_chipid == RT_CHIPID_MT7620) + intr_mask = ( + RT5350_INT_TXQ3_DONE | + RT5350_INT_TXQ2_DONE | + RT5350_INT_TXQ1_DONE | + RT5350_INT_TXQ0_DONE); + else + intr_mask = ( INT_TXQ3_DONE | INT_TXQ2_DONE | INT_TXQ1_DONE | @@ -1584,10 +1801,10 @@ rt_periodic_task(void *context, int pend * network subsystem. */ static int -rt_rx_eof(struct rt_softc *sc, int limit) +rt_rx_eof(struct rt_softc *sc, struct rt_softc_rx_ring *ring, int limit) { struct ifnet *ifp; - struct rt_softc_rx_ring *ring; +/* struct rt_softc_rx_ring *ring; */ struct rt_rxdesc *desc; struct rt_softc_rx_data *data; struct mbuf *m, *mnew; @@ -1597,12 +1814,12 @@ rt_rx_eof(struct rt_softc *sc, int limit int error, nsegs, len, nframes; ifp = sc->ifp; - ring = &sc->rx_ring; +/* ring = &sc->rx_ring[0]; */ nframes = 0; while (limit != 0) { - index = RT_READ(sc, PDMA_BASE + RX_DRX_IDX0); + index = RT_READ(sc, sc->rx_drx_idx[0]); if (ring->cur == index) break; @@ -1728,10 +1945,10 @@ skip: } if (ring->cur == 0) - RT_WRITE(sc, PDMA_BASE + RX_CALC_IDX0, + RT_WRITE(sc, sc->rx_calc_idx[0], RT_SOFTC_RX_RING_DATA_COUNT - 1); else - RT_WRITE(sc, PDMA_BASE + RX_CALC_IDX0, + RT_WRITE(sc, sc->rx_calc_idx[0], ring->cur - 1); RT_DPRINTF(sc, RT_DEBUG_RX, "Rx eof: nframes=%d\n", nframes); @@ -1760,7 +1977,7 @@ rt_tx_eof(struct rt_softc *sc, struct rt nframes = 0; for (;;) { - index = RT_READ(sc, PDMA_BASE + TX_DTX_IDX(ring->qid)); + index = RT_READ(sc, sc->tx_dtx_idx[ring->qid]); if (ring->desc_next == index) break; @@ -1834,12 +2051,13 @@ rt_watchdog(struct rt_softc *sc) #ifdef notyet int ntries; #endif + if(sc->rt_chipid != RT_CHIPID_RT5350 && + sc->rt_chipid != RT_CHIPID_MT7620) { + tmp = RT_READ(sc, PSE_BASE + CDMA_OQ_STA); - tmp = RT_READ(sc, PSE_BASE + CDMA_OQ_STA); - - RT_DPRINTF(sc, RT_DEBUG_WATCHDOG, "watchdog: PSE_IQ_STA=0x%08x\n", - tmp); - + RT_DPRINTF(sc, RT_DEBUG_WATCHDOG, + "watchdog: PSE_IQ_STA=0x%08x\n", tmp); + } /* XXX: do not reset */ #ifdef notyet if (((tmp >> P0_IQ_PCNT_SHIFT) & 0xff) != 0) { @@ -1896,7 +2114,7 @@ rt_intr_enable(struct rt_softc *sc, uint sc->intr_disable_mask &= ~intr_mask; tmp = sc->intr_enable_mask & ~sc->intr_disable_mask; - RT_WRITE(sc, GE_PORT_BASE + FE_INT_ENABLE, tmp); + RT_WRITE(sc, sc->fe_int_enable, tmp); } static void @@ -1906,7 +2124,7 @@ rt_intr_disable(struct rt_softc *sc, uin sc->intr_disable_mask |= intr_mask; tmp = sc->intr_enable_mask & ~sc->intr_disable_mask; - RT_WRITE(sc, GE_PORT_BASE + FE_INT_ENABLE, tmp); + RT_WRITE(sc, sc->fe_int_enable, tmp); } /* @@ -1923,7 +2141,7 @@ rt_txrx_enable(struct rt_softc *sc) /* enable Tx/Rx DMA engine */ for (ntries = 0; ntries < 200; ntries++) { - tmp = RT_READ(sc, PDMA_BASE + PDMA_GLO_CFG); + tmp = RT_READ(sc, sc->pdma_glo_cfg); if (!(tmp & (FE_TX_DMA_BUSY | FE_RX_DMA_BUSY))) break; @@ -1938,7 +2156,7 @@ rt_txrx_enable(struct rt_softc *sc) DELAY(50); tmp |= FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN; - RT_WRITE(sc, PDMA_BASE + PDMA_GLO_CFG, tmp); + RT_WRITE(sc, sc->pdma_glo_cfg, tmp); /* XXX set Rx filter */ return (0); @@ -1948,7 +2166,7 @@ rt_txrx_enable(struct rt_softc *sc) * rt_alloc_rx_ring - allocate RX DMA ring buffer */ static int -rt_alloc_rx_ring(struct rt_softc *sc, struct rt_softc_rx_ring *ring) +rt_alloc_rx_ring(struct rt_softc *sc, struct rt_softc_rx_ring *ring, int qid) { struct rt_rxdesc *desc; struct rt_softc_rx_data *data; @@ -2041,6 +2259,7 @@ rt_alloc_rx_ring(struct rt_softc *sc, st bus_dmamap_sync(ring->desc_dma_tag, ring->desc_dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + ring->qid = qid; return (0); fail: @@ -2352,7 +2571,7 @@ rt_sysctl_attach(struct rt_softc *sc) "Rx coherent interrupts"); SYSCTL_ADD_ULONG(ctx, SYSCTL_CHILDREN(stats), OID_AUTO, - "rx_interrupts", CTLFLAG_RD, &sc->rx_interrupts, + "rx_interrupts", CTLFLAG_RD, &sc->rx_interrupts[0], "Rx interrupts"); SYSCTL_ADD_ULONG(ctx, SYSCTL_CHILDREN(stats), OID_AUTO, @@ -2606,6 +2825,10 @@ static driver_t rt_driver = static devclass_t rt_dev_class; DRIVER_MODULE(rt, nexus, rt_driver, rt_dev_class, 0, 0); +#ifdef FDT +DRIVER_MODULE(rt, simplebus, rt_driver, rt_dev_class, 0, 0); +#endif + MODULE_DEPEND(rt, ether, 1, 1, 1); MODULE_DEPEND(rt, miibus, 1, 1, 1); Modified: head/sys/dev/rt/if_rtreg.h ============================================================================== --- head/sys/dev/rt/if_rtreg.h Thu Dec 24 18:40:10 2015 (r292703) +++ head/sys/dev/rt/if_rtreg.h Thu Dec 24 18:41:16 2015 (r292704) @@ -62,6 +62,7 @@ #define FC_DROP_CNT_SHIFT 16 #define PSE_RESET (1<<0) +/* RT305x interrupt registers */ #define FE_INT_STATUS 0x10 #define CNT_PPE_AF (1<<31) #define CNT_GDM_AF (1<<29) @@ -82,6 +83,21 @@ #define TX_DLY_INT (1<<1) /* TXQ[0|1]_DONE with delay */ #define RX_DLY_INT (1<<0) /* RX_DONE with delay */ #define FE_INT_ENABLE 0x14 + +/* RT5350 interrupt registers */ +#define RT5350_FE_INT_STATUS (RT5350_PDMA_BASE + 0x220) +#define RT5350_INT_RX_COHERENT (1<<31) +#define RT5350_RX_DLY_INT (1<<30) +#define RT5350_INT_TX_COHERENT (1<<29) +#define RT5350_TX_DLY_INT (1<<28) +#define RT5350_INT_RXQ1_DONE (1<<17) +#define RT5350_INT_RXQ0_DONE (1<<16) +#define RT5350_INT_TXQ3_DONE (1<<3) +#define RT5350_INT_TXQ2_DONE (1<<2) +#define RT5350_INT_TXQ1_DONE (1<<1) +#define RT5350_INT_TXQ0_DONE (1<<0) +#define RT5350_FE_INT_ENABLE (RT5350_PDMA_BASE + 0x228) + #define MDIO_CFG2 0x18 #define FOE_TS_T 0x1c #define PSE_FQ_PCNT_MASK 0xff000000 @@ -208,7 +224,9 @@ #define P0_IQ_PCNT_SHIFT 0 #define PDMA_BASE 0x0100 +#define RT5350_PDMA_BASE 0x0800 #define PDMA_GLO_CFG 0x00 +#define RT5350_PDMA_GLO_CFG 0x204 #define FE_TX_WB_DDONE (1<<6) #define FE_DMA_BT_SIZE4 (0<<4) #define FE_DMA_BT_SIZE8 (1<<4) @@ -218,6 +236,7 @@ #define FE_TX_DMA_BUSY (1<<1) #define FE_TX_DMA_EN (1<<0) #define PDMA_RST_IDX 0x04 +#define RT5350_PDMA_RST_IDX 0x208 #define FE_RST_DRX_IDX0 (1<<16) #define FE_RST_DTX_IDX3 (1<<3) #define FE_RST_DTX_IDX2 (1<<2) @@ -225,7 +244,9 @@ #define FE_RST_DTX_IDX0 (1<<0) #define PDMA_SCH_CFG 0x08 +#define RT5350_PDMA_SCH_CFG 0x280 #define DELAY_INT_CFG 0x0C +#define RT5350_DELAY_INT_CFG 0x20C #define TXDLY_INT_EN (1<<31) #define TXMAX_PINT_SHIFT 24 #define TXMAX_PTIME_SHIFT 16 @@ -263,6 +284,41 @@ #define TX_CTX_IDX(qid) (((qid>1)?(0x28):(0x18)) + (qid) * 16) #define TX_DTX_IDX(qid) (((qid>1)?(0x2c):(0x1c)) + (qid) * 16) +#define RT5350_TX_BASE_PTR0 0x000 +#define RT5350_TX_MAX_CNT0 0x004 +#define RT5350_TX_CTX_IDX0 0x008 +#define RT5350_TX_DTX_IDX0 0x00C + +#define RT5350_TX_BASE_PTR1 0x010 +#define RT5350_TX_MAX_CNT1 0x014 +#define RT5350_TX_CTX_IDX1 0x018 +#define RT5350_TX_DTX_IDX1 0x01C + +#define RT5350_TX_BASE_PTR2 0x020 +#define RT5350_TX_MAX_CNT2 0x024 +#define RT5350_TX_CTX_IDX2 0x028 +#define RT5350_TX_DTX_IDX2 0x02C + +#define RT5350_TX_BASE_PTR3 0x030 +#define RT5350_TX_MAX_CNT3 0x034 +#define RT5350_TX_CTX_IDX3 0x038 +#define RT5350_TX_DTX_IDX3 0x03C + +#define RT5350_RX_BASE_PTR0 0x100 +#define RT5350_RX_MAX_CNT0 0x104 +#define RT5350_RX_CALC_IDX0 0x108 +#define RT5350_RX_DRX_IDX0 0x10C + +#define RT5350_RX_BASE_PTR1 0x110 +#define RT5350_RX_MAX_CNT1 0x114 +#define RT5350_RX_CALC_IDX1 0x118 +#define RT5350_RX_DRX_IDX1 0x11C + +#define RT5350_TX_BASE_PTR(qid) ((qid) * 0x10 + 0x000) +#define RT5350_TX_MAX_CNT(qid) ((qid) * 0x10 + 0x004) +#define RT5350_TX_CTX_IDX(qid) ((qid) * 0x10 + 0x008) +#define RT5350_TX_DTX_IDX(qid) ((qid) * 0x10 + 0x00C) + #define PPE_BASE 0x0200 #define CNTR_BASE 0x0400 Modified: head/sys/dev/rt/if_rtvar.h ============================================================================== --- head/sys/dev/rt/if_rtvar.h Thu Dec 24 18:40:10 2015 (r292703) +++ head/sys/dev/rt/if_rtvar.h Thu Dec 24 18:41:16 2015 (r292704) @@ -68,6 +68,7 @@ mtx_assert(&(ring)->lock, MA_OWNED) #define RT_SOFTC_TX_RING_COUNT 4 +#define RT_SOFTC_RX_RING_COUNT 4 #ifndef IF_RT_RING_DATA_COUNT #define IF_RT_RING_DATA_COUNT 128 @@ -151,6 +152,7 @@ struct rt_softc_rx_ring bus_dmamap_t spare_dma_map; struct rt_softc_rx_data data[RT_SOFTC_RX_RING_DATA_COUNT]; int cur; + int qid; }; struct rt_softc_tx_data @@ -216,7 +218,7 @@ struct rt_softc unsigned long periodic_round; struct taskqueue *taskqueue; - struct rt_softc_rx_ring rx_ring; + struct rt_softc_rx_ring rx_ring[RT_SOFTC_RX_RING_COUNT]; struct rt_softc_tx_ring tx_ring[RT_SOFTC_TX_RING_COUNT]; int tx_ring_mgtqid; @@ -227,7 +229,7 @@ struct rt_softc unsigned long interrupts; unsigned long tx_coherent_interrupts; unsigned long rx_coherent_interrupts; - unsigned long rx_interrupts; + unsigned long rx_interrupts[RT_SOFTC_RX_RING_COUNT]; unsigned long rx_delay_interrupts; unsigned long tx_interrupts[RT_SOFTC_TX_RING_COUNT]; unsigned long tx_delay_interrupts; @@ -257,6 +259,25 @@ struct rt_softc #ifdef IF_RT_DEBUG int debug; #endif + + uint32_t rt_chipid; + /* chip specific registers config */ + int rx_ring_count; + uint32_t int_rx_done_mask; + uint32_t int_tx_done_mask; + uint32_t delay_int_cfg; + uint32_t fe_int_status; + uint32_t fe_int_enable; + uint32_t pdma_glo_cfg; + uint32_t pdma_rst_idx; + uint32_t tx_base_ptr[RT_SOFTC_TX_RING_COUNT]; + uint32_t tx_max_cnt[RT_SOFTC_TX_RING_COUNT]; + uint32_t tx_ctx_idx[RT_SOFTC_TX_RING_COUNT]; + uint32_t tx_dtx_idx[RT_SOFTC_TX_RING_COUNT]; + uint32_t rx_base_ptr[RT_SOFTC_RX_RING_COUNT]; + uint32_t rx_max_cnt[RT_SOFTC_RX_RING_COUNT]; + uint32_t rx_calc_idx[RT_SOFTC_RX_RING_COUNT]; + uint32_t rx_drx_idx[RT_SOFTC_RX_RING_COUNT]; }; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512241841.tBOIfHFe064302>