2 * Driver for Blackfin On-Chip MAC device
4 * Copyright (c) 2005-2008 Analog Device, Inc.
6 * Licensed under the GPL-2 or later.
15 #include <asm/blackfin.h>
16 #include <asm/mach-common/bits/dma.h>
17 #include <asm/mach-common/bits/emac.h>
18 #include <asm/mach-common/bits/pll.h>
29 #define DEBUGF(fmt, args...) printf(fmt, ##args)
31 #define DEBUGF(fmt, args...)
34 #define RXBUF_BASE_ADDR 0xFF900000
35 #define TXBUF_BASE_ADDR 0xFF800000
38 #define TOUT_LOOP 1000000
40 ADI_ETHER_BUFFER
*txbuf
[TX_BUF_CNT
];
41 ADI_ETHER_BUFFER
*rxbuf
[PKTBUFSRX
];
42 static u16 txIdx
; /* index of the current RX buffer */
43 static u16 rxIdx
; /* index of the current TX buffer */
45 u16 PHYregs
[NO_PHY_REGS
]; /* u16 PHYADDR; */
47 /* DMAx_CONFIG values at DMA Restart */
48 const ADI_DMA_CONFIG_REG rxdmacfg
= {
49 .b_DMA_EN
= 1, /* enabled */
50 .b_WNR
= 1, /* write to memory */
51 .b_WDSIZE
= 2, /* wordsize is 32 bits */
55 .b_DI_EN
= 0, /* no interrupt */
56 .b_NDSIZE
= 5, /* 5 half words is desc size */
57 .b_FLOW
= 7 /* large desc flow */
60 const ADI_DMA_CONFIG_REG txdmacfg
= {
61 .b_DMA_EN
= 1, /* enabled */
62 .b_WNR
= 0, /* read from memory */
63 .b_WDSIZE
= 2, /* wordsize is 32 bits */
67 .b_DI_EN
= 0, /* no interrupt */
68 .b_NDSIZE
= 5, /* 5 half words is desc size */
69 .b_FLOW
= 7 /* large desc flow */
72 int bfin_EMAC_initialize(bd_t
*bis
)
74 struct eth_device
*dev
;
75 dev
= (struct eth_device
*)malloc(sizeof(*dev
));
79 memset(dev
, 0, sizeof(*dev
));
80 sprintf(dev
->name
, "Blackfin EMAC");
84 dev
->init
= bfin_EMAC_init
;
85 dev
->halt
= bfin_EMAC_halt
;
86 dev
->send
= bfin_EMAC_send
;
87 dev
->recv
= bfin_EMAC_recv
;
94 static int bfin_EMAC_send(struct eth_device
*dev
, volatile void *packet
,
100 buf
= (unsigned int *)packet
;
103 printf("Ethernet: bad packet size: %d\n", length
);
107 if ((*pDMA2_IRQ_STATUS
& DMA_ERR
) != 0) {
108 printf("Ethernet: tx DMA error\n");
112 for (i
= 0; (*pDMA2_IRQ_STATUS
& DMA_RUN
) != 0; i
++) {
114 puts("Ethernet: tx time out\n");
118 txbuf
[txIdx
]->FrmData
->NoBytes
= length
;
119 memcpy(txbuf
[txIdx
]->FrmData
->Dest
, (void *)packet
, length
);
120 txbuf
[txIdx
]->Dma
[0].START_ADDR
= (u32
) txbuf
[txIdx
]->FrmData
;
121 *pDMA2_NEXT_DESC_PTR
= &txbuf
[txIdx
]->Dma
[0];
122 *pDMA2_CONFIG
= *(u16
*) (void *)(&txdmacfg
);
125 for (i
= 0; (txbuf
[txIdx
]->StatusWord
& TX_COMP
) == 0; i
++) {
127 puts("Ethernet: tx error\n");
131 result
= txbuf
[txIdx
]->StatusWord
;
132 txbuf
[txIdx
]->StatusWord
= 0;
133 if ((txIdx
+ 1) >= TX_BUF_CNT
)
138 DEBUGF("BFIN EMAC send: length = %d\n", length
);
142 static int bfin_EMAC_recv(struct eth_device
*dev
)
147 if ((rxbuf
[rxIdx
]->StatusWord
& RX_COMP
) == 0) {
151 if ((rxbuf
[rxIdx
]->StatusWord
& RX_DMAO
) != 0) {
152 printf("Ethernet: rx dma overrun\n");
155 if ((rxbuf
[rxIdx
]->StatusWord
& RX_OK
) == 0) {
156 printf("Ethernet: rx error\n");
159 length
= rxbuf
[rxIdx
]->StatusWord
& 0x000007FF;
161 printf("Ethernet: bad frame\n");
164 NetRxPackets
[rxIdx
] =
165 (volatile uchar
*)(rxbuf
[rxIdx
]->FrmData
->Dest
);
166 NetReceive(NetRxPackets
[rxIdx
], length
- 4);
167 *pDMA1_IRQ_STATUS
|= DMA_DONE
| DMA_ERR
;
168 rxbuf
[rxIdx
]->StatusWord
= 0x00000000;
169 if ((rxIdx
+ 1) >= PKTBUFSRX
)
178 /**************************************************************
180 * Ethernet Initialization Routine
182 *************************************************************/
184 static int bfin_EMAC_init(struct eth_device
*dev
, bd_t
*bd
)
189 DEBUGF("Eth_init: ......\n");
194 /* Initialize System Register */
195 if (SetupSystemRegs(&dat
) < 0)
198 /* Initialize EMAC address */
199 bfin_EMAC_setup_addr(bd
);
201 /* Initialize TX and RX buffer */
202 for (i
= 0; i
< PKTBUFSRX
; i
++) {
203 rxbuf
[i
] = SetupRxBuffer(i
);
205 rxbuf
[i
- 1]->Dma
[1].NEXT_DESC_PTR
=
207 if (i
== (PKTBUFSRX
- 1))
208 rxbuf
[i
]->Dma
[1].NEXT_DESC_PTR
=
212 for (i
= 0; i
< TX_BUF_CNT
; i
++) {
213 txbuf
[i
] = SetupTxBuffer(i
);
215 txbuf
[i
- 1]->Dma
[1].NEXT_DESC_PTR
=
217 if (i
== (TX_BUF_CNT
- 1))
218 txbuf
[i
]->Dma
[1].NEXT_DESC_PTR
=
224 *pDMA1_NEXT_DESC_PTR
= &rxbuf
[0]->Dma
[0];
225 *pDMA1_CONFIG
= *((u16
*) (void *)&rxbuf
[0]->Dma
[0].CONFIG
);
230 /* We enable only RX here */
231 /* ASTP : Enable Automatic Pad Stripping
232 PR : Promiscuous Mode for test
233 PSF : Receive frames with total length less than 64 bytes.
234 FDMODE : Full Duplex Mode
235 LB : Internal Loopback for test
236 RE : Receiver Enable */
238 opmode
= ASTP
| FDMODE
| PSF
;
242 #ifdef CONFIG_BFIN_MAC_RMII
245 /* Turn on the EMAC */
246 *pEMAC_OPMODE
= opmode
;
250 static void bfin_EMAC_halt(struct eth_device
*dev
)
252 DEBUGF("Eth_halt: ......\n");
253 /* Turn off the EMAC */
254 *pEMAC_OPMODE
= 0x00000000;
255 /* Turn off the EMAC RX DMA */
256 *pDMA1_CONFIG
= 0x0000;
257 *pDMA2_CONFIG
= 0x0000;
261 void bfin_EMAC_setup_addr(bd_t
*bd
)
265 bd
->bi_enetaddr
[1] << 8 |
266 bd
->bi_enetaddr
[2] << 16 |
267 bd
->bi_enetaddr
[3] << 24;
270 bd
->bi_enetaddr
[5] << 8;
273 static void PollMdcDone(void)
275 /* poll the STABUSY bit */
276 while (*pEMAC_STAADD
& STABUSY
) ;
279 static void WrPHYReg(u16 PHYAddr
, u16 RegAddr
, u16 Data
)
283 *pEMAC_STADAT
= Data
;
285 *pEMAC_STAADD
= SET_PHYAD(PHYAddr
) | SET_REGAD(RegAddr
) |
286 STAOP
| STAIE
| STABUSY
;
289 /*********************************************************************************
290 * Read an off-chip register in a PHY through the MDC/MDIO port *
291 *********************************************************************************/
292 static u16
RdPHYReg(u16 PHYAddr
, u16 RegAddr
)
298 *pEMAC_STAADD
= SET_PHYAD(PHYAddr
) | SET_REGAD(RegAddr
) |
303 Data
= (u16
) * pEMAC_STADAT
;
305 PHYregs
[RegAddr
] = Data
; /* save shadow copy */
310 #if 0 /* dead code ? */
311 static void SoftResetPHY(void)
314 /* set the reset bit */
315 WrPHYReg(PHYADDR
, PHY_MODECTL
, PHY_RESET
);
316 /* and clear it again */
317 WrPHYReg(PHYADDR
, PHY_MODECTL
, 0x0000);
319 /* poll until reset is complete */
320 phydat
= RdPHYReg(PHYADDR
, PHY_MODECTL
);
321 } while ((phydat
& PHY_RESET
) != 0);
325 static int SetupSystemRegs(int *opmode
)
329 /* Enable PHY output */
330 *pVR_CTL
|= CLKBUFOE
;
331 /* Set all the pins to peripheral mode */
333 #ifndef CONFIG_BFIN_MAC_RMII
334 *pPORTH_FER
= 0xFFFF;
336 *pPORTH_MUX
= PORT_x_MUX_0_FUNC_2
| PORT_x_MUX_1_FUNC_2
| PORT_x_MUX_2_FUNC_2
;
339 #if defined(__ADSPBF536__) || defined(__ADSPBF537__)
340 *pPORTH_FER
= 0xC373;
343 *pPORTH_FER
= 0x01FF;
344 *pPORTH_MUX
= PORT_x_MUX_0_FUNC_2
| PORT_x_MUX_1_FUNC_2
;
348 sysctl
= SET_MDCDIV(24);
349 /* Odd word alignment for Receive Frame DMA word */
350 /* Configure checksum support and rcve frame word alignment */
351 sysctl
|= RXDWA
| RXCKS
;
352 *pEMAC_SYSCTL
= sysctl
;
353 /* auto negotiation on */
356 phydat
= PHY_ANEG_EN
| PHY_DUPLEX
| PHY_SPD_SET
;
357 WrPHYReg(PHYADDR
, PHY_MODECTL
, phydat
);
360 phydat
= RdPHYReg(PHYADDR
, PHY_MODESTAT
);
363 ("Link is down, please check your network connection\n");
367 } while (!(phydat
& 0x0004));
369 phydat
= RdPHYReg(PHYADDR
, PHY_ANLPAR
);
371 if ((phydat
& 0x0100) || (phydat
& 0x0040))
376 *pEMAC_MMC_CTL
= RSTC
| CROLL
;
378 /* Initialize the TX DMA channel registers */
384 /* Initialize the RX DMA channel registers */
392 ADI_ETHER_BUFFER
*SetupRxBuffer(int no
)
394 ADI_ETHER_FRAME_BUFFER
*frmbuf
;
395 ADI_ETHER_BUFFER
*buf
;
396 int nobytes_buffer
= sizeof(ADI_ETHER_BUFFER
[2]) / 2; /* ensure a multi. of 4 */
397 int total_size
= nobytes_buffer
+ RECV_BUFSIZE
;
399 buf
= (ADI_ETHER_BUFFER
*) (RXBUF_BASE_ADDR
+ no
* total_size
);
401 (ADI_ETHER_FRAME_BUFFER
*) (RXBUF_BASE_ADDR
+ no
* total_size
+
404 memset(buf
, 0x00, nobytes_buffer
);
405 buf
->FrmData
= frmbuf
;
406 memset(frmbuf
, 0xfe, RECV_BUFSIZE
);
408 /* set up first desc to point to receive frame buffer */
409 buf
->Dma
[0].NEXT_DESC_PTR
= &(buf
->Dma
[1]);
410 buf
->Dma
[0].START_ADDR
= (u32
) buf
->FrmData
;
411 buf
->Dma
[0].CONFIG
.b_DMA_EN
= 1; /* enabled */
412 buf
->Dma
[0].CONFIG
.b_WNR
= 1; /* Write to memory */
413 buf
->Dma
[0].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
414 buf
->Dma
[0].CONFIG
.b_NDSIZE
= 5; /* 5 half words is desc size. */
415 buf
->Dma
[0].CONFIG
.b_FLOW
= 7; /* large desc flow */
417 /* set up second desc to point to status word */
418 buf
->Dma
[1].NEXT_DESC_PTR
= &(buf
->Dma
[0]);
419 buf
->Dma
[1].START_ADDR
= (u32
) & buf
->IPHdrChksum
;
420 buf
->Dma
[1].CONFIG
.b_DMA_EN
= 1; /* enabled */
421 buf
->Dma
[1].CONFIG
.b_WNR
= 1; /* Write to memory */
422 buf
->Dma
[1].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
423 buf
->Dma
[1].CONFIG
.b_DI_EN
= 1; /* enable interrupt */
424 buf
->Dma
[1].CONFIG
.b_NDSIZE
= 5; /* must be 0 when FLOW is 0 */
425 buf
->Dma
[1].CONFIG
.b_FLOW
= 7; /* stop */
430 ADI_ETHER_BUFFER
*SetupTxBuffer(int no
)
432 ADI_ETHER_FRAME_BUFFER
*frmbuf
;
433 ADI_ETHER_BUFFER
*buf
;
434 int nobytes_buffer
= sizeof(ADI_ETHER_BUFFER
[2]) / 2; /* ensure a multi. of 4 */
435 int total_size
= nobytes_buffer
+ RECV_BUFSIZE
;
437 buf
= (ADI_ETHER_BUFFER
*) (TXBUF_BASE_ADDR
+ no
* total_size
);
439 (ADI_ETHER_FRAME_BUFFER
*) (TXBUF_BASE_ADDR
+ no
* total_size
+
442 memset(buf
, 0x00, nobytes_buffer
);
443 buf
->FrmData
= frmbuf
;
444 memset(frmbuf
, 0x00, RECV_BUFSIZE
);
446 /* set up first desc to point to receive frame buffer */
447 buf
->Dma
[0].NEXT_DESC_PTR
= &(buf
->Dma
[1]);
448 buf
->Dma
[0].START_ADDR
= (u32
) buf
->FrmData
;
449 buf
->Dma
[0].CONFIG
.b_DMA_EN
= 1; /* enabled */
450 buf
->Dma
[0].CONFIG
.b_WNR
= 0; /* Read to memory */
451 buf
->Dma
[0].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
452 buf
->Dma
[0].CONFIG
.b_NDSIZE
= 5; /* 5 half words is desc size. */
453 buf
->Dma
[0].CONFIG
.b_FLOW
= 7; /* large desc flow */
455 /* set up second desc to point to status word */
456 buf
->Dma
[1].NEXT_DESC_PTR
= &(buf
->Dma
[0]);
457 buf
->Dma
[1].START_ADDR
= (u32
) & buf
->StatusWord
;
458 buf
->Dma
[1].CONFIG
.b_DMA_EN
= 1; /* enabled */
459 buf
->Dma
[1].CONFIG
.b_WNR
= 1; /* Write to memory */
460 buf
->Dma
[1].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
461 buf
->Dma
[1].CONFIG
.b_DI_EN
= 1; /* enable interrupt */
462 buf
->Dma
[1].CONFIG
.b_NDSIZE
= 0; /* must be 0 when FLOW is 0 */
463 buf
->Dma
[1].CONFIG
.b_FLOW
= 0; /* stop */
468 #if defined(CONFIG_POST) && defined(CFG_POST_ETHER)
469 int ether_post_test(int flags
)
475 printf("\n--------");
476 bfin_EMAC_init(NULL
, NULL
);
477 /* construct the package */
478 buf
[0] = buf
[6] = (unsigned char)(*pEMAC_ADDRLO
& 0xFF);
479 buf
[1] = buf
[7] = (unsigned char)((*pEMAC_ADDRLO
& 0xFF00) >> 8);
480 buf
[2] = buf
[8] = (unsigned char)((*pEMAC_ADDRLO
& 0xFF0000) >> 16);
481 buf
[3] = buf
[9] = (unsigned char)((*pEMAC_ADDRLO
& 0xFF000000) >> 24);
482 buf
[4] = buf
[10] = (unsigned char)(*pEMAC_ADDRHI
& 0xFF);
483 buf
[5] = buf
[11] = (unsigned char)((*pEMAC_ADDRHI
& 0xFF00) >> 8);
484 buf
[12] = 0x08; /* Type: ARP */
486 buf
[14] = 0x00; /* Hardware type: Ethernet */
488 buf
[16] = 0x08; /* Protocal type: IP */
490 buf
[18] = 0x06; /* Hardware size */
491 buf
[19] = 0x04; /* Protocol size */
492 buf
[20] = 0x00; /* Opcode: request */
495 for (i
= 0; i
< 42; i
++)
497 printf("--------Send 64 bytes......\n");
498 bfin_EMAC_send(NULL
, (volatile void *)buf
, 64);
499 for (i
= 0; i
< 100; i
++) {
501 if ((rxbuf
[rxIdx
]->StatusWord
& RX_COMP
) != 0) {
507 printf("--------EMAC can't receive any data\n");
511 length
= rxbuf
[rxIdx
]->StatusWord
& 0x000007FF - 4;
512 for (i
= 0; i
< length
; i
++) {
513 if (rxbuf
[rxIdx
]->FrmData
->Dest
[i
] != buf
[i
]) {
514 printf("--------EMAC receive error data!\n");
519 printf("--------receive %d bytes, matched\n", length
);
520 bfin_EMAC_halt(NULL
);