diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/ChangeLog b/ThirdParty/sw_services/lwip140_v2_4/src/ChangeLog index 1ff2cc60..15594944 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/ChangeLog +++ b/ThirdParty/sw_services/lwip140_v2_4/src/ChangeLog @@ -1,5 +1,8 @@ Change Log for lwip ================================= +2014-9-12 + * Created a new version lwip140_v2_4. + * It has CR fixes for 827638, 830976, 828866. 2014-12-11 * Fixed the bug in the emaclite on zynq. Added the parameter use_emaclite_on_zynq to the mld file. diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xadapter.h b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xadapter.h index b473336a..25c476a4 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xadapter.h +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xadapter.h @@ -56,7 +56,7 @@ struct xemac_s { int topology_index; void *state; #if !NO_SYS - sys_sem_t sem_rx_data_available; + sys_sem_t sem_rx_data_available; #endif }; diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xemacpsif.h b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xemacpsif.h index 00dcc85a..8c59e687 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xemacpsif.h +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/include/netif/xemacpsif.h @@ -40,6 +40,7 @@ extern "C" { #include "xlwipconfig.h" #include "lwip/netif.h" #include "netif/etharp.h" +#include "lwip/sys.h" #include "netif/xadapter.h" #include "xstatus.h" @@ -63,10 +64,7 @@ extern "C" { void xemacpsif_setmac(u32_t index, u8_t *addr); u8_t* xemacpsif_getmac(u32_t index); err_t xemacpsif_init(struct netif *netif); -int xemacpsif_input(struct netif *netif); -#ifdef NOTNOW_BHILL -unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp); -#endif +s32_t xemacpsif_input(struct netif *netif); /* xaxiemacif_hw.c */ void xemacps_error_handler(XEmacPs * Temac); @@ -91,13 +89,13 @@ typedef struct { extern xemacpsif_s xemacpsif; -int is_tx_space_available(xemacpsif_s *emac); +s32_t is_tx_space_available(xemacpsif_s *emac); -/* xaxiemacif_dma.c */ +/* xemacpsif_dma.c */ -XStatus init_axi_dma(struct xemac_s *xemac); void process_sent_bds(XEmacPs_BdRing *txring); -unsigned Phy_Setup (XEmacPs *xemacpsp); +u32_t phy_setup (XEmacPs *xemacpsp, u32_t phy_addr); +void detect_phy(XEmacPs *xemacpsp); void emacps_send_handler(void *arg); XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p); void emacps_recv_handler(void *arg); @@ -110,8 +108,8 @@ void init_emacps(xemacpsif_s *xemacps, struct netif *netif); void setup_isr (struct xemac_s *xemac); XStatus init_dma(struct xemac_s *xemac); void start_emacps (xemacpsif_s *xemacps); -void FreeTxRxPBufs(void); -void FreeOnlyTxPBufs(void); +void free_txrx_pbufs(void); +void free_onlytx_pbufs(void); void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif); void clean_dma_txdescs(struct xemac_s *xemac); void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif); diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif.c b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif.c index 24c79e45..b5869ced 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif.c +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif.c @@ -85,7 +85,7 @@ static u8_t xemacps_mcast_entry_mask = 0; XEmacPs_Config *mac_config; struct netif *NetIf; -void FreeTxPBufs(void); + /* * this function is always called with interrupts off * this function also assumes that there are available BD's @@ -129,27 +129,33 @@ static err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif, static err_t low_level_output(struct netif *netif, struct pbuf *p) { SYS_ARCH_DECL_PROTECT(lev); - err_t err; + err_t err; + s32_t freecnt; + XEmacPs_BdRing *txring; struct xemac_s *xemac = (struct xemac_s *)(netif->state); xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); SYS_ARCH_PROTECT(lev); - /* check if space is available to send */ - if (is_tx_space_available(xemacpsif)) { + freecnt = is_tx_space_available(xemacpsif); + if (freecnt <= 5) { + txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + process_sent_bds(txring); + } + + if (is_tx_space_available(xemacpsif)) { _unbuffered_low_level_output(xemacpsif, p); err = ERR_OK; } else { #if LINK_STATS lwip_stats.link.drop++; #endif - print("pack dropped, no space\r\n"); + printf("pack dropped, no space\r\n"); err = ERR_MEM; } - SYS_ARCH_UNPROTECT(lev); return err; } @@ -205,7 +211,7 @@ static err_t xemacpsif_output(struct netif *netif, struct pbuf *p, * */ -int xemacpsif_input(struct netif *netif) +s32_t xemacpsif_input(struct netif *netif) { struct eth_hdr *ethhdr; struct pbuf *p; @@ -215,45 +221,45 @@ int xemacpsif_input(struct netif *netif) while (1) #endif { - /* move received packet into a new pbuf */ - SYS_ARCH_PROTECT(lev); - p = low_level_input(netif); - SYS_ARCH_UNPROTECT(lev); + /* move received packet into a new pbuf */ + SYS_ARCH_PROTECT(lev); + p = low_level_input(netif); + SYS_ARCH_UNPROTECT(lev); - /* no packet could be read, silently ignore this */ - if (p == NULL) { - return 0; - } + /* no packet could be read, silently ignore this */ + if (p == NULL) { + return 0; + } - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = p->payload; + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; -#if LINK_STATS - lwip_stats.link.recv++; -#endif /* LINK_STATS */ + #if LINK_STATS + lwip_stats.link.recv++; + #endif /* LINK_STATS */ - switch (htons(ethhdr->type)) { - /* IP or ARP packet? */ - case ETHTYPE_IP: - case ETHTYPE_ARP: -#if PPPOE_SUPPORT - /* PPPoE packet? */ - case ETHTYPE_PPPOEDISC: - case ETHTYPE_PPPOE: -#endif /* PPPOE_SUPPORT */ - /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n")); + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: + #if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: + #endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n")); + pbuf_free(p); + p = NULL; + } + break; + + default: pbuf_free(p); p = NULL; - } - break; - - default: - pbuf_free(p); - p = NULL; - break; - } + break; + } } return 1; @@ -262,12 +268,12 @@ int xemacpsif_input(struct netif *netif) static err_t low_level_init(struct netif *netif) { - unsigned mac_address = (unsigned)(netif->state); + u32_t mac_address = (u32_t)(netif->state); struct xemac_s *xemac; xemacpsif_s *xemacpsif; u32 dmacrreg; - int Status = XST_SUCCESS; + s32_t status = XST_SUCCESS; NetIf = netif; @@ -312,9 +318,9 @@ static err_t low_level_init(struct netif *netif) /* obtain config of this emac */ mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)netif->state); - Status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, + status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, mac_config->BaseAddress); - if (Status != XST_SUCCESS) { + if (status != XST_SUCCESS) { xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__); } @@ -342,17 +348,17 @@ static err_t low_level_init(struct netif *netif) void HandleEmacPsError(struct xemac_s *xemac) { xemacpsif_s *xemacpsif; - int Status = XST_SUCCESS; + s32_t status = XST_SUCCESS; u32 dmacrreg; SYS_ARCH_DECL_PROTECT(lev); SYS_ARCH_PROTECT(lev); - FreeTxRxPBufs(); + free_txrx_pbufs(); xemacpsif = (xemacpsif_s *)(xemac->state); - Status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, + status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, mac_config->BaseAddress); - if (Status != XST_SUCCESS) { + if (status != XST_SUCCESS) { xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__); } /* initialize the mac */ @@ -382,7 +388,7 @@ void HandleTxErrors(struct xemac_s *xemac) netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, netctrlreg); - FreeOnlyTxPBufs(); + free_onlytx_pbufs(); clean_dma_txdescs(xemac); netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_dma.c b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_dma.c index 6fb29cdf..3a7bd81a 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_dma.c +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_dma.c @@ -53,9 +53,6 @@ #include "timers.h" #endif -/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c - *** to run it on a PEEP board - ***/ #define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR #define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR @@ -63,11 +60,55 @@ /* Byte alignment of BDs */ #define BD_ALIGNMENT (XEMACPS_DMABD_MINIMUM_ALIGNMENT*2) -static int tx_pbufs_storage[XLWIP_CONFIG_N_TX_DESC]; -static int rx_pbufs_storage[XLWIP_CONFIG_N_RX_DESC]; +static s32_t tx_pbufs_storage[XLWIP_CONFIG_N_TX_DESC]; +static s32_t rx_pbufs_storage[XLWIP_CONFIG_N_RX_DESC]; -static int EmacIntrNum; -extern u8 _end; +static s32_t emac_intr_num; + +/****************************************************************************** + * Each BD is of 8 bytes of size and the BDs (BD chain) need to be put + * at uncached memory location. If they are not put at uncached + * locations, the user needs to flush or invalidate for each BD/packet. + * However, the flush or invalidate can happen over a cache line which can + * span multiple BDs. This means a flush or invalidate of one BD can actually + * flush/invalidate multiple BDs adjacent to the targeted BD.Assuming that + * the user and hardware both update the BD fields, this operation from user + * can potentially overwrite the updates done by hardware or user. + * To avoid this, it is always safe to put the BD chains for Rx and tx side + * at uncached memory location. + * + * The Xilinx standalone BSP for Cortex A9 implements only primary page tables. + * Each table entry corresponds to 1 MB of address map. This means, if a memory + * region has to be made uncached, the minimum granularity will be of 1 MB. + * + * The implementation below allocates a 1 MB of u8 array aligned to 1 MB. + * This ensures that this array is put at 1 MB aligned memory (e.g. 0x1200000) + * and accupies memory of 1 MB. The init_dma function then changes 1 MB of this + * region to make it uncached (strongly ordered). + * This increases the bss section of the program significantly and can be a + * wastage of memory. The reason beings, BDs will hardly occupy few KBs of + * memory and the rest of 1 MB of memory will be unused. + * + * If a program uses other peripherals that have DMAs/bus masters and need + * uncached memory, they may also end of following the same approach. This + * definitely aggravates the memory wastage issue. To avoid all this, the user + * can create a new 1 MB section in the linker script and reserve it for such + * use cases that need uncached memory location. They can then have their own + * memory allocation logic in their application that allocates uncached memory + * from this 1 MB location. For such a case, changes need to be done in this + * file and appropriate uncached memory allocated through other means can be + * used. + * + * The present implementation here allocates 1 MB of uncached memory. It + * reserves of 64 KB of memory for each BD chain. 64 KB of memory means 8192 of + * BDs for each BD chain which is more than enough for any application. + * Assuming that both emac0 and emac1 are present, 256 KB of memory is allocated + * for BDs. The rest 768 KB of memory is just unused. + *********************************************************************************/ + +u8_t bd_space[0x100000] __attribute__ ((aligned (0x100000))); +static volatile u32_t bd_space_index = 0; +static volatile u32_t bd_space_attr_set = 0; #ifdef OS_IS_FREERTOS long xInsideISR = 0; @@ -77,10 +118,10 @@ long xInsideISR = 0; (((u32)bdptr - (u32)(ringptr)->BaseBdAddr) / (ringptr)->Separation) -int is_tx_space_available(xemacpsif_s *emac) +s32_t is_tx_space_available(xemacpsif_s *emac) { XEmacPs_BdRing *txring; - int freecnt = 0; + s32_t freecnt = 0; txring = &(XEmacPs_GetTxRing(&emac->emacps)); @@ -92,13 +133,13 @@ int is_tx_space_available(xemacpsif_s *emac) void process_sent_bds(XEmacPs_BdRing *txring) { XEmacPs_Bd *txbdset; - XEmacPs_Bd *CurBdPntr; - int n_bds; - XStatus Status; - int n_pbufs_freed = 0; - unsigned int BdIndex; + XEmacPs_Bd *curbdpntr; + s32_t n_bds; + XStatus status; + s32_t n_pbufs_freed = 0; + u32_t bdindex; struct pbuf *p; - unsigned int *Temp; + u32_t *temp; while (1) { /* obtain processed BD's */ @@ -109,29 +150,29 @@ void process_sent_bds(XEmacPs_BdRing *txring) } /* free the processed BD's */ n_pbufs_freed = n_bds; - CurBdPntr = txbdset; + curbdpntr = txbdset; while (n_pbufs_freed > 0) { - BdIndex = XEMACPS_BD_TO_INDEX(txring, CurBdPntr); - Temp = (unsigned int *)CurBdPntr; - *Temp = 0; - Temp++; - *Temp = 0x80000000; - if (BdIndex == (XLWIP_CONFIG_N_TX_DESC - 1)) { - *Temp = 0xC0000000; + bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr); + temp = (u32_t *)curbdpntr; + *temp = 0; + temp++; + *temp = 0x80000000; + if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) { + *temp = 0xC0000000; } - p = (struct pbuf *)tx_pbufs_storage[BdIndex]; + p = (struct pbuf *)tx_pbufs_storage[bdindex]; if(p != NULL) { pbuf_free(p); } - tx_pbufs_storage[BdIndex] = 0; - CurBdPntr = XEmacPs_BdRingNext(txring, CurBdPntr); + tx_pbufs_storage[bdindex] = 0; + curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr); n_pbufs_freed--; dsb(); } - Status = XEmacPs_BdRingFree(txring, n_bds, txbdset); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingFree(txring, n_bds, txbdset); + if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n")); } } @@ -142,19 +183,19 @@ void emacps_send_handler(void *arg) { struct xemac_s *xemac; xemacpsif_s *xemacpsif; - XEmacPs_BdRing *TxRingPtr; - unsigned int regval; + XEmacPs_BdRing *txringptr; + u32_t regval; #ifdef OS_IS_FREERTOS xInsideISR++; #endif xemac = (struct xemac_s *)(arg); xemacpsif = (xemacpsif_s *)(xemac->state); - TxRingPtr = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); + txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval); /* If Transmit done interrupt is asserted, process completed BD's */ - process_sent_bds(TxRingPtr); + process_sent_bds(txringptr); #ifdef OS_IS_FREERTOS xInsideISR--; #endif @@ -163,21 +204,17 @@ void emacps_send_handler(void *arg) XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p) { struct pbuf *q; - int n_pbufs; + s32_t n_pbufs; XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL; XEmacPs_Bd *temp_txbd; - XStatus Status; + XStatus status; XEmacPs_BdRing *txring; - unsigned int BdIndex; - unsigned int lev; + u32_t bdindex; + u32_t lev; lev = mfcpsr(); mtcpsr(lev | 0x000000C0); -#ifdef PEEP - while((XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress, - XEMACPS_TXSR_OFFSET)) & 0x08); -#endif txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); /* first count the number of pbufs */ @@ -185,25 +222,25 @@ XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p) n_pbufs++; /* obtain as many BD's */ - Status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset); + if (status != XST_SUCCESS) { mtcpsr(lev); LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n")); - return ERR_IF; + return XST_FAILURE; } for(q = p, txbd = txbdset; q != NULL; q = q->next) { - BdIndex = XEMACPS_BD_TO_INDEX(txring, txbd); - if (tx_pbufs_storage[BdIndex] != 0) { + bdindex = XEMACPS_BD_TO_INDEX(txring, txbd); + if (tx_pbufs_storage[bdindex] != 0) { mtcpsr(lev); LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n")); - return ERR_IF; + return XST_FAILURE; } /* Send the data from the pbuf to the interface, one pbuf at a time. The size of the data in each pbuf is kept in the ->len variable. */ - Xil_DCacheFlushRange((unsigned int)q->payload, (unsigned)q->len); + Xil_DCacheFlushRange((u32_t)q->payload, (u32_t)q->len); XEmacPs_BdSetAddressTx(txbd, (u32)q->payload); if (q->len > (XEMACPS_MAX_FRAME_SIZE - 18)) @@ -211,16 +248,14 @@ XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p) else XEmacPs_BdSetLength(txbd, q->len & 0x3FFF); - tx_pbufs_storage[BdIndex] = (int)q; + tx_pbufs_storage[bdindex] = (s32_t)q; pbuf_ref(q); last_txbd = txbd; XEmacPs_BdClearLast(txbd); - dsb(); txbd = XEmacPs_BdRingNext(txring, txbd); } XEmacPs_BdSetLast(last_txbd); - dsb(); /* For fragmented packets, remember the 1st BD allocated for the 1st packet fragment. The used bit for this BD should be cleared at the end after clearing out used bits for other fragments. For packets without @@ -234,89 +269,88 @@ XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p) txbd = XEmacPs_BdRingNext(txring, txbd); } XEmacPs_BdClearTxUsed(temp_txbd); - dsb(); - Status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset); + if (status != XST_SUCCESS) { mtcpsr(lev); LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n")); - return ERR_IF; + return XST_FAILURE; } - dsb(); /* Start transmit */ XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, (XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress, XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK)); - dsb(); + mtcpsr(lev); - return Status; + return status; } void setup_rx_bds(XEmacPs_BdRing *rxring) { XEmacPs_Bd *rxbd; - XStatus Status; + XStatus status; struct pbuf *p; - unsigned int FreeBds; - unsigned int BdIndex; - unsigned int *Temp; - - FreeBds = XEmacPs_BdRingGetFreeCnt (rxring); - while (FreeBds > 0) { - FreeBds--; - Status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd); - if (Status != XST_SUCCESS) { - LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n")); - return; - } - BdIndex = XEMACPS_BD_TO_INDEX(rxring, rxbd); - Temp = (unsigned int *)rxbd; - *Temp = 0; - if (BdIndex == (XLWIP_CONFIG_N_RX_DESC - 1)) { - *Temp = 0x00000002; - } - Temp++; - *Temp = 0; + u32_t freebds; + u32_t bdindex; + u32_t *temp; + freebds = XEmacPs_BdRingGetFreeCnt (rxring); + while (freebds > 0) { + freebds--; p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL); if (!p) { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif - LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n")); - XEmacPs_BdRingUnAlloc(rxring, 1, rxbd); - dsb(); + printf("unable to alloc pbuf in recv_handler\r\n"); return; } - XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload); - dsb(); - - rx_pbufs_storage[BdIndex] = (int)p; - Status = XEmacPs_BdRingToHw(rxring, 1, rxbd); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n")); + pbuf_free(p); + return; + } + status = XEmacPs_BdRingToHw(rxring, 1, rxbd); + if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: ")); - if (Status == XST_DMA_SG_LIST_ERROR) + if (status == XST_DMA_SG_LIST_ERROR) LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n")); else LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n")); + + pbuf_free(p); + XEmacPs_BdRingUnAlloc(rxring, 1, rxbd); return; } + Xil_DCacheInvalidateRange((u32_t)p->payload, (u32_t)XEMACPS_MAX_FRAME_SIZE); + bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd); + temp = (u32_t *)rxbd; + *temp = 0; + if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) { + *temp = 0x00000002; + } + temp++; + *temp = 0; + + XEmacPs_BdSetAddressRx(rxbd, (u32_t)p->payload); + rx_pbufs_storage[bdindex] = (s32_t)p; } } void emacps_recv_handler(void *arg) { struct pbuf *p; - XEmacPs_Bd *rxbdset, *CurBdPtr; + XEmacPs_Bd *rxbdset, *curbdptr; struct xemac_s *xemac; xemacpsif_s *xemacpsif; XEmacPs_BdRing *rxring; - volatile int bd_processed; - int rx_bytes, k; - unsigned int BdIndex; - unsigned int regval; + volatile s32_t bd_processed; + s32_t rx_bytes, k; + u32_t bdindex; + u32_t regval; xemac = (struct xemac_s *)(arg); xemacpsif = (xemacpsif_s *)(xemac->state); @@ -337,22 +371,21 @@ void emacps_recv_handler(void *arg) while(1) { bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset); - if (bd_processed <= 0) { break; } - for (k = 0, CurBdPtr=rxbdset; k < bd_processed; k++) { + for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) { - BdIndex = XEMACPS_BD_TO_INDEX(rxring, CurBdPtr); - p = (struct pbuf *)rx_pbufs_storage[BdIndex]; + bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr); + p = (struct pbuf *)rx_pbufs_storage[bdindex]; /* * Adjust the buffer size to the actual number of bytes received. */ - rx_bytes = XEmacPs_BdGetLength(CurBdPtr); + rx_bytes = XEmacPs_BdGetLength(curbdptr); pbuf_realloc(p, rx_bytes); - Xil_DCacheInvalidateRange((unsigned int)p->payload, (unsigned)XEMACPS_MAX_FRAME_SIZE); + /* store it in the receive queue, * where it'll be processed by a different handler */ @@ -367,7 +400,7 @@ void emacps_recv_handler(void *arg) sys_sem_signal(&xemac->sem_rx_data_available); #endif } - CurBdPtr = XEmacPs_BdRingNext( rxring, CurBdPtr); + curbdptr = XEmacPs_BdRingNext( rxring, curbdptr); } /* free up the BD's */ XEmacPs_BdRingFree(rxring, bd_processed, rxbdset); @@ -382,61 +415,62 @@ void emacps_recv_handler(void *arg) void clean_dma_txdescs(struct xemac_s *xemac) { - XEmacPs_Bd BdTemplate; - XEmacPs_BdRing *TxRingPtr; + XEmacPs_Bd bdtemplate; + XEmacPs_BdRing *txringptr; xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); - TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps); + txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps); - XEmacPs_BdClear(&BdTemplate); - XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK); + XEmacPs_BdClear(&bdtemplate); + XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK); /* * Create the TxBD ring */ - XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace, + XEmacPs_BdRingCreate(txringptr, (u32) xemacpsif->tx_bdspace, (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_TX_DESC); - XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND); + XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND); } - XStatus init_dma(struct xemac_s *xemac) { - XEmacPs_Bd BdTemplate; - XEmacPs_BdRing *RxRingPtr, *TxRingPtr; + XEmacPs_Bd bdtemplate; + XEmacPs_BdRing *rxringptr, *txringptr; XEmacPs_Bd *rxbd; struct pbuf *p; - XStatus Status; - int i; - unsigned int BdIndex; - char *endAdd = &_end; - /* - * Align the BD starte address to 1 MB boundary. - */ - char *endAdd_aligned = (char *)(((int)endAdd + 0x100000) & (~0xFFFFF)); + XStatus status; + s32_t i; + u32_t bdindex; + volatile u32_t tempaddress; + xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; /* * The BDs need to be allocated in uncached memory. Hence the 1 MB - * address range that starts at address 0xFF00000 is made uncached + * address range allocated for Bd_Space is made uncached * by setting appropriate attributes in the translation table. + * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures + * a reserved uncached area used only for BDs. */ - Xil_SetTlbAttributes((int)endAdd_aligned, 0xc02); // addr, attr + if (bd_space_attr_set == 0) { + Xil_SetTlbAttributes((s32_t)bd_space, 0xc02); // addr, attr + bd_space_attr_set = 1; + } - RxRingPtr = &XEmacPs_GetRxRing(&xemacpsif->emacps); - TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps); - LWIP_DEBUGF(NETIF_DEBUG, ("RxRingPtr: 0x%08x\r\n", RxRingPtr)); - LWIP_DEBUGF(NETIF_DEBUG, ("TxRingPtr: 0x%08x\r\n", TxRingPtr)); + rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps); + txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps); + LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr)); + LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr)); - xemacpsif->rx_bdspace = (void *)endAdd_aligned; - /* - * We allocate 65536 bytes for Rx BDs which can accomodate a - * maximum of 8192 BDs which is much more than any application - * will ever need. - */ - xemacpsif->tx_bdspace = (void *)(endAdd_aligned + 0x10000); + /* Allocate 64k for Rx and Tx bds each to take care of extreme cases */ + tempaddress = (u32_t)&(bd_space[bd_space_index]); + xemacpsif->rx_bdspace = (void *)tempaddress; + bd_space_index += 0x10000; + tempaddress = (u32_t)&(bd_space[bd_space_index]); + xemacpsif->tx_bdspace = (void *)tempaddress; + bd_space_index += 0x10000; LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: 0x%08x\r\n", xemacpsif->rx_bdspace)); LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: 0x%08x\r\n", xemacpsif->tx_bdspace)); @@ -444,7 +478,7 @@ XStatus init_dma(struct xemac_s *xemac) if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) { xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors", __FILE__, __LINE__); - return XST_FAILURE; + return ERR_IF; } /* @@ -453,43 +487,43 @@ XStatus init_dma(struct xemac_s *xemac) * Setup a BD template for the Rx channel. This template will be copied to * every RxBD. We will not have to explicitly set these again. */ - XEmacPs_BdClear(&BdTemplate); + XEmacPs_BdClear(&bdtemplate); /* * Create the RxBD ring */ - Status = XEmacPs_BdRingCreate(RxRingPtr, (u32) xemacpsif->rx_bdspace, + status = XEmacPs_BdRingCreate(rxringptr, (u32) xemacpsif->rx_bdspace, (u32) xemacpsif->rx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_RX_DESC); - if (Status != XST_SUCCESS) { + if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n")); - return XST_FAILURE; + return ERR_IF; } - Status = XEmacPs_BdRingClone(RxRingPtr, &BdTemplate, XEMACPS_RECV); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV); + if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n")); - return XST_FAILURE; + return ERR_IF; } - XEmacPs_BdClear(&BdTemplate); - XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK); + XEmacPs_BdClear(&bdtemplate); + XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK); /* * Create the TxBD ring */ - Status = XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace, + status = XEmacPs_BdRingCreate(txringptr, (u32) xemacpsif->tx_bdspace, (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_TX_DESC); - if (Status != XST_SUCCESS) { - return XST_FAILURE; + if (status != XST_SUCCESS) { + return ERR_IF; } /* We reuse the bd template, as the same one will work for both rx and tx. */ - Status = XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND); + if (status != XST_SUCCESS) { return ERR_IF; } @@ -497,33 +531,35 @@ XStatus init_dma(struct xemac_s *xemac) * Allocate RX descriptors, 1 RxBD at a time. */ for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) { - Status = XEmacPs_BdRingAlloc(RxRingPtr, 1, &rxbd); - if (Status != XST_SUCCESS) { - LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n")); - return ERR_IF; - } - p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL); if (!p) { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif - LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n")); - return -1; + printf("unable to alloc pbuf in init_dma\r\n"); + return ERR_IF; + } + status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd); + if (status != XST_SUCCESS) { + LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n")); + pbuf_free(p); + return ERR_IF; } - - XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload); - - BdIndex = XEMACPS_BD_TO_INDEX(RxRingPtr, rxbd); - rx_pbufs_storage[BdIndex] = (int)p; - /* Enqueue to HW */ - Status = XEmacPs_BdRingToHw(RxRingPtr, 1, rxbd); - if (Status != XST_SUCCESS) { + status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd); + if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n")); - return XST_FAILURE; + pbuf_free(p); + XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd); + return ERR_IF; } + + Xil_DCacheInvalidateRange((u32_t)p->payload, (u32_t)XEMACPS_MAX_FRAME_SIZE); + XEmacPs_BdSetAddressRx(rxbd, (u32_t)p->payload); + + bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd); + rx_pbufs_storage[bdindex] = (s32_t)p; } /* @@ -538,7 +574,7 @@ XStatus init_dma(struct xemac_s *xemac) * Enable the interrupt for emacps. */ XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr); - EmacIntrNum = (u32) xtopologyp->scugic_emac_intr; + emac_intr_num = (u32) xtopologyp->scugic_emac_intr; return 0; } @@ -558,8 +594,8 @@ XStatus init_dma(struct xemac_s *xemac) void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif) { - unsigned long regctrl; - unsigned long tempcntr; + u32_t regctrl; + u32_t tempcntr; tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET); if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) { @@ -575,46 +611,46 @@ void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif) xemacpsif->last_rx_frms_cntr = tempcntr; } -void FreeTxRxPBufs(void) +void free_txrx_pbufs(void) { - int Index; + s32_t index; struct pbuf *p; - for (Index = 0; Index < XLWIP_CONFIG_N_TX_DESC; Index++) { - if (tx_pbufs_storage[Index] != 0) { - p = (struct pbuf *)tx_pbufs_storage[Index]; + for (index = 0; index < XLWIP_CONFIG_N_TX_DESC; index++) { + if (tx_pbufs_storage[index] != 0) { + p = (struct pbuf *)tx_pbufs_storage[index]; pbuf_free(p); - tx_pbufs_storage[Index] = 0; + tx_pbufs_storage[index] = 0; } } - for (Index = 0; Index < XLWIP_CONFIG_N_RX_DESC; Index++) { - p = (struct pbuf *)rx_pbufs_storage[Index]; + for (index = 0; index < XLWIP_CONFIG_N_RX_DESC; index++) { + p = (struct pbuf *)rx_pbufs_storage[index]; pbuf_free(p); } } -void FreeOnlyTxPBufs(void) +void free_onlytx_pbufs(void) { - int Index; + s32_t index; struct pbuf *p; - for (Index = 0; Index < XLWIP_CONFIG_N_TX_DESC; Index++) { - if (tx_pbufs_storage[Index] != 0) { - p = (struct pbuf *)tx_pbufs_storage[Index]; + for (index = 0; index < XLWIP_CONFIG_N_TX_DESC; index++) { + if (tx_pbufs_storage[index] != 0) { + p = (struct pbuf *)tx_pbufs_storage[index]; pbuf_free(p); - tx_pbufs_storage[Index] = 0; + tx_pbufs_storage[index] = 0; } } } -void EmacDisableIntr(void) +void emac_disable_intr(void) { - XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, EmacIntrNum); + XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, emac_intr_num); } -void EmacEnableIntr(void) +void emac_enable_intr(void) { - XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, EmacIntrNum); + XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, emac_intr_num); } diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_hw.c b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_hw.c index daefa382..11331ac5 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_hw.c +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_hw.c @@ -33,34 +33,42 @@ #include "netif/xemacpsif.h" #include "lwipopts.h" -/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c - *** to run it on a PEEP board - ***/ +#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \ + XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 +#define PCM_PMA_CORE_PRESENT +#else +#undef PCM_PMA_CORE_PRESENT +#endif -unsigned int link_speed = 100; +u32_t link_speed = 100; +extern XEmacPs_Config XEmacPs_ConfigTable[]; +extern u32_t phymapemac0[32]; +extern u32_t phymapemac1[32]; XEmacPs_Config *xemacps_lookup_config(unsigned mac_base) { - extern XEmacPs_Config XEmacPs_ConfigTable[]; - XEmacPs_Config *CfgPtr = NULL; - int i; + XEmacPs_Config *cfgptr = NULL; + s32_t i; for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) { if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) { - CfgPtr = &XEmacPs_ConfigTable[i]; + cfgptr = &XEmacPs_ConfigTable[i]; break; } } - return (CfgPtr); + return (cfgptr); } void init_emacps(xemacpsif_s *xemacps, struct netif *netif) { - unsigned mac_address = (unsigned)(netif->state); + u32_t mac_address = (u32_t)(netif->state); XEmacPs *xemacpsp; XEmacPs_Config *mac_config; - int Status = XST_SUCCESS; + s32_t status = XST_SUCCESS; + u32_t i; + u32_t phyfoundforemac0 = FALSE; + u32_t phyfoundforemac1 = FALSE; /* obtain config of this emac */ mac_config = (XEmacPs_Config *)xemacps_lookup_config(mac_address); @@ -68,26 +76,68 @@ void init_emacps(xemacpsif_s *xemacps, struct netif *netif) xemacpsp = &xemacps->emacps; /* set mac address */ - Status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); - if (Status != XST_SUCCESS) { + status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); + if (status != XST_SUCCESS) { xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__); } + XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224); - link_speed = Phy_Setup(xemacpsp); + +/* Please refer to file header comments for the file xemacpsif_physpeed.c + * to know more about the PHY programming sequence. + * For PCS PMA core, phy_setup is called with the predefined PHY address + * exposed through xaparemeters.h + * For RGMII case, assuming multiple PHYs can be present on the MDIO bus, + * detect_phy is called to get the addresses of the PHY present on + * a particular MDIO bus (emac0 or emac1). This address map is populated + * in phymapemac0 or phymapemac1. + * phy_setup is then called for each PHY present on the MDIO bus. + */ +#ifdef PCM_PMA_CORE_PRESENT +#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT + link_speed = phy_setup(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR); +#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT + link_speed = phy_setup(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR); +#endif +#else + detect_phy(xemacpsp); + for (i = 31; i > 0; i--) { + if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { + if (phymapemac0[i] == TRUE) { + link_speed = phy_setup(xemacpsp, i); + phyfoundforemac0 = TRUE; + } + } else { + if (phymapemac1[i] == TRUE) { + link_speed = phy_setup(xemacpsp, i); + phyfoundforemac1 = TRUE; + } + } + } + /* If no PHY was detected, use broadcast PHY address of 0 */ + if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) { + if (phyfoundforemac0 == FALSE) + link_speed = phy_setup(xemacpsp, 0); + } else { + if (phyfoundforemac1 == FALSE) + link_speed = phy_setup(xemacpsp, 0); + } +#endif + XEmacPs_SetOperatingSpeed(xemacpsp, link_speed); /* Setting the operating speed of the MAC needs a delay. */ { - volatile int wait; + volatile s32_t wait; for (wait=0; wait < 20000; wait++); } } void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif) { - unsigned mac_address = (unsigned)(netif->state); + u32_t mac_address = (u32_t)(netif->state); XEmacPs *xemacpsp; XEmacPs_Config *mac_config; - int Status = XST_SUCCESS; + s32_t status = XST_SUCCESS; /* obtain config of this emac */ mac_config = (XEmacPs_Config *)xemacps_lookup_config(mac_address); @@ -95,8 +145,8 @@ void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif) xemacpsp = &xemacps->emacps; /* set mac address */ - Status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); - if (Status != XST_SUCCESS) { + status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1); + if (status != XST_SUCCESS) { xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__); } @@ -104,7 +154,7 @@ void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif) /* Setting the operating speed of the MAC needs a delay. */ { - volatile int wait; + volatile s32_t wait; for (wait=0; wait < 20000; wait++); } } @@ -137,7 +187,7 @@ void start_emacps (xemacpsif_s *xemacps) } void restart_emacps_transmitter (xemacpsif_s *xemacps) { - u32 Reg; + u32_t Reg; Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET); Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK); diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c index 2ccf2b35..5ab4facd 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c @@ -1,52 +1,110 @@ -/* - * Copyright (c) 2007-2008, Advanced Micro Devices, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Advanced Micro Devices, Inc. nor the names - * of its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ -/* - * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. - * - * Xilinx, Inc. - * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A - * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS - * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR - * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION - * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE - * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. - * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO - * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO - * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE - * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. - * - */ +/***************************************************************************** +* This file xemacpsif_physpeed.c implements functionalities to: +* - Detect the available PHYs connected to a MAC +* - Negotiate speed +* - Configure speed +* - Configure the SLCR registers for the negotiated speed +* +* In a typical use case, users of the APIs implemented in this file need to +* do the following. +* - Call the API detect_phy. It probes for the available PHYs connected to a MAC. +* The MACs can be Emac0 (XPAR_XEMACPS_0_BASEADDR, 0xE000B000) or Emac1 +* (XPAR_XEMACPS_0_BASEADDR, 0xE000C000). It populates an array to notify +* about the detected PHYs. The array phymapemac0 is used for Emac0 and +* phymapemac1 is for Emac1. +* - The users need to parse the corresponding arrays, phymapemac0 or phymapemac1 +* to know the available PHYs for a MAC. The users then need to call phy_setup +* to setup the PHYs for proper speed setting. The API phy_setup should be called +* with the PHY address for which the speed needs to be negotiated or configured. +* In a specific use case, if 2 PHYs are connected to Emac0 with addresses of 7 +* and 11, then users get these address details from phymapemac0 (after calling +* detect_phy) and then call phy_setup twice, with ab address of 7 and 11. +* - Points to note: The MAC can operate at only one speed. If a MAC is connected +* to multiple PHYs, then all PHYs must negotiate and configured for the same +* speed. +* - This file implements static functions to set proper SLCR clocks. As stated +* above, all PHYs connected to a PHY must operate at same speed and the SLCR +* clock will be setup accordingly. +* +* This file implements the following PHY types. +* - The standard RGMII. +* - It provides support for GMII to RGMII converter Xilinx IP. This Xilinx IP +* sits on the MDIO bus with a predefined PHY address. This IP exposes register +* that needs to be programmed with the negotiated speed. +* For example, in a typical design, the Emac0 or Emac1 exposes GMII interface. +* The user can then use the Xilinx IP that converts GMII to RGMII. +* The external PHY (most typically Marvell 88E1116R) negotiates for speed +* with the remote PHY. The implementation in this file then programs the +* Xilinx IP with this negotiated speed. The Xilinx IP has a predefined IP +* address exposed through xparameters.h +* - The SGMII and 1000 BaseX PHY interfaces. +* If the PHY interface is SGMII or 1000 BaseX a separate "get_IEEE_phy_speed" +* is used which is different from standard RGMII "get_IEEE_phy_speed". +* The 1000 BaseX always operates at 1000 Mbps. The SGMII interface can +* negotiate speed accordingly. +* For SGMII or 1000 BaseX interfaces, the detect_phy should not be called. +* The phy addresses for these interfaces are fixed at the design time. +* +* Point to note: +* A MAC can not be connected to PHYs where there is a mix between +* SGMII or 1000 Basex or GMII/MII/RGMII. +* In a typical multiple PHY designs, it is expected that the PHYs connected +* will be RGMII or GMII. +* +* The users can choose not to negotiate speed from lwip settings GUI. +* If they opt to choose a particular PHY speed, then the PHY will hard code +* the speed to operate only at the corresponding speed. It will not advertise +* any other speeds. It is users responsibility to ensure that the remote PHY +* supports the speed programmed through the lwip gui. +* +* The following combination of MDIO/PHY are supported: +* - Multiple PHYs connected to the MDIO bus of a MAC. If Emac0 MDIO is connected +* to single/multiple PHYs, it is supported. Similarly Emac1 MDIO connected to +* single/multiple PHYs is supported. +* - A design where both the interfaces are present and are connected to their own +* MDIO bus is supported. +* +* The following MDIO/PHY setup is not supported: +* - A design has both the MACs present. MDIO bus is available only for one MAC +* (Emac0 or Emac1). This MDIO bus has multiple PHYs available for both the +* MACs. The negotiated speed for PHYs sitting on the MDIO bus of one MAC will +* not be see for the other MAC and hence the speed/SLCR settings of the other +* MAC cannot be programmed. Hence this kind of design will not work for +* this implementation. +* +********************************************************************************/ #include "netif/xemacpsif.h" #include "lwipopts.h" @@ -59,45 +117,32 @@ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \ - ADVERTISE_10HALF | ADVERTISE_100HALF) #define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF) #define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF) - #define ADVERTISE_1000 0x0300 - #define IEEE_CONTROL_REG_OFFSET 0 #define IEEE_STATUS_REG_OFFSET 1 #define IEEE_AUTONEGO_ADVERTISE_REG 4 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5 #define IEEE_1000_ADVERTISE_REG_OFFSET 9 -#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10 #define IEEE_COPPER_SPECIFIC_CONTROL_REG 16 #define IEEE_SPECIFIC_STATUS_REG 17 #define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19 #define IEEE_CONTROL_REG_MAC 21 #define IEEE_PAGE_ADDRESS_REGISTER 22 - - #define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040 #define IEEE_CTRL_LINKSPEED_MASK 0x0040 #define IEEE_CTRL_LINKSPEED_1000M 0x0040 #define IEEE_CTRL_LINKSPEED_100M 0x2000 #define IEEE_CTRL_LINKSPEED_10M 0x0000 #define IEEE_CTRL_RESET_MASK 0x8000 -#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000 -#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008 +#define IEEE_CTRL_RESET_MASK 0x8000 +#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020 #define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200 -#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100 -#define IEEE_AN1_ABILITY_MASK 0x1FE0 -#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00 -#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380 -#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060 #define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030 - #define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800 #define IEEE_PAUSE_MASK 0x0400 #define IEEE_AUTONEG_ERROR_MASK 0x8000 @@ -115,13 +160,10 @@ #define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8) #define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140) #define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144) -#define SLCR_LOCK_KEY_VALUE 0x767B -#define SLCR_UNLOCK_KEY_VALUE 0xDF0D -#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214) -#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF - -#define EMAC0_BASE_ADDRESS 0xE000B000 -#define EMAC1_BASE_ADDRESS 0xE000C000 +#define SLCR_LOCK_KEY_VALUE 0x767B +#define SLCR_UNLOCK_KEY_VALUE 0xDF0D +#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214) +#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \ XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 @@ -135,123 +177,56 @@ #define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF #endif -static int detect_phy(XEmacPs *xemacpsp) +u32_t phymapemac0[32]; +u32_t phymapemac1[32]; + +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr); +static void SetUpSLCRDivisors(s32_t mac_baseaddr, s32_t speed); +static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed); + +#ifdef PCM_PMA_CORE_PRESENT +u32_t phy_setup (XEmacPs *xemacpsp, u32_t phy_addr) { - u16 phy_reg; - u32 phy_addr; + u32_t link_speed; + u16_t regval; - for (phy_addr = 31; phy_addr > 0; phy_addr--) { - XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG, - &phy_reg); + link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr); + if (link_speed == 1000) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); + else if (link_speed == 100) + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); + else + SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); - if ((phy_reg != 0xFFFF) && - ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { - /* Found a valid PHY address */ - LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n", - phy_addr)); - LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected.\r\n")); - return phy_addr; - } - } - - LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\r\n")); - - /* default to zero */ - return 0; + xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed); + return link_speed; } -unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) { - u16 temp; - u16 control; - u16 status; - u16 partner_capabilities; -#ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT - u32 phy_addr = XPAR_PCSPMA_1000BASEX_PHYADDR; -#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT - u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR; -#elif XPAR_XEMACPS_0_BASEADDR - u32 phy_addr = detect_phy(xemacpsp); -#endif + u16_t temp; + u16_t control; + u16_t status; + u16_t partner_capabilities; xil_printf("Start PHY autonegotiation \r\n"); -#ifdef PCM_PMA_CORE_PRESENT -#else - XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); - control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); - - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); - - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); - control |= IEEE_ASYMMETRIC_PAUSE_MASK; - control |= IEEE_PAUSE_MASK; - control |= ADVERTISE_100; - control |= ADVERTISE_10; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); - - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - &control); - control |= ADVERTISE_1000; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - control); - - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, - &control); - control |= (7 << 12); /* max number of gigabit attempts */ - control |= (1 << 11); /* enable downshift */ - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, - control); -#endif XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; control |= IEEE_STAT_AUTONEGOTIATE_RESTART; -#ifdef PCM_PMA_CORE_PRESENT - control &= IEEE_CTRL_ISOLATE_DISABLE; -#endif + control &= IEEE_CTRL_ISOLATE_DISABLE; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); -#ifdef PCM_PMA_CORE_PRESENT -#else - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); - control |= IEEE_CTRL_RESET_MASK; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); - - while (1) { - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); - if (control & IEEE_CTRL_RESET_MASK) - continue; - else - break; - } -#endif xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { sleep(1); -#ifdef PCM_PMA_CORE_PRESENT -#else - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, - &temp); - if (temp & IEEE_AUTONEG_ERROR_MASK) { - xil_printf("Auto negotiation error \r\n"); - } -#endif XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); - } - + } xil_printf("autonegotiation complete \r\n"); -#ifdef PCM_PMA_CORE_PRESENT -#else - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities); -#endif - #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp); @@ -284,151 +259,57 @@ unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp) XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100); return 10; } -#else - if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */ - return 1000; - else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */ - return 100; - else /* 10Mbps */ - return 10; #endif + } -unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed) +#else /*PCM_PMA_CORE_PRESENT not defined, GMII/RGMII case*/ +void detect_phy(XEmacPs *xemacpsp) { - u16 control; - u32 phy_addr = detect_phy(xemacpsp); + u16_t phy_reg; + u32_t phy_addr; + u32_t emacnum; - XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); - control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) + emacnum = 0; + else + emacnum = 1; + for (phy_addr = 31; phy_addr > 0; phy_addr--) { + XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG, + &phy_reg); - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); - - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); - control |= IEEE_ASYMMETRIC_PAUSE_MASK; - control |= IEEE_PAUSE_MASK; - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); - - XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); - control &= ~IEEE_CTRL_LINKSPEED_1000M; - control &= ~IEEE_CTRL_LINKSPEED_100M; - control &= ~IEEE_CTRL_LINKSPEED_10M; - - if (speed == 1000) { - control |= IEEE_CTRL_LINKSPEED_1000M; + if ((phy_reg != 0xFFFF) && + ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n", + phy_addr)); + if (emacnum == 0) + phymapemac0[phy_addr] = TRUE; + else + phymapemac1[phy_addr] = TRUE; + } } - - else if (speed == 100) { - control |= IEEE_CTRL_LINKSPEED_100M; - /* Dont advertise PHY speed of 1000 Mbps */ - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0); - /* Dont advertise PHY speed of 10 Mbps */ - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, - ADVERTISE_100); - } - - else if (speed == 10) { - control |= IEEE_CTRL_LINKSPEED_10M; - /* Dont advertise PHY speed of 1000 Mbps */ - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, - 0); - /* Dont advertise PHY speed of 100 Mbps */ - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, - ADVERTISE_10); - } - - XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, - control | IEEE_CTRL_RESET_MASK); - { - volatile int wait; - for (wait=0; wait < 100000; wait++); - } - return 0; } -static void SetUpSLCRDivisors(int mac_baseaddr, int speed) +u32_t phy_setup (XEmacPs *xemacpsp, u32_t phy_addr) { - volatile u32 slcrBaseAddress; - u32 SlcrDiv0; - u32 SlcrDiv1; - u32 SlcrTxClkCntrl; - - *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE; - - if (mac_baseaddr == EMAC0_BASE_ADDRESS) { - slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR; - } else { - slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR; - } - if (speed == 1000) { - if (mac_baseaddr == EMAC0_BASE_ADDRESS) { -#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 - SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0; - SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1; -#endif - } else { -#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0 - SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0; - SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1; -#endif - } - } else if (speed == 100) { - if (mac_baseaddr == EMAC0_BASE_ADDRESS) { -#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 - SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0; - SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1; -#endif - } else { -#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0 - SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0; - SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1; -#endif - } - } else { - if (mac_baseaddr == EMAC0_BASE_ADDRESS) { -#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 - SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0; - SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1; -#endif - } else { -#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0 - SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0; - SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1; -#endif - } - } - SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress); - SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK; - SlcrTxClkCntrl |= (SlcrDiv1 << 20); - SlcrTxClkCntrl |= (SlcrDiv0 << 8); - *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl; - *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE; - return; -} - - -unsigned Phy_Setup (XEmacPs *xemacpsp) -{ - unsigned link_speed; - unsigned short regval; - unsigned long conv_present = 0; - unsigned long convspeeddupsetting = 0; - unsigned long convphyaddr = 0; + u32_t link_speed; + u16_t regval; + u32_t conv_present = 0; + u32_t convspeeddupsetting = 0; + u32_t convphyaddr = 0; #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR; conv_present = 1; -#else +#endif #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR; conv_present = 1; #endif -#endif #ifdef CONFIG_LINKSPEED_AUTODETECT - link_speed = get_IEEE_phy_speed(xemacpsp); + link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr); if (link_speed == 1000) { SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; @@ -442,19 +323,19 @@ unsigned Phy_Setup (XEmacPs *xemacpsp) #elif defined(CONFIG_LINKSPEED1000) SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000); link_speed = 1000; - configure_IEEE_phy_speed(xemacpsp, link_speed); + configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD; sleep(1); #elif defined(CONFIG_LINKSPEED100) SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100); link_speed = 100; - configure_IEEE_phy_speed(xemacpsp, link_speed); + configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD; sleep(1); #elif defined(CONFIG_LINKSPEED10) SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10); link_speed = 10; - configure_IEEE_phy_speed(xemacpsp, link_speed); + configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed); convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD; sleep(1); #endif @@ -463,6 +344,231 @@ unsigned Phy_Setup (XEmacPs *xemacpsp) XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting); } - xil_printf("link speed: %d\r\n", link_speed); + xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed); return link_speed; } + +static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) +{ + u16_t temp; + u16_t control; + u16_t status; + u16_t partner_capabilities; + + xil_printf("Start PHY autonegotiation \r\n"); + + XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); + control |= IEEE_ASYMMETRIC_PAUSE_MASK; + control |= IEEE_PAUSE_MASK; + control |= ADVERTISE_100; + control |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + &control); + control |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, + control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + &control); + control |= (7 << 12); /* max number of gigabit attempts */ + control |= (1 << 11); /* enable downshift */ + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, + control); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control |= IEEE_CTRL_RESET_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); + + while (1) { + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + if (control & IEEE_CTRL_RESET_MASK) + continue; + else + break; + } + xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { + sleep(1); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, + &temp); + if (temp & IEEE_AUTONEG_ERROR_MASK) { + xil_printf("Auto negotiation error \r\n"); + } + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, + &status); + } + xil_printf("autonegotiation complete \r\n"); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities); + + if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */ + return 1000; + else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */ + return 100; + else /* 10Mbps */ + return 10; +} + +static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed) +{ + u16_t control; + u16_t autonereg; + + XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); + control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg |= IEEE_ASYMMETRIC_PAUSE_MASK; + autonereg |= IEEE_PAUSE_MASK; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); + control &= ~IEEE_CTRL_LINKSPEED_1000M; + control &= ~IEEE_CTRL_LINKSPEED_100M; + control &= ~IEEE_CTRL_LINKSPEED_10M; + + if (speed == 1000) { + control |= IEEE_CTRL_LINKSPEED_1000M; + + /* Dont advertise PHY speed of 100 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_100); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Dont advertise PHY speed of 10 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_10); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg); + autonereg |= ADVERTISE_1000; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg); + } + + else if (speed == 100) { + control |= IEEE_CTRL_LINKSPEED_100M; + + /* Dont advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg); + autonereg &= (~ADVERTISE_1000); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg); + + /* Dont advertise PHY speed of 10 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_10); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Advertise PHY speed of 100 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg |= ADVERTISE_100; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + } + + else if (speed == 10) { + control |= IEEE_CTRL_LINKSPEED_10M; + + /* Dont advertise PHY speed of 1000 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg); + autonereg &= (~ADVERTISE_1000); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg); + + /* Dont advertise PHY speed of 100 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg &= (~ADVERTISE_100); + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + + /* Advertise PHY speed of 10 Mbps */ + XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg); + autonereg |= ADVERTISE_10; + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg); + } + + XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, + control | IEEE_CTRL_RESET_MASK); + { + volatile s32_t wait; + for (wait=0; wait < 100000; wait++); + } + return 0; +} +#endif /*PCM_PMA_CORE_PRESENT*/ + +static void SetUpSLCRDivisors(s32_t mac_baseaddr, s32_t speed) +{ + volatile u32_t slcrBaseAddress; + u32_t SlcrDiv0; + u32_t SlcrDiv1; + u32_t SlcrTxClkCntrl; + + *(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE; + + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { + slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR; + } else { + slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR; + } + if (speed == 1000) { + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1; +#endif + } + } else if (speed == 100) { + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1; +#endif + } + } else { + if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) { +#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1; +#endif + } else { +#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0 + SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0; + SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1; +#endif + } + } + SlcrTxClkCntrl = *(volatile u32_t *)(slcrBaseAddress); + SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK; + SlcrTxClkCntrl |= (SlcrDiv1 << 20); + SlcrTxClkCntrl |= (SlcrDiv0 << 8); + *(volatile u32_t *)(slcrBaseAddress) = SlcrTxClkCntrl; + *(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE; + return; +} diff --git a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/sys_arch_raw.c b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/sys_arch_raw.c index ab4947b9..5e898b4c 100755 --- a/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/sys_arch_raw.c +++ b/ThirdParty/sw_services/lwip140_v2_4/src/contrib/ports/xilinx/sys_arch_raw.c @@ -44,9 +44,6 @@ #include "arch/cc.h" #include "lwip/sys.h" -/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c - *** to run it on a PEEP board - ***/ /* * This optional function does a "fast" critical region protection and returns * the previous protection level. This function is only called during very short @@ -70,12 +67,8 @@ sys_arch_protect() cur = mfmsr(); mtmsr(cur & ~XEXC_ALL); #elif __arm__ -#ifdef PEEP - EmacDisableIntr(); -#else cur = mfcpsr(); mtcpsr(cur | 0xC0); -#endif #endif return cur; } @@ -90,11 +83,7 @@ void sys_arch_unprotect(sys_prot_t lev) { #ifdef __arm__ -#ifdef PEEP - EmacEnableIntr(); -#else mtcpsr(lev); -#endif #else mtmsr(lev); #endif