blob: af7488e04a5f4cdc6ae67e5a2cdeabe844d3ec6d [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/** -----------------------------------------------------------------------------------------------------------------@n
2 * °æÈ¨ËùÓÐ(C)2000-2011, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
3 *
4 * ÎÄ ¼þ Ãû: drv_gmac.c @defgroup DRV_GMAC
5 *
6 * ×÷ Õß: ÕÔÀû±ó10113809
7 *
8 * Ä£¿é¸ÅÊö:
9 * - <´Ë´¦ÌîÄ£¿é¸ÅÊö, ÌîÍêºó¿ÕÒ»ÐÐ>
10 *
11 * Ä£¿éÏêÊö:
12 * - <´Ë´¦ÌîÄ£¿éÏêÊö, ÌîÍêºó¿ÕÒ»ÐÐ>
13 *
14 * ÓÃÀý1:
15 * @code
16 *
17 *
18 * @endcode
19 *
20 * °æ ±¾: v0.0
21 *
22 * ------------------------------------------------------------------------------------------------------------------
23 *
24 * ÐÞ¸ÄÈÕÆÚ ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
25 * @li 20120114 ÕÔÀû±ó10113809 ´´½¨
26 * @li 20120907 ÕÔÀû±ó10113809 Ð޸ĴúÂëÖеÄbug
27 * @li 20120908 ÕÔÀû±ó10113809 Ð޸ĴúÂë¹æ·¶£¬µ÷Õû´úÂë½á¹¹
28 * @li 20120910 ÕÔÀû±ó10113809 µ÷Õû´úÂë½á¹¹£¬Ôö¼Ó×¢ÊÍ£¬Ìí¼Ó¹¦ÄÜ
29 * @li 20120925 ÕÔÀû±ó10113809 µ÷Õû´úÂë½á¹¹£¬Ôö¼Ó×¢ÊÍ£¬Ìí¼Ó¹¦ÄÜ£¬ÓÃalignedÊôÐÔ½øÐÐ×Ö½Ú¶ÔÆë
30 * 20150302 ÐìÏÄÃô10180991 Ϊ7520sÐÞ¸Ä
31 *
32 *
33 * @n@{ --------------------------------------------------------------------------------------------------------------- */
34
35#include <linux/string.h> /* ʹÓÃÀïÃæµÄmemcpyº¯Êý */
36#include <asm/arch/gmac.h> /* ʹÓÃÀïÃæµÄÊý¾ÝÀàÐͶ¨Òå BYTE WORD32Ö®ÀàµÄ */
37#include <common.h>
38
39//#define PHY_CLOCK 5
40#define GMAC_RX_DES_ADDR CONFIG_GMAC_DMA_BUF_ADDR
41#define GMAC_TX_DES_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+GMAC_RX_BUF_NUM*128)
42
43#define GMAC_RX_BUF_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+0x800)
44#define GMAC_TX_BUF_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+0x1800)
45//#define GMAC_TX_BUF_ADDR (CONFIG_GMAC_DMA_BUF_ADDR+0x8000)
46
47volatile unsigned int g_dwRxBdOffset = 0;
48volatile unsigned int g_dwTxBdOffset = 0;
49
50/*---------------------------------------------------------------------------------------------------------------------
51 * ÒÔÏÂͨ¹ý±àÒëÆ÷alignedÊôÐÔÉùÃ÷×Ö½Ú¶ÔÆë£¬´¦Àí·½Ê½±È½Ï·½±ã£¬´¦Àí´úÂë²»Ò׳ö´í£¬Ê¡È¥Á˲»ÉÙÈßÓàµÄ¼ÆË㣬µ«ÐèÒª±àÒëÆ÷Ö§
52 * ³ÖcÀ©Õ¹ÊôÐÔ¡£ÃèÊö·û´óСΪ×Ö½Ú¶ÔÆëµÄÕûÊý±¶£¬±£Ö¤ÁËÊ×µØÖ·×Ö½Ú¶ÔÆëµÄÇé¿öÏÂÿ¸öÃèÊö·ûµØÖ·¶¼ÊÇ×Ö½Ú¶ÔÆëµÄ¡£Îª±£Ö¤Ã¿¸ö
53 * »º³åÇøµØÖ·¶¼ÊÇ×Ö½Ú¶ÔÆëµÄÐèÒª»º³åÇø´óСΪ×Ö½Ú¶ÔÆëµÄÕûÊý±¶¡£
54 *
55 * ÔÚʵ¼ÊʹÓÃÖпª±ÙÊÕ·¢»º³åÇøÒ²¿ÉÒÔÔÚϵͳ¹æ»®ÄÚ´æÊ¹ÓõÄʱºò½øÐпª±Ù£¬Ö»ÒªÄܱ£Ö¤Ê×µØÖ··ûºÏmacÇý¶¯µÄµØÖ·¶ÔÆëÒªÇó¼´¿É£¬
56 * È»ºóͨ¹ý²ÎÊý´«µÝµ½ÃèÊö·û³õʼ»¯º¯ÊýÖС£Êµ¼ÊÉÏ»º³åÇøÒ²¿ÉÒÔ²»¶ÔÆëÖ±½ÓʹÓ㬲»¹ýÐèÒª×öÒ»Ð©ÌØÊâ´¦Àí£¬ÌØ±ðÊǽÓÊÕ¶Ë¡£
57 *
58 *--------------------------------------------------------------------------------------------------------------------*/
59//T_GMAC_RxDescr g_tRxDes[GMAC_RX_BUF_NUM]__attribute__((aligned(8)));
60//T_GMAC_TxDescr g_tTxDes[GMAC_TX_BUF_NUM]__attribute__((aligned(8)));
61
62
63T_GMAC_RxDescr *g_tRxDes = (T_GMAC_RxDescr *) GMAC_RX_DES_ADDR;
64T_GMAC_TxDescr *g_tTxDes = (T_GMAC_TxDescr *) GMAC_TX_DES_ADDR;
65
66T_GMAC_DmaRegs *g_ptGmacDmaRegs = (T_GMAC_DmaRegs *) GMAC_DMA_ADDR_BASE;
67T_GMAC_GmacRegs *g_ptGmacGmacRegs = (T_GMAC_GmacRegs *) GMAC_MAC_ADDR_BASE;
68
69
70/*data in DDR*/
71//volatile BYTE g_RxBuf[GMAC_RX_BUF_SIZE * GMAC_RX_BUF_NUM]__attribute__((aligned(8)));
72//volatile BYTE g_TxBuf[GMAC_TX_BUF_SIZE * GMAC_TX_BUF_NUM]__attribute__((aligned(8)));
73
74/*data in IRAM*/
75volatile BYTE *g_RxBuf = (volatile BYTE *) GMAC_RX_BUF_ADDR;
76volatile BYTE *g_TxBuf = (volatile BYTE *) GMAC_TX_BUF_ADDR;
77
78WORD16 phyid = 0;
79WORD32 autotimeout = 100000;
80
81static WORD16 mii_read(WORD32 tPhyAddr, WORD32 tPhyReg);
82
83static void zx_gmac_initBd(void)
84{
85 unsigned int dwIdx;
86 T_GMAC_TxDescr *ptTxTmp;
87 T_GMAC_RxDescr *ptRxTmp;
88
89 ptTxTmp = g_tTxDes;
90 g_dwTxBdOffset = 0;
91 for (dwIdx = 0; dwIdx < GMAC_TX_DESC_NUM; dwIdx++)
92 {
93 /* Initialize Tx descriptor ring */
94 //ptTxTmp->dwDescr0 =0;
95 ptTxTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXINT | GMAC_DESC_TXSTS_TXCHAIN);
96 //ptTxTmp->dwDescr0 = GMAC_ENDIAN32_SWAP( GMAC_DESC_TXSTS_TXCHAIN);
97 //ptTxTmp->dwDescr0 |= ~ GMAC_ENDIAN32_SWAP( GMAC_DESC_TXSTS_OWNBYDMA);
98 ptTxTmp->dwDescr1 = GMAC_ENDIAN32_SWAP(GMAC_TX_BUF_SIZE & GMAC_DESC_TXCTRL_SIZE1MASK);
99 ptTxTmp->dwBuf1Addr = GMAC_ENDIAN32_SWAP((WORD32)&g_TxBuf[dwIdx * GMAC_TX_BUF_SIZE]);
100 ptTxTmp->ptNext = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTxTmp+1)));
101 ptTxTmp++;
102 }
103 ptTxTmp--;
104 ptTxTmp->ptNext = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(g_tTxDes)));
105 ptTxTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXRINGEND);
106
107 ptRxTmp = g_tRxDes;
108 g_dwRxBdOffset = 0;
109 for(dwIdx = 0; dwIdx < GMAC_RX_DESC_NUM; dwIdx++)
110 {
111 //±êÃ÷½ÓÊÕÃèÊö·û±»dmaÕ¼ÓÃ
112 ptRxTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
113 ptRxTmp->dwDescr1 = GMAC_ENDIAN32_SWAP((GMAC_RX_BUF_SIZE & GMAC_DESC_RXCTRL_SIZE1MASK) | GMAC_DESC_RXCTRL_RXCHAIN);
114 ptRxTmp->dwBuf1Addr = GMAC_ENDIAN32_SWAP((WORD32)&g_RxBuf[dwIdx * GMAC_RX_BUF_SIZE]);
115 ptRxTmp->ptNext = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptRxTmp+1)));
116 ptRxTmp++;
117 }
118
119 ptRxTmp--;
120 ptRxTmp->ptNext = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(g_tRxDes)));
121 ptRxTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_RXCTRL_RXRINGEND);
122}
123
124
125int zx_gmac_init(void)
126{
127
128 g_ptGmacDmaRegs->dwBusMode = GMAC_BUSMODE_SRST; // software reset all gmac subsystem inter registers and logic
129
130 zx_gmac_initBd();
131
132 /* ËÙÂÊģʽҪÓëPHYµÄËÙÂÊÆ¥Åä */
133 /*PS: Port Select Selects between GMII and MII:*/
134 g_ptGmacGmacRegs->dwMacConfig = (GMAC_POART_MODE);
135
136 /* µÈ´ý¸´Î»Íê³É*/
137 /*SWR: Software Reset*/
138 while((g_ptGmacDmaRegs->dwBusMode & GMAC_BUSMODE_SRST_MASK) == GMAC_BUSMODE_SRST)
139 {
140 /* cpuËٶȺܿ죬ÉÏÃæ½øÐÐËÙÂÊÆ¥Åäʱ¼Ä´æÆ÷Ä£¿é»¹Ã»Óи´Î»³É¹¦£¬ÕâÀïÖØÐÂÆ¥Åä */
141 g_ptGmacGmacRegs->dwMacConfig = (GMAC_POART_MODE);
142 }
143
144 //É趨PBL: Programmable Burst Length
145 g_ptGmacDmaRegs->dwBusMode &= (~GMAC_BUSMODE_PBL_MASK);
146 g_ptGmacDmaRegs->dwBusMode |= ( GMAC_BUSMODE_PBL_8& GMAC_BUSMODE_PBL_MASK);
147
148 //g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)&g_RxBd[0] + 0x7) & 0xFFFFFFF8;
149 //g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)&g_TxBd[0] + 0x7) & 0xFFFFFFF8;
150 //g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)g_ptRxDes);
151 //g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)g_ptTxDes);
152 g_ptGmacDmaRegs->dwRxDesListAddr = ((WORD32)g_tRxDes);
153 g_ptGmacDmaRegs->dwTxDesListAddr = ((WORD32)g_tTxDes);
154
155 g_ptGmacDmaRegs->dwStatus = 0x0001ffff; //write 1 to clear init
156 g_ptGmacDmaRegs->dwIntEnable = (GMAC_INT_TIE|GMAC_INT_RIE|GMAC_INT_NIE); //interrupt is disable
157 //g_ptGmacDmaRegs->dwIntEnable = (GMAC_INT_ERE|GMAC_INT_ETE|GMAC_INT_TIE|GMAC_INT_RIE|GMAC_INT_NIE);
158 //g_ptGmacDmaRegs->dwIntEnable = 0x1e7ff;
159 //g_ptGmacDmaRegs->dwIntEnable = 0x180f5; // linux gmac
160
161
162 while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
163
164 /* ¸´Î»ÉèÖÃport selectºóÆäËû±ÈÌØÎ»¶¼Îª0 Òò´ËûÓнøÐÐÇå0²Ù×÷ */
165 g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_100M | GMAC_MAC_NORMAL | GMAC_MAC_DUPLEX_MODE );
166 //g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_10M | GMAC_MAC_NORMAL | GMAC_MAC_DUPLEX_MODE );
167
168 //g_ptGmacGmacRegs->dwMacConfig |= (GMAC_MAC_100M | GMAC_MAC_LOOP | GMAC_MAC_DUPLEX_MODE );
169 g_ptGmacGmacRegs->dwMacFrameFilter &= ~(GMAC_MAC_RCVALL_EN);
170 g_ptGmacGmacRegs->dwMacFrameFilter |= (GMAC_MAC_RCVALL_EN);
171 //g_ptGmacGmacRegs->dwMacFrameFilter |= (1 << 0);
172
173 //TSF: Transmit Store and Forward
174 //g_ptGmacDmaRegs->dwOpMode |= (dwMode & (GMAC_DMA_TSF | GMAC_DMA_RSF));
175
176 g_ptGmacDmaRegs->dwOpMode |= (1 << 1); //enable dma
177 g_ptGmacDmaRegs->dwOpMode |= (1 << 13);
178
179 g_ptGmacDmaRegs->dwOpMode |= (1 << 3); //useful when rsf
180 g_ptGmacDmaRegs->dwOpMode |= (1 << 4);
181 g_ptGmacDmaRegs->dwOpMode |= (1 << 14);//useful when tsf
182// g_ptGmacDmaRegs->dwOpMode = 0x601a;
183
184 g_ptGmacGmacRegs->dwMacConfig |= (1 << 3); //enable mac rt tx
185 g_ptGmacGmacRegs->dwMacConfig |= (1 << 2);
186 printf("Mac Config = %x\n",g_ptGmacGmacRegs->dwMacConfig);
187 //g_ptGmacGmacRegs->dwMacConfig = 0x0040c80c;
188 return 0;
189}
190
191void zx_gmac_stop(void)
192{
193 g_ptGmacDmaRegs->dwOpMode &= ~ ((1 << 1)|(1 << 13)); //disable dma
194 g_ptGmacGmacRegs->dwMacConfig &= ~ ((1 << 2)|(1 << 3)); //disable mac rxtx
195 g_ptGmacDmaRegs->dwIntEnable = 0x00; //disable dma interrupt
196
197 g_ptGmacDmaRegs->dwOpMode |= 1 << 20; //clear tx fifo
198 while(g_ptGmacDmaRegs->dwOpMode & (1 << 20)); //wait for clear tx fifo
199}
200
201int zx_gmac_send(BYTE *const txdata,const WORD32 txlen)
202{
203 T_GMAC_TxDescr *ptTmp;
204 T_GMAC_TxDescr *ptFirstBd;
205 BYTE *pBuf;
206 WORD32 dwBdNum = 0;
207 WORD32 dwTmplen = txlen;
208 WORD32 dwBdOffset = g_dwTxBdOffset;
209 WORD32 dwIdx;
210
211 WORD16 tval=0;
212
213 /* Ö»Óûñȡһ´Î¾Í¿ÉÒÔ Öмä¹ý³Ì»áͬ²½È«¾Ö±äÁ¿rd_bd_offsetÓëÃèÊö·ûÁ´±í */
214 //ptTmp = (T_GMAC_TxDescr *)(((WORD32)&g_TxBd[g_dwTxBdOffset*sizeof(T_GMAC_TxDescr)] + 0x7) & 0xFFFFFFF8);
215 ptTmp = &g_tTxDes[g_dwTxBdOffset];
216
217 if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_TXSTS_OWNBYDMAMASK) == GMAC_DESC_TXSTS_OWNBYDMA)
218 {
219 printf("ERROR: GMAC DESC TXSTS OWN BY DMA\n");
220 return 1;
221 }
222
223 ptFirstBd = ptTmp;
224 pBuf = txdata;
225
226 while(1)
227 {
228 /* »¹ÐèÒªÅÐ¶Ï ÒòΪ²»Ö»ÊÇÉÏÃæÐèÒªÅжÏownλ */
229 if ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_TXSTS_OWNBYDMAMASK) != GMAC_DESC_TXSTS_OWNBYDMA)
230 {
231 ptTmp->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_TXLAST | GMAC_DESC_TXSTS_TXFIRST));
232 if(dwTmplen == txlen)
233 {
234 ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXFIRST);
235 ptFirstBd->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_OWNBYDMAMASK)); //show this bd has data wait for tx
236 }
237
238 if(dwTmplen > GMAC_TX_BUF_SIZE)
239 {
240 memcpy((void *)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (void *)pBuf, GMAC_TX_BUF_SIZE);//long frame
241 // ptTmp->dwBuf1Addr = (WORD32)pBuf;
242 ptTmp->dwDescr1 &= GMAC_ENDIAN32_SWAP(~GMAC_DESC_TXCTRL_SIZE1MASK);
243 ptTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(GMAC_TX_BUF_SIZE & GMAC_DESC_TXCTRL_SIZE1MASK);
244 pBuf += GMAC_TX_BUF_SIZE;
245 if(ptFirstBd != ptTmp)
246 {
247 ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);
248 }
249
250 ptTmp = (T_GMAC_TxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
251 dwTmplen -= GMAC_TX_BUF_SIZE;
252 dwBdNum++;
253 g_dwTxBdOffset = (g_dwTxBdOffset+1)%GMAC_TX_DESC_NUM;
254 }
255 else
256 {
257 memcpy((void *)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (void *)pBuf, dwTmplen);
258 //ptTmp->dwBuf1Addr = (WORD32)pBuf;
259 pBuf += dwTmplen;
260 /* Ôö¼ÓÏÂÃæÒ»ÐдúÂë, ½â¾öbug, ½«Êý¾Ý³¤¶È×Ö¶ÎÏÈÇå0ÔÙ¸³Öµ, ·ñÔò²»Äܵõ½Ô¤ÆÚµÄÊý¾Ý³¤¶È */
261 /* »·»Ø²âÊÔÖе¼ÖÂÃèÊö·ûËùÔÚÄÚ´æµØÖ·±»¸²¸Ç£¬µ±È»Ò²¿ÉÄܲúÉúÆäËûÏÖÏ󣬱¾ÖʾÍÊÇÉÏÊöÔ­Òò 2010.09.07 */
262 ptTmp->dwDescr1 &= GMAC_ENDIAN32_SWAP(~GMAC_DESC_TXCTRL_SIZE1MASK);
263 ptTmp->dwDescr1 |= GMAC_ENDIAN32_SWAP(dwTmplen & GMAC_DESC_TXCTRL_SIZE1MASK);
264 ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_TXLAST);
265 ptTmp->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA);
266
267 for ( dwIdx = 0; dwIdx < 100; dwIdx++ ); /* delay */
268 //ptFirstBd->dwDescr0 |= GMAC_ENDIAN32_SWAP(GMAC_DESC_TXSTS_OWNBYDMA); //due to bd only two ,not necessary
269
270 if(((g_ptGmacDmaRegs->dwStatus >> 20) & 0x7) == 0x6) /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
271 {
272 //Print("Reg = %x\n",g_ptGmacDmaRegs->dwStatus);
273 g_ptGmacDmaRegs->dwTxPollDemand = 1;
274
275 }
276 else
277 {
278 printf("Reg = %x\n",g_ptGmacDmaRegs->dwStatus);
279 //g_ptGmacDmaRegs->dwTxPollDemand = 1;
280 }
281 //mac_tx_enable();
282 //memset((void *)ptTmp->Buf1Addr, 0, dwTmplen);
283 g_dwTxBdOffset = (g_dwTxBdOffset+1)%GMAC_TX_DESC_NUM;
284
285 return 0;
286 }
287 }
288 else
289 {
290 ptTmp = ptFirstBd;
291 while(dwBdNum--)
292 {
293 ptTmp->dwDescr0 &= GMAC_ENDIAN32_SWAP(~(GMAC_DESC_TXSTS_OWNBYDMAMASK));
294 ptTmp = (T_GMAC_TxDescr *)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
295 }
296 g_ptGmacDmaRegs->dwTxPollDemand = 1;
297 g_dwTxBdOffset = dwBdOffset;
298 return 1;
299 }
300 }
301}
302
303int zx_gmac_getbd(WORD32 bdnum)
304{
305 T_GMAC_RxDescr *ptTmp;
306 if(bdnum > GMAC_RX_DESC_NUM)
307 {
308 printf("buffer description num error\n");
309 return 1;
310 }
311 ptTmp = &g_tRxDes[bdnum];
312 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
313 return 1;
314
315 return 0;
316}
317
318int zx_gmac_rx(BYTE *const prxbuf, WORD32 *const prxlen,WORD32 bdnum)
319{
320 T_GMAC_RxDescr *ptTmp;
321 WORD32 dwRet;
322 WORD32 dwTmpLen;
323 BYTE *pBuf = NULL;
324 int sdFirstBd=0;
325
326 /* Ö»Óûñȡһ´Î¾Í¿ÉÒÔ Öмä¹ý³Ì»áͬ²½È«¾Ö±äÁ¿rd_bd_offsetÓëÃèÊö·ûÁ´±í */
327 //ptTmp = (T_GMAC_RxDescr *)(((WORD32)&g_RxBd[g_dwRxBdOffset*sizeof(T_GMAC_RxDescr)] + 0x7) & 0xFFFFFFF8);
328 //ptTmp = &g_tRxDes[g_dwRxBdOffset];
329 ptTmp = &g_tRxDes[bdnum];
330 if(ptTmp == 0)
331 {
332 printf("ERROR: g_tRxDes == 0\n");
333 return 0;
334 }
335
336 if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) == GMAC_DESC_RXSTS_OWNBYDMA)
337 {
338 printf("ERROR: GMAC DESC RXSTS OWN BY DMA\n");
339 return 0;
340 }
341
342 pBuf = prxbuf;
343 dwTmpLen = 0;
344
345 //memset((void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)),0,0x200);
346
347 while((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_OWNBYDMAMASK) != GMAC_DESC_RXSTS_OWNBYDMA)
348 {
349 if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXES) == GMAC_DESC_RXSTS_RXES)
350 {
351 printf("ERROR: GMAC RX DESC ERROR : ");
352 if((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXCE) == GMAC_DESC_RXSTS_RXCE)
353 {
354 printf("CRC Error\n");
355 return 0;
356 }
357 else
358 {
359 //printf("\nRX DESC: GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0)=%x\n", GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0));
360 }
361 }
362
363 //Èç¹ûÖ»ÓÐÒ»¸ö½ÓÊÕÃèÊö·ûÓÐÊý¾Ý(¼ÈÊǵÚÒ»¸ö£¬ÓÖÊÇ×îºóÒ»¸ö)
364 if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) == GMAC_DESC_RXSTS_RXFIRST)
365 && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) == GMAC_DESC_RXSTS_RXLAST))
366 {
367 dwRet = (((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_FRAMELENMASK)
368 >> GMAC_DESC_RXSTS_FRAMELENSHFT)-4); // remove 4 bytes crc
369
370 memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), dwRet);
371
372 //memset((void*)ptTmp->dwBuf1Addr, 0, (ptTmp->dwDescr1 & 0x1FFF));
373 ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
374 /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
375 if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
376 {
377 g_ptGmacDmaRegs->dwRxPollDemand = 1;
378 }
379
380 //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
381 return dwRet;
382 }
383
384 //Èç¹ûÊǵÚÒ»¸ö½ÓÊÕÃèÊö·û(ºóÃæ»¹ÓнÓÊÕÃèÊö·û)
385 if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) == GMAC_DESC_RXSTS_RXFIRST)
386 && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) != GMAC_DESC_RXSTS_RXLAST))
387 {
388 memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF));
389 pBuf += (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF);
390 dwTmpLen += GMAC_RX_BUF_SIZE;
391 ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(0x1u << 31);
392 /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
393 if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
394 {
395 g_ptGmacDmaRegs->dwRxPollDemand = 1;
396 }
397
398 //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
399 sdFirstBd = 1;
400 ptTmp = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
401
402 continue;
403 }
404
405 //Èç¹ûÊÇ×îºóÒ»¸ö½ÓÊÕÃèÊö·û(µ«²»ÊǵÚÒ»¸ö½ÓÊÕÃèÊö·û)
406 if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) != GMAC_DESC_RXSTS_RXFIRST)
407 && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) == GMAC_DESC_RXSTS_RXLAST)
408 && sdFirstBd == 1)
409 {
410 dwRet = (((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) >> 16) & 0x3FFF)-4);
411 memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (dwRet-dwTmpLen));
412 ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
413 /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
414 if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
415 {
416 g_ptGmacDmaRegs->dwRxPollDemand = 1;
417 }
418
419 //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
420 return dwRet;
421 }
422
423 //Èç¹û¼È²»ÊǵÚÒ»¸ö£¬Ò²²»ÊÇ×îºóÒ»¸ö½ÓÊÕÃèÊö·û
424 if(((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXFIRST) != GMAC_DESC_RXSTS_RXFIRST)
425 && ((GMAC_ENDIAN32_SWAP(ptTmp->dwDescr0) & GMAC_DESC_RXSTS_RXLAST) != GMAC_DESC_RXSTS_RXLAST)
426 && sdFirstBd == 1)
427 {
428 memcpy((void*)pBuf,(void*)(GMAC_ENDIAN32_SWAP(ptTmp->dwBuf1Addr)), (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF));
429 pBuf += (GMAC_ENDIAN32_SWAP(ptTmp->dwDescr1) & 0x1FFF);
430 dwTmpLen += GMAC_RX_BUF_SIZE;
431 ptTmp->dwDescr0 = GMAC_ENDIAN32_SWAP(GMAC_DESC_RXSTS_OWNBYDMA);
432 /*Èç¹ûDMAÍ£Ö¹¹¤×÷£¬Æô¶¯DMA¹¤×÷*/
433 if(((g_ptGmacDmaRegs->dwStatus >> 17) & 0x7) == 0x4)
434 {
435 g_ptGmacDmaRegs->dwRxPollDemand = 1;
436 }
437 //g_dwRxBdOffset = (g_dwRxBdOffset+1)%GMAC_RX_DESC_NUM;
438 ptTmp = (T_GMAC_RxDescr*)(GMAC_ENDIAN32_SWAP((WORD32)(ptTmp->ptNext)));
439 }
440
441 if(sdFirstBd == 0)
442 {
443 printf("ERROR: RX DESC lost first bd\n");/*lost first bd */
444 break;
445 }
446 }
447 return dwTmpLen;
448}
449
450static void mii_write(WORD32 tPhyAddr, WORD32 tPhyReg, WORD16 tData)
451{
452 while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
453
454 g_ptGmacGmacRegs->dwGMIIData = (WORD32)tData;
455
456 g_ptGmacGmacRegs->dwGMIIAddr = (GMAC_GMII_MDC << GMAC_GMII_MDC_SHIFT);
457
458 g_ptGmacGmacRegs->dwGMIIAddr |= ((tPhyAddr << GMAC_GMII_ADDR_SHIFT) & GMAC_GMII_ADDR_MSK)
459 | ((tPhyReg << GMAC_GMII_PHYREG_SHIFT) & GMAC_GMII_PHYREG_MSK)
460 | GMAC_GMII_WRITE
461 | GMAC_GMII_BUSY;
462
463 while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
464}
465
466
467static WORD16 mii_read(WORD32 tPhyAddr, WORD32 tPhyReg)
468{
469 while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
470
471 g_ptGmacGmacRegs->dwGMIIAddr = (GMAC_GMII_MDC << GMAC_GMII_MDC_SHIFT);//clock 3 35~60MHZ ʱÖÓλ
472
473 g_ptGmacGmacRegs->dwGMIIAddr |= ((tPhyAddr << GMAC_GMII_ADDR_SHIFT) & GMAC_GMII_ADDR_MSK)
474 | ((tPhyReg << GMAC_GMII_PHYREG_SHIFT) & GMAC_GMII_PHYREG_MSK)
475 | GMAC_GMII_BUSY;
476
477 while(g_ptGmacGmacRegs->dwGMIIAddr & GMAC_GMII_BUSY);
478
479 return (WORD16)(g_ptGmacGmacRegs->dwGMIIData&0xFFFF); /* 0xFFFF: 16λÊý¾ÝÑÚÂë */
480
481}
482
483#if (GMAC_PHY_USE == GMAC_PHY_88E1111)
484int gmac_phy_led(WORD32 tphyid,WORD32 ledctrl,WORD32 lednum)
485{
486 WORD32 tphy;
487 WORD16 tval=0;
488 WORD16 tctrl=0;
489 WORD32 tcount=0;
490
491 tphy = tphyid;
492 if(lednum > GMAC_PHY_LED_MAX)
493 return 1;
494
495 if(ledctrl)
496 {
497 tctrl = mii_read(tphy, GMAC_PHY_LED_CTRL_REG);
498 tval = mii_read(tphy, GMAC_PHY_LED_MANUAL_REG);
499
500 mii_write(tphy, GMAC_PHY_LED_CTRL_REG, tctrl|(1<<15)); /*¿ªÆôled ¹¦ÄÜÜ */
501
502 tval &= ~(0x1 << (lednum-1));
503 mii_write(tphy, GMAC_PHY_LED_MANUAL_REG,tval);
504 tcount++;
505 }
506 else
507 {
508 tctrl = mii_read(tphy, GMAC_PHY_LED_CTRL_REG);
509 tval = mii_read(tphy, GMAC_PHY_LED_MANUAL_REG);
510
511 tval |= (0x1 << (lednum-1));
512 mii_write(tphy, GMAC_PHY_LED_MANUAL_REG,tval);
513 tcount--;
514
515 if(tcount == 0)
516 mii_write(tphy, GMAC_PHY_LED_CTRL_REG, tctrl&(~(1<<15))); /* ½ûÖ¹Led ¹¦ÄÜ¿ */
517 }
518 return 0;
519
520}
521
522void gmac_phy_setclock(WORD32 tphyid)
523{
524 WORD32 tphy;
525 WORD16 tval=0;
526
527 tphy = tphyid;
528
529 mii_write(tphy, 27, 0x800F); /* GMII PORT to Copper */
530 /*software reset*/
531 tval = mii_read(tphy, 0x0);
532 mii_write(tphy, 0x0, tval | ( 1 << 15));
533 while( mii_read(tphy, 0x0) & ( 1 << 15));
534
535 mii_write(tphy, 22, 0x00); /* */
536 /*software reset*/
537 tval = mii_read(tphy, 0x0);
538 mii_write(tphy, 0x0, tval | ( 1 << 15));
539 while( mii_read(tphy, 0x0) & ( 1 << 15));
540
541 mii_write(tphy, 30, 0x00); /* */
542 /*software reset*/
543 tval = mii_read(tphy, 0x0);
544 mii_write(tphy, 0x0, tval | ( 1 << 15));
545 while( mii_read(tphy, 0x0) & ( 1 << 15));
546
547 mii_write(tphy, 20, 0x51); /* 100M 25MHZ*/
548 /*software reset*/
549 tval = mii_read(tphy, 0x0);
550 mii_write(tphy, 0x0, tval | ( 1 << 15));
551 while( mii_read(tphy, 0x0) & ( 1 << 15));
552
553 //mii_write(tphy, 0, 0x3100); /* 100M Full Duplex, Autonegotiation */
554 mii_write(tphy, 0, 0x3100); /* 100M half Duplex, Autonegotiation */
555 /*software reset*/
556 tval = mii_read(tphy, 0x0);
557 mii_write(tphy, 0x0, tval | ( 1 << 15));
558 while( mii_read(tphy, 0x0) & ( 1 << 15));
559
560}
561
562int gmac_phy_init(void)
563{
564 WORD32 i;
565 WORD32 tphy;
566 WORD16 tval=0;
567 // »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID
568 WORD32 val;
569
570 val = *(volatile WORD32 *)(0x01306114);
571 //*(volatile WORD32 *)(0x01306114) = val & 0xFFFE; //¸´Î»gmac top
572 //*(volatile WORD32 *)(0x01306114) = val | 0x01;
573
574 //*(volatile WORD32 *)(0x01306114) = val & 0xFFFd; //¸´Î»gmac bus
575 //*(volatile WORD32 *)(0x01306114) = val | 0x02;
576
577 *(volatile WORD32 *)(0x01306114) = val & 0xFFDF; //¸´Î»gmac
578 *(volatile WORD32 *)(0x01306114) = val | 0x20;
579
580
581 for(i = 0; i < PHY_88E1111_MAX_NUM; i++)
582 {
583 tval = mii_read(i, PHY_88E1111_PHYIDR1);
584 if(tval == GMAC_PHY_88E1111_ID)
585 {
586 tphy = i;
587 break;
588 }
589 }
590 if(PHY_88E1111_MAX_NUM == i)
591 {
592 printf("Error: can not find phy 88E1111\n");
593 return 1;
594 }
595 phyid = tphy;
596 gmac_phy_setclock(tphy);
597
598 mii_write(tphy, 16, 0x38);
599
600 /* Disable Auto-Selection when loopback */
601 tval = mii_read(tphy, 27);
602 tval = tval | (0x1<<15);
603 mii_write(tphy, 27, tval);
604
605 /*software reset*/
606 tval = mii_read(tphy, 0);
607 mii_write(tphy, 0, tval | ( 1 << 15));
608 while( mii_read(tphy, 0x0) & ( 1 << 15));
609
610 /* Disable Autonegotiation */
611 tval = mii_read(tphy, 0x0);
612 tval = tval & (~(0x1 << 12));
613 mii_write(tphy, 0x0, tval);
614 /*software reset*/
615 tval = mii_read(tphy, 0x0);
616 mii_write(tphy, 0x0, tval | ( 1 << 15));
617 while( mii_read(tphy, 0x0) & ( 1 << 15));
618
619 /* enable led,set tx led*/
620 tval = mii_read(tphy, 24);
621 mii_write(tphy, 24, tval & 0x7fbe);
622 tval = mii_read(tphy, 24);
623 mii_write(tphy, 24, tval | ( 1 << 1));
624
625 /* set phy tx and crc error count*/
626 //tval = mii_read(tphy, 29);
627 mii_write(tphy, 29, 0x0010);
628 //tval = mii_read(tphy, 30);
629 mii_write(tphy, 30, 0x0001);
630 //tval = mii_read(tphy, 29);
631 mii_write(tphy, 29, 0x000c);
632
633 // tval = mii_read(tphy, 29);
634 mii_write(tphy, 18, 0xff);
635
636 /* enable phyloopback */
637 //tval = mii_read(tphy, 0x0);
638 //tval = tval | (0x1 << 14);
639 //mii_write(tphy, 0x0, tval);
640
641
642 /* Debug */
643 tval = mii_read(tphy, 0x0);
644 printf("Phy Reg0 = %x\n",(u32)tval);
645 return 0;
646}
647#endif
648
649#if (GMAC_PHY_USE == GMAC_PHY_IP101A)
650void gmac_phy_setclock(WORD32 tphyid)
651{
652 WORD32 tphy;
653 WORD16 tval=0;
654
655 tphy = tphyid;
656
657 /*software reset*/
658 mii_write(tphy, MII_BMCR, BMCR_RESET);
659 while( mii_read(tphy, MII_BMCR) & BMCR_RESET);
660#if 0
661 #if 1
662 tval = mii_read(tphy, MII_BMCR);
663 tval |= (BMCR_LOOPBACK); /* enable loopback */
664 mii_write(tphy, MII_BMCR, tval);
665 #endif
666
667 tval = mii_read(tphy, MII_BMCR);
668 tval |= (BMCR_FULLDPLX | BMCR_SPEED100); /* 100M Full Duplex, disAutonegotiation */
669 tval &= ~BMCR_ANENABLE; //disable auto-negotiation
670 mii_write(tphy, MII_BMCR, tval);
671
672 tval = mii_read(tphy, 16);
673 tval |= (0x1<<11); /* disAutonegotiation dis midx*/
674 mii_write(tphy, 16, tval);
675#endif
676
677}
678
679//char TYPE = 0;
680int gmac_phy_init(void)
681{
682 WORD32 i = 0,j = 0;
683 WORD32 tphy = 0,autospeed = 0,autoduplex = 0;
684 WORD16 tval=0;
685 WORD32 val = 0,utmp = 0;
686
687 val = *(volatile WORD32 *)(0x013C020);
688 *(volatile WORD32 *)(0x013C020) = val | (0x1<9); // GPIO cfg rmii_clk_o
689 *(volatile WORD32 *)(0x0013B11C) = 0x00000005; //enable rmii clock RMII_CLOCK_CFG
690
691 val = *(volatile WORD32 *)(0x013C020);
692 *(volatile WORD32 *)(0x013C020) = val | (0x1<18); // GPIO cfg rmii_clk_o
693
694 val = *(volatile WORD32 *)(0x00140150);
695 //*(volatile WORD32 *)(0x00140150) = val & 0xFFFFFFEF ; // GMAC_MOD_CFG gmac phy reset
696
697 *(volatile WORD32 *)(0x00140150) = val | 0x10 ;
698 udelay(200); //IP101A phy delay >10ms ²Åok
699
700
701 // »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID
702 for(i = 0; i < IP101A_PHY_MAX_NUM; i++)
703 {
704 tval = mii_read(i, MII_PHYSID1);
705 printf("Phy Reg%d = %x\n",(s32)i,(u32)tval);
706 if(tval == IP101A_PHY_ID)
707 {
708 tphy = i;
709 phyid = tphy;
710 break;
711 }
712 }
713 if(IP101A_PHY_MAX_NUM == i)
714 {
715 printf("Error: can not find phy IP101A\n");
716 return -1;
717 }
718
719 gmac_phy_setclock(tphy);
720
721 mii_write(tphy, MII_ADVERTISE, 0x1E1);
722 tval = BMCR_ANENABLE | BMCR_ANRESTART;
723 mii_write(tphy, MII_BMCR, tval);
724
725 /* ²éѯ×ÔЭÉÌÊÇ·ñÍê³É */
726 while(autotimeout)
727 //while(1)
728 {
729 tval = mii_read(tphy, MII_BMSR);
730 if(tval&BMSR_ANEGCOMPLETE)
731 {
732 break;
733 }
734 autotimeout--;
735 }
736 if(autotimeout == 0)
737 {
738 printf("phy IP101A auto negotiation failed\n");
739 return -1;
740 }
741 /* ²éѯÊÇ·ñÁ¬½ÓÉÏ*/
742 tval = mii_read(tphy, MII_LPA);
743 autospeed = tval & LPA_100 ? GMAC_PHY_SPEED_100 : GMAC_PHY_SPEED_10;
744 autoduplex = (mii_read(tphy, MII_BMCR) & 0x0100) >> 8;
745 if(autospeed == GMAC_PHY_SPEED_100)
746 {
747 printf("phy IP101A auto negotiation speed is 100M\n");
748 }
749 else
750 {
751 printf("phy IP101A auto negotiation speed is 10M\n");
752 }
753
754 if(autoduplex == GMAC_PHY_DUPLEX_FULL)
755 {
756 printf("phy IP101A auto negotiation duplex is full\n");
757 }
758 else
759 {
760 printf("phy IP101A auto negotiation duplex is half\n");
761 }
762
763 return 0;
764}
765#endif
766