2 * Driver for Blackfin On-Chip MAC device
4 * Copyright (c) 2005-2008 Analog Device, Inc.
6 * Licensed under the GPL-2 or later.
16 #include <asm/blackfin.h>
17 #include <asm/mach-common/bits/dma.h>
18 #include <asm/mach-common/bits/emac.h>
19 #include <asm/mach-common/bits/pll.h>
30 #define DEBUGF(fmt, args...) printf(fmt, ##args)
32 #define DEBUGF(fmt, args...)
35 #define RXBUF_BASE_ADDR 0xFF900000
36 #define TXBUF_BASE_ADDR 0xFF800000
39 #define TOUT_LOOP 1000000
41 ADI_ETHER_BUFFER
*txbuf
[TX_BUF_CNT
];
42 ADI_ETHER_BUFFER
*rxbuf
[PKTBUFSRX
];
43 static u16 txIdx
; /* index of the current RX buffer */
44 static u16 rxIdx
; /* index of the current TX buffer */
46 u16 PHYregs
[NO_PHY_REGS
]; /* u16 PHYADDR; */
48 /* DMAx_CONFIG values at DMA Restart */
49 const ADI_DMA_CONFIG_REG rxdmacfg
= {
50 .b_DMA_EN
= 1, /* enabled */
51 .b_WNR
= 1, /* write to memory */
52 .b_WDSIZE
= 2, /* wordsize is 32 bits */
56 .b_DI_EN
= 0, /* no interrupt */
57 .b_NDSIZE
= 5, /* 5 half words is desc size */
58 .b_FLOW
= 7 /* large desc flow */
61 const ADI_DMA_CONFIG_REG txdmacfg
= {
62 .b_DMA_EN
= 1, /* enabled */
63 .b_WNR
= 0, /* read from memory */
64 .b_WDSIZE
= 2, /* wordsize is 32 bits */
68 .b_DI_EN
= 0, /* no interrupt */
69 .b_NDSIZE
= 5, /* 5 half words is desc size */
70 .b_FLOW
= 7 /* large desc flow */
73 int bfin_EMAC_initialize(bd_t
*bis
)
75 struct eth_device
*dev
;
76 dev
= (struct eth_device
*)malloc(sizeof(*dev
));
80 memset(dev
, 0, sizeof(*dev
));
81 sprintf(dev
->name
, "Blackfin EMAC");
85 dev
->init
= bfin_EMAC_init
;
86 dev
->halt
= bfin_EMAC_halt
;
87 dev
->send
= bfin_EMAC_send
;
88 dev
->recv
= bfin_EMAC_recv
;
95 static int bfin_EMAC_send(struct eth_device
*dev
, volatile void *packet
,
101 buf
= (unsigned int *)packet
;
104 printf("Ethernet: bad packet size: %d\n", length
);
108 if ((*pDMA2_IRQ_STATUS
& DMA_ERR
) != 0) {
109 printf("Ethernet: tx DMA error\n");
113 for (i
= 0; (*pDMA2_IRQ_STATUS
& DMA_RUN
) != 0; i
++) {
115 puts("Ethernet: tx time out\n");
119 txbuf
[txIdx
]->FrmData
->NoBytes
= length
;
120 memcpy(txbuf
[txIdx
]->FrmData
->Dest
, (void *)packet
, length
);
121 txbuf
[txIdx
]->Dma
[0].START_ADDR
= (u32
) txbuf
[txIdx
]->FrmData
;
122 *pDMA2_NEXT_DESC_PTR
= &txbuf
[txIdx
]->Dma
[0];
123 *pDMA2_CONFIG
= *(u16
*) (void *)(&txdmacfg
);
126 for (i
= 0; (txbuf
[txIdx
]->StatusWord
& TX_COMP
) == 0; i
++) {
128 puts("Ethernet: tx error\n");
132 result
= txbuf
[txIdx
]->StatusWord
;
133 txbuf
[txIdx
]->StatusWord
= 0;
134 if ((txIdx
+ 1) >= TX_BUF_CNT
)
139 DEBUGF("BFIN EMAC send: length = %d\n", length
);
143 static int bfin_EMAC_recv(struct eth_device
*dev
)
148 if ((rxbuf
[rxIdx
]->StatusWord
& RX_COMP
) == 0) {
152 if ((rxbuf
[rxIdx
]->StatusWord
& RX_DMAO
) != 0) {
153 printf("Ethernet: rx dma overrun\n");
156 if ((rxbuf
[rxIdx
]->StatusWord
& RX_OK
) == 0) {
157 printf("Ethernet: rx error\n");
160 length
= rxbuf
[rxIdx
]->StatusWord
& 0x000007FF;
162 printf("Ethernet: bad frame\n");
165 NetRxPackets
[rxIdx
] =
166 (volatile uchar
*)(rxbuf
[rxIdx
]->FrmData
->Dest
);
167 NetReceive(NetRxPackets
[rxIdx
], length
- 4);
168 *pDMA1_IRQ_STATUS
|= DMA_DONE
| DMA_ERR
;
169 rxbuf
[rxIdx
]->StatusWord
= 0x00000000;
170 if ((rxIdx
+ 1) >= PKTBUFSRX
)
179 /**************************************************************
181 * Ethernet Initialization Routine
183 *************************************************************/
185 static int bfin_EMAC_init(struct eth_device
*dev
, bd_t
*bd
)
190 DEBUGF("Eth_init: ......\n");
195 /* Initialize System Register */
196 if (SetupSystemRegs(&dat
) < 0)
199 /* Initialize EMAC address */
200 bfin_EMAC_setup_addr(bd
);
202 /* Initialize TX and RX buffer */
203 for (i
= 0; i
< PKTBUFSRX
; i
++) {
204 rxbuf
[i
] = SetupRxBuffer(i
);
206 rxbuf
[i
- 1]->Dma
[1].NEXT_DESC_PTR
=
208 if (i
== (PKTBUFSRX
- 1))
209 rxbuf
[i
]->Dma
[1].NEXT_DESC_PTR
=
213 for (i
= 0; i
< TX_BUF_CNT
; i
++) {
214 txbuf
[i
] = SetupTxBuffer(i
);
216 txbuf
[i
- 1]->Dma
[1].NEXT_DESC_PTR
=
218 if (i
== (TX_BUF_CNT
- 1))
219 txbuf
[i
]->Dma
[1].NEXT_DESC_PTR
=
225 *pDMA1_NEXT_DESC_PTR
= &rxbuf
[0]->Dma
[0];
226 *pDMA1_CONFIG
= *((u16
*) (void *)&rxbuf
[0]->Dma
[0].CONFIG
);
231 /* We enable only RX here */
232 /* ASTP : Enable Automatic Pad Stripping
233 PR : Promiscuous Mode for test
234 PSF : Receive frames with total length less than 64 bytes.
235 FDMODE : Full Duplex Mode
236 LB : Internal Loopback for test
237 RE : Receiver Enable */
239 opmode
= ASTP
| FDMODE
| PSF
;
243 #ifdef CONFIG_BFIN_MAC_RMII
246 /* Turn on the EMAC */
247 *pEMAC_OPMODE
= opmode
;
251 static void bfin_EMAC_halt(struct eth_device
*dev
)
253 DEBUGF("Eth_halt: ......\n");
254 /* Turn off the EMAC */
255 *pEMAC_OPMODE
= 0x00000000;
256 /* Turn off the EMAC RX DMA */
257 *pDMA1_CONFIG
= 0x0000;
258 *pDMA2_CONFIG
= 0x0000;
262 void bfin_EMAC_setup_addr(bd_t
*bd
)
266 bd
->bi_enetaddr
[1] << 8 |
267 bd
->bi_enetaddr
[2] << 16 |
268 bd
->bi_enetaddr
[3] << 24;
271 bd
->bi_enetaddr
[5] << 8;
274 static void PollMdcDone(void)
276 /* poll the STABUSY bit */
277 while (*pEMAC_STAADD
& STABUSY
) ;
280 static void WrPHYReg(u16 PHYAddr
, u16 RegAddr
, u16 Data
)
284 *pEMAC_STADAT
= Data
;
286 *pEMAC_STAADD
= SET_PHYAD(PHYAddr
) | SET_REGAD(RegAddr
) |
287 STAOP
| STAIE
| STABUSY
;
290 /*********************************************************************************
291 * Read an off-chip register in a PHY through the MDC/MDIO port *
292 *********************************************************************************/
293 static u16
RdPHYReg(u16 PHYAddr
, u16 RegAddr
)
299 *pEMAC_STAADD
= SET_PHYAD(PHYAddr
) | SET_REGAD(RegAddr
) |
304 Data
= (u16
) * pEMAC_STADAT
;
306 PHYregs
[RegAddr
] = Data
; /* save shadow copy */
311 #if 0 /* dead code ? */
312 static void SoftResetPHY(void)
315 /* set the reset bit */
316 WrPHYReg(PHYADDR
, PHY_MODECTL
, PHY_RESET
);
317 /* and clear it again */
318 WrPHYReg(PHYADDR
, PHY_MODECTL
, 0x0000);
320 /* poll until reset is complete */
321 phydat
= RdPHYReg(PHYADDR
, PHY_MODECTL
);
322 } while ((phydat
& PHY_RESET
) != 0);
326 static int SetupSystemRegs(int *opmode
)
330 /* Enable PHY output */
331 *pVR_CTL
|= CLKBUFOE
;
332 /* Set all the pins to peripheral mode */
334 #ifndef CONFIG_BFIN_MAC_RMII
335 *pPORTH_FER
= 0xFFFF;
337 *pPORTH_MUX
= PORT_x_MUX_0_FUNC_2
| PORT_x_MUX_1_FUNC_2
| PORT_x_MUX_2_FUNC_2
;
340 #if defined(__ADSPBF536__) || defined(__ADSPBF537__)
341 *pPORTH_FER
= 0xC373;
344 *pPORTH_FER
= 0x01FF;
345 *pPORTH_MUX
= PORT_x_MUX_0_FUNC_2
| PORT_x_MUX_1_FUNC_2
;
349 sysctl
= SET_MDCDIV(24);
350 /* Odd word alignment for Receive Frame DMA word */
351 /* Configure checksum support and rcve frame word alignment */
352 sysctl
|= RXDWA
| RXCKS
;
353 *pEMAC_SYSCTL
= sysctl
;
354 /* auto negotiation on */
357 phydat
= PHY_ANEG_EN
| PHY_DUPLEX
| PHY_SPD_SET
;
358 WrPHYReg(PHYADDR
, PHY_MODECTL
, phydat
);
361 phydat
= RdPHYReg(PHYADDR
, PHY_MODESTAT
);
364 ("Link is down, please check your network connection\n");
368 } while (!(phydat
& 0x0004));
370 phydat
= RdPHYReg(PHYADDR
, PHY_ANLPAR
);
372 if ((phydat
& 0x0100) || (phydat
& 0x0040))
377 *pEMAC_MMC_CTL
= RSTC
| CROLL
;
379 /* Initialize the TX DMA channel registers */
385 /* Initialize the RX DMA channel registers */
393 ADI_ETHER_BUFFER
*SetupRxBuffer(int no
)
395 ADI_ETHER_FRAME_BUFFER
*frmbuf
;
396 ADI_ETHER_BUFFER
*buf
;
397 int nobytes_buffer
= sizeof(ADI_ETHER_BUFFER
[2]) / 2; /* ensure a multi. of 4 */
398 int total_size
= nobytes_buffer
+ RECV_BUFSIZE
;
400 buf
= (ADI_ETHER_BUFFER
*) (RXBUF_BASE_ADDR
+ no
* total_size
);
402 (ADI_ETHER_FRAME_BUFFER
*) (RXBUF_BASE_ADDR
+ no
* total_size
+
405 memset(buf
, 0x00, nobytes_buffer
);
406 buf
->FrmData
= frmbuf
;
407 memset(frmbuf
, 0xfe, RECV_BUFSIZE
);
409 /* set up first desc to point to receive frame buffer */
410 buf
->Dma
[0].NEXT_DESC_PTR
= &(buf
->Dma
[1]);
411 buf
->Dma
[0].START_ADDR
= (u32
) buf
->FrmData
;
412 buf
->Dma
[0].CONFIG
.b_DMA_EN
= 1; /* enabled */
413 buf
->Dma
[0].CONFIG
.b_WNR
= 1; /* Write to memory */
414 buf
->Dma
[0].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
415 buf
->Dma
[0].CONFIG
.b_NDSIZE
= 5; /* 5 half words is desc size. */
416 buf
->Dma
[0].CONFIG
.b_FLOW
= 7; /* large desc flow */
418 /* set up second desc to point to status word */
419 buf
->Dma
[1].NEXT_DESC_PTR
= &(buf
->Dma
[0]);
420 buf
->Dma
[1].START_ADDR
= (u32
) & buf
->IPHdrChksum
;
421 buf
->Dma
[1].CONFIG
.b_DMA_EN
= 1; /* enabled */
422 buf
->Dma
[1].CONFIG
.b_WNR
= 1; /* Write to memory */
423 buf
->Dma
[1].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
424 buf
->Dma
[1].CONFIG
.b_DI_EN
= 1; /* enable interrupt */
425 buf
->Dma
[1].CONFIG
.b_NDSIZE
= 5; /* must be 0 when FLOW is 0 */
426 buf
->Dma
[1].CONFIG
.b_FLOW
= 7; /* stop */
431 ADI_ETHER_BUFFER
*SetupTxBuffer(int no
)
433 ADI_ETHER_FRAME_BUFFER
*frmbuf
;
434 ADI_ETHER_BUFFER
*buf
;
435 int nobytes_buffer
= sizeof(ADI_ETHER_BUFFER
[2]) / 2; /* ensure a multi. of 4 */
436 int total_size
= nobytes_buffer
+ RECV_BUFSIZE
;
438 buf
= (ADI_ETHER_BUFFER
*) (TXBUF_BASE_ADDR
+ no
* total_size
);
440 (ADI_ETHER_FRAME_BUFFER
*) (TXBUF_BASE_ADDR
+ no
* total_size
+
443 memset(buf
, 0x00, nobytes_buffer
);
444 buf
->FrmData
= frmbuf
;
445 memset(frmbuf
, 0x00, RECV_BUFSIZE
);
447 /* set up first desc to point to receive frame buffer */
448 buf
->Dma
[0].NEXT_DESC_PTR
= &(buf
->Dma
[1]);
449 buf
->Dma
[0].START_ADDR
= (u32
) buf
->FrmData
;
450 buf
->Dma
[0].CONFIG
.b_DMA_EN
= 1; /* enabled */
451 buf
->Dma
[0].CONFIG
.b_WNR
= 0; /* Read to memory */
452 buf
->Dma
[0].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
453 buf
->Dma
[0].CONFIG
.b_NDSIZE
= 5; /* 5 half words is desc size. */
454 buf
->Dma
[0].CONFIG
.b_FLOW
= 7; /* large desc flow */
456 /* set up second desc to point to status word */
457 buf
->Dma
[1].NEXT_DESC_PTR
= &(buf
->Dma
[0]);
458 buf
->Dma
[1].START_ADDR
= (u32
) & buf
->StatusWord
;
459 buf
->Dma
[1].CONFIG
.b_DMA_EN
= 1; /* enabled */
460 buf
->Dma
[1].CONFIG
.b_WNR
= 1; /* Write to memory */
461 buf
->Dma
[1].CONFIG
.b_WDSIZE
= 2; /* wordsize is 32 bits */
462 buf
->Dma
[1].CONFIG
.b_DI_EN
= 1; /* enable interrupt */
463 buf
->Dma
[1].CONFIG
.b_NDSIZE
= 0; /* must be 0 when FLOW is 0 */
464 buf
->Dma
[1].CONFIG
.b_FLOW
= 0; /* stop */
469 #if defined(CONFIG_POST) && defined(CONFIG_SYS_POST_ETHER)
470 int ether_post_test(int flags
)
476 printf("\n--------");
477 bfin_EMAC_init(NULL
, NULL
);
478 /* construct the package */
479 buf
[0] = buf
[6] = (unsigned char)(*pEMAC_ADDRLO
& 0xFF);
480 buf
[1] = buf
[7] = (unsigned char)((*pEMAC_ADDRLO
& 0xFF00) >> 8);
481 buf
[2] = buf
[8] = (unsigned char)((*pEMAC_ADDRLO
& 0xFF0000) >> 16);
482 buf
[3] = buf
[9] = (unsigned char)((*pEMAC_ADDRLO
& 0xFF000000) >> 24);
483 buf
[4] = buf
[10] = (unsigned char)(*pEMAC_ADDRHI
& 0xFF);
484 buf
[5] = buf
[11] = (unsigned char)((*pEMAC_ADDRHI
& 0xFF00) >> 8);
485 buf
[12] = 0x08; /* Type: ARP */
487 buf
[14] = 0x00; /* Hardware type: Ethernet */
489 buf
[16] = 0x08; /* Protocal type: IP */
491 buf
[18] = 0x06; /* Hardware size */
492 buf
[19] = 0x04; /* Protocol size */
493 buf
[20] = 0x00; /* Opcode: request */
496 for (i
= 0; i
< 42; i
++)
498 printf("--------Send 64 bytes......\n");
499 bfin_EMAC_send(NULL
, (volatile void *)buf
, 64);
500 for (i
= 0; i
< 100; i
++) {
502 if ((rxbuf
[rxIdx
]->StatusWord
& RX_COMP
) != 0) {
508 printf("--------EMAC can't receive any data\n");
512 length
= rxbuf
[rxIdx
]->StatusWord
& 0x000007FF - 4;
513 for (i
= 0; i
< length
; i
++) {
514 if (rxbuf
[rxIdx
]->FrmData
->Dest
[i
] != buf
[i
]) {
515 printf("--------EMAC receive error data!\n");
520 printf("--------receive %d bytes, matched\n", length
);
521 bfin_EMAC_halt(NULL
);