[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/Makefile b/boot/common/src/uboot/drivers/gmac/Makefile
new file mode 100644
index 0000000..7983907
--- /dev/null
+++ b/boot/common/src/uboot/drivers/gmac/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libgmac.o
+
+COBJS-y += gmac.o
+COBJS-y += net.o
+
+
+
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
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
+
diff --git a/boot/common/src/uboot/drivers/gmac/net.c b/boot/common/src/uboot/drivers/gmac/net.c
new file mode 100644
index 0000000..ce03adf
--- /dev/null
+++ b/boot/common/src/uboot/drivers/gmac/net.c
@@ -0,0 +1,315 @@
+/*******************************************************************************
+* °æÈ¨ËùÓÐ (C)2011, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ: net.c
+* Îļþ±êʶ:
+* ÄÚÈÝÕªÒª: ¸ºÔðCPUºÍPPÄ£¿éÖ®¼äµÄÊý¾Ý½»»¥
+* ÆäËü˵Ã÷:
+* µ±Ç°°æ±¾: 1.0
+* ×÷¡¡¡¡Õß: ±«Ð¡ÔÆ
+* Íê³ÉÈÕÆÚ: 2012-1-12 16:22:32
+*
+* Ð޸ļǼ1
+* ÐÞ¸ÄÈÕÆÚ:
+* °æ±¾¡¡ºÅ:
+* Ð޸ġ¡ÈË:
+* ÐÞ¸ÄÄÚÈÝ:
+*
+*******************************************************************************/
+#include <common.h>
+#include <asm/errno.h>
+#include <malloc.h>
+#include <net.h>
+#include <asm/arch/gmac.h>
+
+
+#if 0
+#include <tm/io.h>
+#include <tm/tm.h>
+#include <tm/pon.h>
+#include <tm/pp/dma.h>
+#include <tm/pp/bmu.h>
+#include <tm/pp/red.h>
+#include <tm/pp/pp.h>
+#include <tm/pp/net.h>
+#include <tm/switch/smac.h>
+#endif
+
+
+#ifdef CONFIG_CMD_NET
+
+#define CACHE_ALIGNED(x) ((x)&(~0x1f))
+#if 0
+typedef struct _queue_ctrl{
+ u8 *pFirst;
+ u32 nextToProc;
+} NET_QUEUE_CTRL;
+#endif
+u8 default_mac[6]={0x00,0xd0,0xd0,0x01,0x02,0x03};
+/*NET_QUEUE_CTRL queue_ctrl[PP_MAX_QUEUE];
+int pp_net_debug=0;*/
+
+void (* volatile net_recv) (u8 * buf, int len) = NULL;
+
+void register_net_recv(void *handle)
+{
+ net_recv = handle;
+}
+
+/*
+ * Get pointer to next RX descriptor to be processed by SW
+ */
+ #if 0
+static inline struct pp_desc * pp_get_next_rxdesc(int rxq)
+{
+ struct pp_desc *desc;
+ NET_QUEUE_CTRL *qc;
+ qc = &queue_ctrl[rxq];
+ desc = (struct pp_desc *)(qc->nextToProc * PP_DESC_SIZE + qc->pFirst);
+ if(unlikely(++qc->nextToProc >= PP_QUEUE_SIZE)){
+ qc->nextToProc = 0;
+ }
+ return desc;
+}
+
+static void dump_net_data(u8 *data, u32 len)
+{
+ int i;
+ len = len > 64?64:len;
+ for(i=0;i<len;i++){
+ printf("%.2x ",data[i]);
+ if((i&0xf) == 0xf)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+void dump_desc(struct pp_desc *desc)
+{
+ u32 *data = (u32 *)desc;
+ printf("%.8x:0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",(u32)desc,data[0],data[1],data[2],data[3]);
+ printf("bp %u gem %u len %u\n",desc->BP,desc->Gemport_ID,desc->Pkt_Len);
+}
+
+
+static void free_desc(struct pp_desc *desc,int bp)
+{
+ // free desc
+#ifdef CONFIG_ZX279112
+ if(soft_release_rx_desc(desc->Direction, desc->CPU_Queue_ID,desc->Buffer_Type) < 0)
+#else
+ if(soft_release_rx_desc(desc->CPU_Queue_ID,desc->Buffer_Type) < 0)
+#endif
+ printf("failed to rls rx desc1\n");
+ // free bp
+ if(pp_bmu_free_bp((u16)bp) < 0)
+ printf("failed to rls bp\n");
+}
+
+static inline int pp_net_rx(struct eth_device* dev,int cnt,int rxq)
+{
+ int i,bp,len;
+ struct pp_desc *desc ;
+ u8 *buf;
+
+ // receive packet
+#ifdef CONFIG_SYS_ARM_CACHE_WRITETHROUGH
+ invalidate_dcache_all();
+#endif
+ for(i=0;i<cnt;i++){
+ //get desc, invalid cache, and prefetch
+ desc = pp_get_next_rxdesc(rxq);
+#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)
+ invalidate_dcache_range((u32)desc,(u32)desc+16);
+#endif
+ bp = desc->BP;
+ // check bp
+ if(unlikely(bp >= BP_NUMBERS)){
+ printf("invalid bp %u\n",bp);
+ dump_desc(desc);
+ //error handle
+#ifdef CONFIG_ZX279112
+ soft_release_rx_desc(desc->Direction, rxq,1);
+#else
+ soft_release_rx_desc(rxq,1);
+#endif
+ continue;
+ }
+ buf = (u8 *)(BP_TO_ADDR(bp)) + desc->Offset;
+ len = desc->Pkt_Len;
+#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)
+ invalidate_dcache_range((u32)buf,(u32)buf+len);
+#endif
+ if(pp_net_debug>0){
+ dump_desc(desc);
+ printf("receive len %u, BP %d ,gem %d,addr %x\n",len,
+ bp,desc->Gemport_ID,(u32)buf);
+ dump_net_data(buf,len);
+ pp_net_debug--;
+ }
+
+ if(net_recv == NULL)
+ NetReceive(buf, len);
+ else
+ net_recv(buf, len);
+ free_desc(desc,bp);
+ }
+ return cnt;
+}
+
+/*
+ * get the count of unprocess packet
+ */
+static inline int pp_get_rx_cnt(u32 queue)
+{
+ return ZX_REG_READ(PP_DMA_CPU_QUEUE_CNT(queue));
+}
+#endif
+int max_rx_delay=1000;
+/*
+ * pp net poll interface
+ */
+static int gmac_net_poll(struct eth_device* dev)
+{
+ int i,len=0,trxlen=0;
+// unsigned char *rxbuf;
+ unsigned char rxbuf[256];
+
+
+ //for(i=2;i>0;i--)
+ for(i=0;i<2;i++)
+ {
+ if(zx_gmac_getbd(i)!=0)
+ {
+ trxlen=zx_gmac_rx(rxbuf,&len,i);
+ if(net_recv == NULL)
+ NetReceive(rxbuf, trxlen);
+ else
+ net_recv(rxbuf, trxlen);
+ if(zx_gmac_getbd(i)!=0)
+ /* new packet arrived or hardware has update rx cnt, wait for a while */
+ udelay(1);
+ }
+ }
+ return 0;
+}
+#if 0
+int pp_data_raw_send(u8 *data, u32 len,struct pp_desc *desc)
+{
+ int bp;
+ u8 *buf;
+ /* get the tx descriptor */
+ /* alloc bp to save data */
+ if((bp = pp_bmu_alloc_bp())<0){
+ PON_NET_DBG("alloc bp failed\n");
+ return -1;
+ }
+ /* check bp */
+ if(unlikely(bp >= BP_NUMBERS)){
+ PON_NET_DBG("invalid bp %d\n",bp);
+ return -1;
+ }
+ /* copy data to bp */
+ buf = (u8 *)BP_TO_ADDR(bp)+16;
+ memcpy(buf,data,len);
+
+ /* make desc */
+ desc->BP = bp;
+ desc->Pkt_Len = len;
+ desc->Pkt_Len_Changed = len;
+ desc->Offset = 16;
+ if(pp_net_debug>0){
+ printf("send len %u, BP %d ,addr %x\n",len,
+ bp,(u32)buf);
+ dump_desc(desc);
+ dump_net_data(buf,len);
+ pp_net_debug--;
+ }
+
+#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)
+ flush_dcache_range((u32)buf,(u32)buf+len);
+#endif
+ /* insert desc */
+ if(soft_insert_tx_desc((u32 *)desc)<0){
+ PON_NET_DBG("insert desc failed\n");
+ return -2;
+ }
+ return 0;
+}
+#endif
+/*
+ * send packet to sw,
+ */
+static int gmac_net_sw_tx(struct eth_device* dev, volatile void* packet, int length)
+{
+ if(zx_gmac_send((u8 *)packet,length) != 0)
+ {
+ printf("gmac send error\n");
+ return 1;
+ }
+ return 0;
+}
+#if 0
+void pp_queue_init(void)
+{
+ int i;
+ NET_QUEUE_CTRL *qc;
+ /* init inner rx queue status */
+ for(i=0;i<PP_MAX_QUEUE;i++){
+ qc = &queue_ctrl[i];
+ qc->pFirst = (u8 *)(PP_VA_DESC_BASE + 0x10000 * (PP_RX_QUEUE_OFF+i));
+ qc->nextToProc = 0;
+ }
+}
+#endif
+int gmac_eth_init(struct eth_device* dev, bd_t* bd)
+{
+ zx_gmac_init();
+ return 0;
+}
+
+void gmac_eth_halt(struct eth_device* dev)
+{
+ udelay(100); /* wait for send complete */
+ zx_gmac_stop();
+
+}
+
+/*int pp_net_init(void)
+{
+ tm_set_onu_mac(ONU_MAC1,default_mac);
+ pp_queue_init();
+ return 0;
+}*/
+
+void gmac_net_register(void)
+{
+ struct eth_device *dev;
+
+ dev = malloc(sizeof(*dev));
+ if (!dev) {
+ free(dev);
+ return ;
+ }
+
+ memset(dev, 0, sizeof(*dev));
+
+ dev->init = gmac_eth_init;
+ dev->halt = gmac_eth_halt;
+ dev->send = gmac_net_sw_tx;
+ dev->recv = gmac_net_poll;
+
+ sprintf(dev->name, "eth0");
+
+ /* get mac */
+ if(!eth_getenv_enetaddr("ethaddr", dev->enetaddr)){
+ puts("Please set MAC address\n");
+ }
+ else{
+ memcpy(default_mac,dev->enetaddr,6);
+ }
+
+ eth_register(dev);
+}
+
+#endif