[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/uboot/drivers/gmac/gmac.c b/boot/common/src/uboot/drivers/gmac/gmac.c
new file mode 100644
index 0000000..af7488e
--- /dev/null
+++ b/boot/common/src/uboot/drivers/gmac/gmac.c
@@ -0,0 +1,766 @@
+/** -----------------------------------------------------------------------------------------------------------------@n
+ * °æÈ¨ËùÓÐ(C)2000-2011, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+ *
+ * ÎÄ ¼þ Ãû: drv_gmac.c @defgroup DRV_GMAC
+ *
+ * ×÷ Õß: ÕÔÀû±ó10113809
+ *
+ * Ä£¿é¸ÅÊö:
+ * - <´Ë´¦ÌîÄ£¿é¸ÅÊö, ÌîÍêºó¿ÕÒ»ÐÐ>
+ *
+ * Ä£¿éÏêÊö:
+ * - <´Ë´¦ÌîÄ£¿éÏêÊö, ÌîÍêºó¿ÕÒ»ÐÐ>
+ *
+ * ÓÃÀý1:
+ * @code
+ *
+ *
+ * @endcode
+ *
+ * °æ ±¾: v0.0
+ *
+ * ------------------------------------------------------------------------------------------------------------------
+ *
+ * ÐÞ¸ÄÈÕÆÚ ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
+ * @li 20120114 ÕÔÀû±ó10113809 ´´½¨
+ * @li 20120907 ÕÔÀû±ó10113809 Ð޸ĴúÂëÖеÄbug
+ * @li 20120908 ÕÔÀû±ó10113809 Ð޸ĴúÂë¹æ·¶£¬µ÷Õû´úÂë½á¹¹
+ * @li 20120910 ÕÔÀû±ó10113809 µ÷Õû´úÂë½á¹¹£¬Ôö¼Ó×¢ÊÍ£¬Ìí¼Ó¹¦ÄÜ
+ * @li 20120925 ÕÔÀû±ó10113809 µ÷Õû´úÂë½á¹¹£¬Ôö¼Ó×¢ÊÍ£¬Ìí¼Ó¹¦ÄÜ£¬ÓÃalignedÊôÐÔ½øÐÐ×Ö½Ú¶ÔÆë
+ * 20150302 ÐìÏÄÃô10180991 Ϊ7520sÐÞ¸Ä
+ *
+ *
+ * @n@{ --------------------------------------------------------------------------------------------------------------- */
+
+#include <linux/string.h> /* ʹÓÃÀïÃæµÄmemcpyº¯Êý */
+#include <asm/arch/gmac.h> /* ʹÓÃÀïÃæµÄÊý¾ÝÀàÐͶ¨Òå BYTE WORD32Ö®ÀàµÄ */
+#include <common.h>
+
+//#define PHY_CLOCK 5
+#define GMAC_RX_DES_ADDR CONFIG_GMAC_DMA_BUF_ADDR
+#define GMAC_TX_DES_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+GMAC_RX_BUF_NUM*128)
+
+#define GMAC_RX_BUF_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+0x800)
+#define GMAC_TX_BUF_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+0x1800)
+//#define GMAC_TX_BUF_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+0x8000)
+
+volatile unsigned int g_dwRxBdOffset = 0;
+volatile unsigned int g_dwTxBdOffset = 0;
+
+/*---------------------------------------------------------------------------------------------------------------------
+ * ÒÔÏÂͨ¹ý±àÒëÆ÷alignedÊôÐÔÉùÃ÷×Ö½Ú¶ÔÆë£¬´¦Àí·½Ê½±È½Ï·½±ã£¬´¦Àí´úÂë²»Ò׳ö´í£¬Ê¡È¥Á˲»ÉÙÈßÓàµÄ¼ÆË㣬µ«ÐèÒª±àÒëÆ÷Ö§
+ * ³ÖcÀ©Õ¹ÊôÐÔ¡£ÃèÊö·û´óСΪ×Ö½Ú¶ÔÆëµÄÕûÊý±¶£¬±£Ö¤ÁËÊ×µØÖ·×Ö½Ú¶ÔÆëµÄÇé¿öÏÂÿ¸öÃèÊö·ûµØÖ·¶¼ÊÇ×Ö½Ú¶ÔÆëµÄ¡£Îª±£Ö¤Ã¿¸ö
+ * »º³åÇøµØÖ·¶¼ÊÇ×Ö½Ú¶ÔÆëµÄÐèÒª»º³åÇø´óСΪ×Ö½Ú¶ÔÆëµÄÕûÊý±¶¡£
+ *
+ * ÔÚʵ¼ÊʹÓÃÖпª±ÙÊÕ·¢»º³åÇøÒ²¿ÉÒÔÔÚϵͳ¹æ»®ÄÚ´æÊ¹ÓõÄʱºò½øÐпª±Ù£¬Ö»ÒªÄܱ£Ö¤Ê×µØÖ··ûºÏmacÇý¶¯µÄµØÖ·¶ÔÆëÒªÇó¼´¿É£¬
+ * È»ºóͨ¹ý²ÎÊý´«µÝµ½ÃèÊö·û³õʼ»¯º¯ÊýÖС£Êµ¼ÊÉÏ»º³åÇøÒ²¿ÉÒÔ²»¶ÔÆëÖ±½ÓʹÓ㬲»¹ýÐèÒª×öÒ»Ð©ÌØÊâ´¦Àí£¬ÌØ±ðÊǽÓÊÕ¶Ë¡£
+ *
+ *--------------------------------------------------------------------------------------------------------------------*/
+//T_GMAC_RxDescr g_tRxDes[GMAC_RX_BUF_NUM]__attribute__((aligned(8)));
+//T_GMAC_TxDescr g_tTxDes[GMAC_TX_BUF_NUM]__attribute__((aligned(8)));
+
+
+T_GMAC_RxDescr *g_tRxDes = (T_GMAC_RxDescr *) GMAC_RX_DES_ADDR;
+T_GMAC_TxDescr *g_tTxDes = (T_GMAC_TxDescr *) GMAC_TX_DES_ADDR;
+
+T_GMAC_DmaRegs *g_ptGmacDmaRegs = (T_GMAC_DmaRegs *) GMAC_DMA_ADDR_BASE;
+T_GMAC_GmacRegs *g_ptGmacGmacRegs = (T_GMAC_GmacRegs *) GMAC_MAC_ADDR_BASE;
+
+
+/*data in DDR*/
+//volatile BYTE g_RxBuf[GMAC_RX_BUF_SIZE * GMAC_RX_BUF_NUM]__attribute__((aligned(8)));
+//volatile BYTE g_TxBuf[GMAC_TX_BUF_SIZE * GMAC_TX_BUF_NUM]__attribute__((aligned(8)));
+
+/*data in IRAM*/
+volatile BYTE *g_RxBuf = (volatile BYTE *) GMAC_RX_BUF_ADDR;
+volatile BYTE *g_TxBuf = (volatile BYTE *) GMAC_TX_BUF_ADDR;
+
+WORD16 phyid = 0;
+WORD32 autotimeout = 100000;
+
+static WORD16 mii_read(WORD32 tPhyAddr, WORD32 tPhyReg);
+
+static void zx_gmac_initBd(void)
+{
+ unsigned int dwIdx;
+ T_GMAC_TxDescr *ptTxTmp;
+ T_GMAC_RxDescr *ptRxTmp;
+
+ ptTxTmp = g_tTxDes;
+ g_dwTxBdOffset = 0;
+ for (dwIdx = 0; dwIdx < GMAC_TX_DESC_NUM; dwIdx++)
+ {
+ /* Initialize Tx descriptor ring */
+ //ptTxTmp->dwDescr0 =0;
+ ptTxTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXINT | GMAC_DESC_TXSTS_TXCHAIN);
+ //ptTxTmp->dwDescr0 = GMAC_ENDIAN32_SWAP( GMAC_DESC_TXSTS_TXCHAIN);
+ //ptTxTmp->dwDescr0 |= ~ GMAC_ENDIAN32_SWAP( GMAC_DESC_TXSTS_OWNBYDMA);
+ ptTxTmp->dwDescr1 = GMAC_ENDIAN32_SWAP(GMAC_TX_BUF_SIZE & GMAC_DESC_TXCTRL_SIZE1MASK);
+ ptTxTmp->dwBuf1Addr = GMAC_ENDIAN32_SWAP((WORD32)&g_TxBuf[dwIdx * GMAC_TX_BUF_SIZE]);
+ ptTxTmp->ptNext = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTxTmp+1)));
+ ptTxTmp++;
+ }
+ ptTxTmp--;
+ ptTxTmp->ptNext = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(g_tTxDes)));
+ ptTxTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXRINGEND);
+
+ ptRxTmp = g_tRxDes;
+ g_dwRxBdOffset = 0;
+ for(dwIdx = 0; dwIdx < GMAC_RX_DESC_NUM; dwIdx++)
+ {
+ //±êÃ÷½ÓÊÕÃèÊö·û±»dmaÕ¼ÓÃ
+ ptRxTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+ ptRxTmp->dwDescr1 = GMAC_ENDIAN32_SWAP((GMAC_RX_BUF_SIZE & GMAC_DESC_RXCTRL_SIZE1MASK) | GMAC_DESC_RXCTRL_RXCHAIN);
+ ptRxTmp->dwBuf1Addr = GMAC_ENDIAN32_SWAP((WORD32)&g_RxBuf[dwIdx * GMAC_RX_BUF_SIZE]);
+ ptRxTmp->ptNext = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptRxTmp+1)));
+ ptRxTmp++;
+ }
+
+ ptRxTmp--;
+ ptRxTmp->ptNext = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(g_tRxDes)));
+ ptRxTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_RXCTRL_RXRINGEND);
+}
+
+
+int zx_gmac_init(void)
+{
+
+ g_ptGmacDmaRegs->dwBusMode = GMAC_BUSMODE_SRST; // software reset all gmac subsystem inter registers and logic
+
+ zx_gmac_initBd();
+
+ /* ËÙÂÊģʽҪÓëPHYµÄËÙÂÊÆ¥Åä */
+ /*PS: Port Select Selects between GMII and MII:*/
+ g_ptGmacGmacRegs->dwMacConfig = (GMAC_POART_MODE);
+
+ /* µÈ´ý¸´Î»Íê³É*/
+ /*SWR: Software Reset*/
+ while((g_ptGmacDmaRegs->dwBusMode & GMAC_BUSMODE_SRST_MASK) == GMAC_BUSMODE_SRST)
+ {
+ /* cpuËٶȺܿ죬ÉÏÃæ½øÐÐËÙÂÊÆ¥Åäʱ¼Ä´æÆ÷Ä£¿é»¹Ã»Óи´Î»³É¹¦£¬ÕâÀïÖØÐÂÆ¥Åä */
+ g_ptGmacGmacRegs->dwMacConfig = (GMAC_POART_MODE);
+ }
+
+ //É趨PBL: Programmable Burst Length
+ g_ptGmacDmaRegs->dwBusMode &= (~GMAC_BUSMODE_PBL_MASK);
+ g_ptGmacDmaRegs->dwBusMode |= ( GMAC_BUSMODE_PBL_8& GMAC_BUSMODE_PBL_MASK);
+
+ //g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)&g_RxBd[0] + 0x7) & 0xFFFFFFF8;
+ //g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)&g_TxBd[0] + 0x7) & 0xFFFFFFF8;
+ //g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)g_ptRxDes);
+ //g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)g_ptTxDes);
+ g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)g_tRxDes);
+ g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)g_tTxDes);
+
+ g_ptGmacDmaRegs->dwStatus = 0x0001ffff; //write 1 to clear init
+ g_ptGmacDmaRegs->dwIntEnable = (GMAC_INT_TIE|GMAC_INT_RIE|GMAC_INT_NIE); //interrupt is disable
+ //g_ptGmacDmaRegs->dwIntEnable = (GMAC_INT_ERE|GMAC_INT_ETE|GMAC_INT_TIE|GMAC_INT_RIE|GMAC_INT_NIE);
+ //g_ptGmacDmaRegs->dwIntEnable = 0x1e7ff;
+ //g_ptGmacDmaRegs->dwIntEnable = 0x180f5; // linux gmac
+
+
+ while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+ /* ¸´Î»ÉèÖÃport selectºóÆäËû±ÈÌØÎ»¶¼Îª0 Òò´ËûÓнøÐÐÇå0²Ù×÷ */
+ g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_100M | GMAC_MAC_NORMAL | GMAC_MAC_DUPLEX_MODE );
+ //g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_10M | GMAC_MAC_NORMAL | GMAC_MAC_DUPLEX_MODE );
+
+ //g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_100M | GMAC_MAC_LOOP | GMAC_MAC_DUPLEX_MODE );
+ g_ptGmacGmacRegs->dwMacFrameFilter &= ~(GMAC_MAC_RCVALL_EN);
+ g_ptGmacGmacRegs->dwMacFrameFilter |= (GMAC_MAC_RCVALL_EN);
+ //g_ptGmacGmacRegs->dwMacFrameFilter |= (1 << 0);
+
+ //TSF: Transmit Store and Forward
+ //g_ptGmacDmaRegs->dwOpMode |= (dwMode & (GMAC_DMA_TSF | GMAC_DMA_RSF));
+
+ g_ptGmacDmaRegs->dwOpMode |= (1 << 1); //enable dma
+ g_ptGmacDmaRegs->dwOpMode |= (1 << 13);
+
+ g_ptGmacDmaRegs->dwOpMode |= (1 << 3); //useful when rsf
+ g_ptGmacDmaRegs->dwOpMode |= (1 << 4);
+ g_ptGmacDmaRegs->dwOpMode |= (1 << 14);//useful when tsf
+// g_ptGmacDmaRegs->dwOpMode = 0x601a;
+
+ g_ptGmacGmacRegs->dwMacConfig |= (1 << 3); //enable mac rt tx
+ g_ptGmacGmacRegs->dwMacConfig |= (1 << 2);
+ printf("Mac Config = %x\n",g_ptGmacGmacRegs->dwMacConfig);
+ //g_ptGmacGmacRegs->dwMacConfig = 0x0040c80c;
+ return 0;
+}
+
+void zx_gmac_stop(void)
+{
+ g_ptGmacDmaRegs->dwOpMode &= ~ ((1 << 1)|(1 << 13)); //disable dma
+ g_ptGmacGmacRegs->dwMacConfig &= ~ ((1 << 2)|(1 << 3)); //disable mac rxtx
+ g_ptGmacDmaRegs->dwIntEnable = 0x00; //disable dma interrupt
+
+ g_ptGmacDmaRegs->dwOpMode |= 1 << 20; //clear tx fifo
+ while(g_ptGmacDmaRegs->dwOpMode & (1 << 20)); //wait for clear tx fifo
+}
+
+int zx_gmac_send(BYTE *const txdata,const WORD32 txlen)
+{
+ T_GMAC_TxDescr *ptTmp;
+ T_GMAC_TxDescr *ptFirstBd;
+ BYTE *pBuf;
+ WORD32 dwBdNum = 0;
+ WORD32 dwTmplen = txlen;
+ WORD32 dwBdOffset = g_dwTxBdOffset;
+ WORD32 dwIdx;
+
+ WORD16 tval=0;
+
+ /* Ö»Óûñȡһ´Î¾Í¿ÉÒÔ Öмä¹ý³Ì»áͬ²½È«¾Ö±äÁ¿rd_bd_offsetÓëÃèÊö·ûÁ´±í */
+ //ptTmp = (T_GMAC_TxDescr *)(((WORD32)&g_TxBd[g_dwTxBdOffset*sizeof(T_GMAC_TxDescr)] + 0x7) & 0xFFFFFFF8);
+ ptTmp = &g_tTxDes[g_dwTxBdOffset];
+
+ if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_TXSTS_OWNBYDMAMASK) == GMAC_DESC_TXSTS_OWNBYDMA)
+ {
+ printf("ERROR: GMAC DESC TXSTS OWN BY DMA\n");
+ return 1;
+ }
+
+ ptFirstBd = ptTmp;
+ pBuf = txdata;
+
+ while(1)
+ {
+ /* »¹ÐèÒªÅÐ¶Ï ÒòΪ²»Ö»ÊÇÉÏÃæÐèÒªÅжÏownλ */
+ if ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_TXSTS_OWNBYDMAMASK) != GMAC_DESC_TXSTS_OWNBYDMA)
+ {
+ ptTmp->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_TXLAST | GMAC_DESC_TXSTS_TXFIRST));
+ if(dwTmplen == txlen)
+ {
+ ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXFIRST);
+ ptFirstBd->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_OWNBYDMAMASK)); //show this bd has data wait for tx
+ }
+
+ if(dwTmplen > GMAC_TX_BUF_SIZE)
+ {
+ memcpy((void *)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (void *)pBuf, GMAC_TX_BUF_SIZE);//long frame
+ // ptTmp->dwBuf1Addr = (WORD32)pBuf;
+ ptTmp->dwDescr1 &= GMAC_ENDIAN32_SWAP(~GMAC_DESC_TXCTRL_SIZE1MASK);
+ ptTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(GMAC_TX_BUF_SIZE & GMAC_DESC_TXCTRL_SIZE1MASK);
+ pBuf += GMAC_TX_BUF_SIZE;
+ if(ptFirstBd != ptTmp)
+ {
+ ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);
+ }
+
+ ptTmp = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+ dwTmplen -= GMAC_TX_BUF_SIZE;
+ dwBdNum++;
+ g_dwTxBdOffset = (g_dwTxBdOffset+1)%GMAC_TX_DESC_NUM;
+ }
+ else
+ {
+ memcpy((void *)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (void *)pBuf, dwTmplen);
+ //ptTmp->dwBuf1Addr = (WORD32)pBuf;
+ pBuf += dwTmplen;
+ /* Ôö¼ÓÏÂÃæÒ»ÐдúÂë, ½â¾öbug, ½«Êý¾Ý³¤¶È×Ö¶ÎÏÈÇå0ÔÙ¸³Öµ, ·ñÔò²»Äܵõ½Ô¤ÆÚµÄÊý¾Ý³¤¶È */
+ /* »·»Ø²âÊÔÖе¼ÖÂÃèÊö·ûËùÔÚÄÚ´æµØÖ·±»¸²¸Ç£¬µ±È»Ò²¿ÉÄܲúÉúÆäËûÏÖÏ󣬱¾ÖʾÍÊÇÉÏÊöÔÒò 2010.09.07 */
+ ptTmp->dwDescr1 &= GMAC_ENDIAN32_SWAP(~GMAC_DESC_TXCTRL_SIZE1MASK);
+ ptTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(dwTmplen & GMAC_DESC_TXCTRL_SIZE1MASK);
+ ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXLAST);
+ ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);
+
+ for ( dwIdx = 0; dwIdx < 100; dwIdx++ ); /* delay */
+ //ptFirstBd->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA); //due to bd only two ,not necessary
+
+ if(((g_ptGmacDmaRegs->dwStatus >> 20) & 0x7) == 0x6) /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+ {
+ //Print("Reg = %x\n",g_ptGmacDmaRegs->dwStatus);
+ g_ptGmacDmaRegs->dwTxPollDemand = 1;
+
+ }
+ else
+ {
+ printf("Reg = %x\n",g_ptGmacDmaRegs->dwStatus);
+ //g_ptGmacDmaRegs->dwTxPollDemand = 1;
+ }
+ //mac_tx_enable();
+ //memset((void *)ptTmp->Buf1Addr, 0, dwTmplen);
+ g_dwTxBdOffset = (g_dwTxBdOffset+1)%GMAC_TX_DESC_NUM;
+
+ return 0;
+ }
+ }
+ else
+ {
+ ptTmp = ptFirstBd;
+ while(dwBdNum--)
+ {
+ ptTmp->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_OWNBYDMAMASK));
+ ptTmp = (T_GMAC_TxDescr *)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+ }
+ g_ptGmacDmaRegs->dwTxPollDemand = 1;
+ g_dwTxBdOffset = dwBdOffset;
+ return 1;
+ }
+ }
+}
+
+int zx_gmac_getbd(WORD32 bdnum)
+{
+ T_GMAC_RxDescr *ptTmp;
+ if(bdnum > GMAC_RX_DESC_NUM)
+ {
+ printf("buffer description num error\n");
+ return 1;
+ }
+ ptTmp = &g_tRxDes[bdnum];
+ if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) != GMAC_DESC_RXSTS_OWNBYDMA) //check rx bd descr0 bit31 is 0 ,show that data come
+ return 1;
+
+ return 0;
+}
+
+int zx_gmac_rx(BYTE *const prxbuf, WORD32 *const prxlen,WORD32 bdnum)
+{
+ T_GMAC_RxDescr *ptTmp;
+ WORD32 dwRet;
+ WORD32 dwTmpLen;
+ BYTE *pBuf = NULL;
+ int sdFirstBd=0;
+
+ /* Ö»Óûñȡһ´Î¾Í¿ÉÒÔ Öмä¹ý³Ì»áͬ²½È«¾Ö±äÁ¿rd_bd_offsetÓëÃèÊö·ûÁ´±í */
+ //ptTmp = (T_GMAC_RxDescr *)(((WORD32)&g_RxBd[g_dwRxBdOffset*sizeof(T_GMAC_RxDescr)] + 0x7) & 0xFFFFFFF8);
+ //ptTmp = &g_tRxDes[g_dwRxBdOffset];
+ ptTmp = &g_tRxDes[bdnum];
+ if(ptTmp == 0)
+ {
+ printf("ERROR: g_tRxDes == 0\n");
+ return 0;
+ }
+
+ if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) == GMAC_DESC_RXSTS_OWNBYDMA)
+ {
+ printf("ERROR: GMAC DESC RXSTS OWN BY DMA\n");
+ return 0;
+ }
+
+ pBuf = prxbuf;
+ dwTmpLen = 0;
+
+ //memset((void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)),0,0x200);
+
+ while((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) != GMAC_DESC_RXSTS_OWNBYDMA)
+ {
+ if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXES) == GMAC_DESC_RXSTS_RXES)
+ {
+ printf("ERROR: GMAC RX DESC ERROR : ");
+ if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXCE) == GMAC_DESC_RXSTS_RXCE)
+ {
+ printf("CRC Error\n");
+ return 0;
+ }
+ else
+ {
+ //printf("\nRX DESC: GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0)=%x\n", GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0));
+ }
+ }
+
+ //Èç¹ûÖ»ÓÐÒ»¸ö½ÓÊÕÃèÊö·ûÓÐÊý¾Ý(¼ÈÊǵÚÒ»¸ö£¬ÓÖÊÇ×îºóÒ»¸ö)
+ if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) == GMAC_DESC_RXSTS_RXFIRST)
+ && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) == GMAC_DESC_RXSTS_RXLAST))
+ {
+ dwRet = (((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_FRAMELENMASK)
+ >> GMAC_DESC_RXSTS_FRAMELENSHFT)-4); // remove 4 bytes crc
+
+ memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), dwRet);
+
+ //memset((void*)ptTmp->dwBuf1Addr, 0, (ptTmp->dwDescr1 & 0x1FFF));
+ ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+ /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+ if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+ {
+ g_ptGmacDmaRegs->dwRxPollDemand = 1;
+ }
+
+ //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+ return dwRet;
+ }
+
+ //Èç¹ûÊǵÚÒ»¸ö½ÓÊÕÃèÊö·û(ºóÃæ»¹ÓнÓÊÕÃèÊö·û)
+ if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) == GMAC_DESC_RXSTS_RXFIRST)
+ && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) != GMAC_DESC_RXSTS_RXLAST))
+ {
+ memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF));
+ pBuf += (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF);
+ dwTmpLen += GMAC_RX_BUF_SIZE;
+ ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(0x1u << 31);
+ /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+ if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+ {
+ g_ptGmacDmaRegs->dwRxPollDemand = 1;
+ }
+
+ //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+ sdFirstBd = 1;
+ ptTmp = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+
+ continue;
+ }
+
+ //Èç¹ûÊÇ×îºóÒ»¸ö½ÓÊÕÃèÊö·û(µ«²»ÊǵÚÒ»¸ö½ÓÊÕÃèÊö·û)
+ if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) != GMAC_DESC_RXSTS_RXFIRST)
+ && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) == GMAC_DESC_RXSTS_RXLAST)
+ && sdFirstBd == 1)
+ {
+ dwRet = (((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) >> 16) & 0x3FFF)-4);
+ memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (dwRet-dwTmpLen));
+ ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+ /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+ if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+ {
+ g_ptGmacDmaRegs->dwRxPollDemand = 1;
+ }
+
+ //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+ return dwRet;
+ }
+
+ //Èç¹û¼È²»ÊǵÚÒ»¸ö£¬Ò²²»ÊÇ×îºóÒ»¸ö½ÓÊÕÃèÊö·û
+ if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) != GMAC_DESC_RXSTS_RXFIRST)
+ && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) != GMAC_DESC_RXSTS_RXLAST)
+ && sdFirstBd == 1)
+ {
+ memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF));
+ pBuf += (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF);
+ dwTmpLen += GMAC_RX_BUF_SIZE;
+ ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
+ /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
+ if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
+ {
+ g_ptGmacDmaRegs->dwRxPollDemand = 1;
+ }
+ //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
+ ptTmp = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
+ }
+
+ if(sdFirstBd == 0)
+ {
+ printf("ERROR: RX DESC lost first bd\n");/*lost first bd */
+ break;
+ }
+ }
+ return dwTmpLen;
+}
+
+static void mii_write(WORD32 tPhyAddr, WORD32 tPhyReg, WORD16 tData)
+{
+ while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+ g_ptGmacGmacRegs->dwGMIIData = (WORD32)tData;
+
+ g_ptGmacGmacRegs->dwGMIIAddr = (GMAC_GMII_MDC << GMAC_GMII_MDC_SHIFT);
+
+ g_ptGmacGmacRegs->dwGMIIAddr |= ((tPhyAddr << GMAC_GMII_ADDR_SHIFT) & GMAC_GMII_ADDR_MSK)
+ | ((tPhyReg << GMAC_GMII_PHYREG_SHIFT) & GMAC_GMII_PHYREG_MSK)
+ | GMAC_GMII_WRITE
+ | GMAC_GMII_BUSY;
+
+ while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+}
+
+
+static WORD16 mii_read(WORD32 tPhyAddr, WORD32 tPhyReg)
+{
+ while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+ g_ptGmacGmacRegs->dwGMIIAddr = (GMAC_GMII_MDC << GMAC_GMII_MDC_SHIFT);//clock 3 35~60MHZ ʱÖÓλ
+
+ g_ptGmacGmacRegs->dwGMIIAddr |= ((tPhyAddr << GMAC_GMII_ADDR_SHIFT) & GMAC_GMII_ADDR_MSK)
+ | ((tPhyReg << GMAC_GMII_PHYREG_SHIFT) & GMAC_GMII_PHYREG_MSK)
+ | GMAC_GMII_BUSY;
+
+ while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
+
+ return (WORD16)(g_ptGmacGmacRegs->dwGMIIData&0xFFFF); /* 0xFFFF: 16λÊý¾ÝÑÚÂë */
+
+}
+
+#if (GMAC_PHY_USE == GMAC_PHY_88E1111)
+int gmac_phy_led(WORD32 tphyid,WORD32 ledctrl,WORD32 lednum)
+{
+ WORD32 tphy;
+ WORD16 tval=0;
+ WORD16 tctrl=0;
+ WORD32 tcount=0;
+
+ tphy = tphyid;
+ if(lednum > GMAC_PHY_LED_MAX)
+ return 1;
+
+ if(ledctrl)
+ {
+ tctrl = mii_read(tphy, GMAC_PHY_LED_CTRL_REG);
+ tval = mii_read(tphy, GMAC_PHY_LED_MANUAL_REG);
+
+ mii_write(tphy, GMAC_PHY_LED_CTRL_REG, tctrl|(1<<15)); /*¿ªÆôled ¹¦ÄÜÜ */
+
+ tval &= ~(0x1 << (lednum-1));
+ mii_write(tphy, GMAC_PHY_LED_MANUAL_REG,tval);
+ tcount++;
+ }
+ else
+ {
+ tctrl = mii_read(tphy, GMAC_PHY_LED_CTRL_REG);
+ tval = mii_read(tphy, GMAC_PHY_LED_MANUAL_REG);
+
+ tval |= (0x1 << (lednum-1));
+ mii_write(tphy, GMAC_PHY_LED_MANUAL_REG,tval);
+ tcount--;
+
+ if(tcount == 0)
+ mii_write(tphy, GMAC_PHY_LED_CTRL_REG, tctrl&(~(1<<15))); /* ½ûÖ¹Led ¹¦ÄÜ¿ */
+ }
+ return 0;
+
+}
+
+void gmac_phy_setclock(WORD32 tphyid)
+{
+ WORD32 tphy;
+ WORD16 tval=0;
+
+ tphy = tphyid;
+
+ mii_write(tphy, 27, 0x800F); /* GMII PORT to Copper */
+ /*software reset*/
+ tval = mii_read(tphy, 0x0);
+ mii_write(tphy, 0x0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+ mii_write(tphy, 22, 0x00); /* */
+ /*software reset*/
+ tval = mii_read(tphy, 0x0);
+ mii_write(tphy, 0x0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+ mii_write(tphy, 30, 0x00); /* */
+ /*software reset*/
+ tval = mii_read(tphy, 0x0);
+ mii_write(tphy, 0x0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+ mii_write(tphy, 20, 0x51); /* 100M 25MHZ*/
+ /*software reset*/
+ tval = mii_read(tphy, 0x0);
+ mii_write(tphy, 0x0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+ //mii_write(tphy, 0, 0x3100); /* 100M Full Duplex, Autonegotiation */
+ mii_write(tphy, 0, 0x3100); /* 100M half Duplex, Autonegotiation */
+ /*software reset*/
+ tval = mii_read(tphy, 0x0);
+ mii_write(tphy, 0x0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+}
+
+int gmac_phy_init(void)
+{
+ WORD32 i;
+ WORD32 tphy;
+ WORD16 tval=0;
+ // »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID
+ WORD32 val;
+
+ val = *(volatile WORD32 *)(0x01306114);
+ //*(volatile WORD32 *)(0x01306114) = val & 0xFFFE; //¸´Î»gmac top
+ //*(volatile WORD32 *)(0x01306114) = val | 0x01;
+
+ //*(volatile WORD32 *)(0x01306114) = val & 0xFFFd; //¸´Î»gmac bus
+ //*(volatile WORD32 *)(0x01306114) = val | 0x02;
+
+ *(volatile WORD32 *)(0x01306114) = val & 0xFFDF; //¸´Î»gmac
+ *(volatile WORD32 *)(0x01306114) = val | 0x20;
+
+
+ for(i = 0; i < PHY_88E1111_MAX_NUM; i++)
+ {
+ tval = mii_read(i, PHY_88E1111_PHYIDR1);
+ if(tval == GMAC_PHY_88E1111_ID)
+ {
+ tphy = i;
+ break;
+ }
+ }
+ if(PHY_88E1111_MAX_NUM == i)
+ {
+ printf("Error: can not find phy 88E1111\n");
+ return 1;
+ }
+ phyid = tphy;
+ gmac_phy_setclock(tphy);
+
+ mii_write(tphy, 16, 0x38);
+
+ /* Disable Auto-Selection when loopback */
+ tval = mii_read(tphy, 27);
+ tval = tval | (0x1<<15);
+ mii_write(tphy, 27, tval);
+
+ /*software reset*/
+ tval = mii_read(tphy, 0);
+ mii_write(tphy, 0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+ /* Disable Autonegotiation */
+ tval = mii_read(tphy, 0x0);
+ tval = tval & (~(0x1 << 12));
+ mii_write(tphy, 0x0, tval);
+ /*software reset*/
+ tval = mii_read(tphy, 0x0);
+ mii_write(tphy, 0x0, tval | ( 1 << 15));
+ while( mii_read(tphy, 0x0) & ( 1 << 15));
+
+ /* enable led,set tx led*/
+ tval = mii_read(tphy, 24);
+ mii_write(tphy, 24, tval & 0x7fbe);
+ tval = mii_read(tphy, 24);
+ mii_write(tphy, 24, tval | ( 1 << 1));
+
+ /* set phy tx and crc error count*/
+ //tval = mii_read(tphy, 29);
+ mii_write(tphy, 29, 0x0010);
+ //tval = mii_read(tphy, 30);
+ mii_write(tphy, 30, 0x0001);
+ //tval = mii_read(tphy, 29);
+ mii_write(tphy, 29, 0x000c);
+
+ // tval = mii_read(tphy, 29);
+ mii_write(tphy, 18, 0xff);
+
+ /* enable phyloopback */
+ //tval = mii_read(tphy, 0x0);
+ //tval = tval | (0x1 << 14);
+ //mii_write(tphy, 0x0, tval);
+
+
+ /* Debug */
+ tval = mii_read(tphy, 0x0);
+ printf("Phy Reg0 = %x\n",(u32)tval);
+ return 0;
+}
+#endif
+
+#if (GMAC_PHY_USE == GMAC_PHY_IP101A)
+void gmac_phy_setclock(WORD32 tphyid)
+{
+ WORD32 tphy;
+ WORD16 tval=0;
+
+ tphy = tphyid;
+
+ /*software reset*/
+ mii_write(tphy, MII_BMCR, BMCR_RESET);
+ while( mii_read(tphy, MII_BMCR) & BMCR_RESET);
+#if 0
+ #if 1
+ tval = mii_read(tphy, MII_BMCR);
+ tval |= (BMCR_LOOPBACK); /* enable loopback */
+ mii_write(tphy, MII_BMCR, tval);
+ #endif
+
+ tval = mii_read(tphy, MII_BMCR);
+ tval |= (BMCR_FULLDPLX | BMCR_SPEED100); /* 100M Full Duplex, disAutonegotiation */
+ tval &= ~BMCR_ANENABLE; //disable auto-negotiation
+ mii_write(tphy, MII_BMCR, tval);
+
+ tval = mii_read(tphy, 16);
+ tval |= (0x1<<11); /* disAutonegotiation dis midx*/
+ mii_write(tphy, 16, tval);
+#endif
+
+}
+
+//char TYPE = 0;
+int gmac_phy_init(void)
+{
+ WORD32 i = 0,j = 0;
+ WORD32 tphy = 0,autospeed = 0,autoduplex = 0;
+ WORD16 tval=0;
+ WORD32 val = 0,utmp = 0;
+
+ val = *(volatile WORD32 *)(0x013C020);
+ *(volatile WORD32 *)(0x013C020) = val | (0x1<9); // GPIO cfg rmii_clk_o
+ *(volatile WORD32 *)(0x0013B11C) = 0x00000005; //enable rmii clock RMII_CLOCK_CFG
+
+ val = *(volatile WORD32 *)(0x013C020);
+ *(volatile WORD32 *)(0x013C020) = val | (0x1<18); // GPIO cfg rmii_clk_o
+
+ val = *(volatile WORD32 *)(0x00140150);
+ //*(volatile WORD32 *)(0x00140150) = val & 0xFFFFFFEF ; // GMAC_MOD_CFG gmac phy reset
+
+ *(volatile WORD32 *)(0x00140150) = val | 0x10 ;
+ udelay(200); //IP101A phy delay >10ms ²Åok
+
+
+ // »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID
+ for(i = 0; i < IP101A_PHY_MAX_NUM; i++)
+ {
+ tval = mii_read(i, MII_PHYSID1);
+ printf("Phy Reg%d = %x\n",(s32)i,(u32)tval);
+ if(tval == IP101A_PHY_ID)
+ {
+ tphy = i;
+ phyid = tphy;
+ break;
+ }
+ }
+ if(IP101A_PHY_MAX_NUM == i)
+ {
+ printf("Error: can not find phy IP101A\n");
+ return -1;
+ }
+
+ gmac_phy_setclock(tphy);
+
+ mii_write(tphy, MII_ADVERTISE, 0x1E1);
+ tval = BMCR_ANENABLE | BMCR_ANRESTART;
+ mii_write(tphy, MII_BMCR, tval);
+
+ /* ²éѯ×ÔÐÉÌÊÇ·ñÍê³É */
+ while(autotimeout)
+ //while(1)
+ {
+ tval = mii_read(tphy, MII_BMSR);
+ if(tval&BMSR_ANEGCOMPLETE)
+ {
+ break;
+ }
+ autotimeout--;
+ }
+ if(autotimeout == 0)
+ {
+ printf("phy IP101A auto negotiation failed\n");
+ return -1;
+ }
+ /* ²éѯÊÇ·ñÁ¬½ÓÉÏ*/
+ tval = mii_read(tphy, MII_LPA);
+ autospeed = tval & LPA_100 ? GMAC_PHY_SPEED_100 : GMAC_PHY_SPEED_10;
+ autoduplex = (mii_read(tphy, MII_BMCR) & 0x0100) >> 8;
+ if(autospeed == GMAC_PHY_SPEED_100)
+ {
+ printf("phy IP101A auto negotiation speed is 100M\n");
+ }
+ else
+ {
+ printf("phy IP101A auto negotiation speed is 10M\n");
+ }
+
+ if(autoduplex == GMAC_PHY_DUPLEX_FULL)
+ {
+ printf("phy IP101A auto negotiation duplex is full\n");
+ }
+ else
+ {
+ printf("phy IP101A auto negotiation duplex is half\n");
+ }
+
+ return 0;
+}
+#endif
+