]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/bfin_mac.c
Blackfin: bfin_mac: hook up new write_hwaddr function
[karo-tx-uboot.git] / drivers / net / bfin_mac.c
1 /*
2  * Driver for Blackfin On-Chip MAC device
3  *
4  * Copyright (c) 2005-2008 Analog Device, Inc.
5  *
6  * Licensed under the GPL-2 or later.
7  */
8
9 #include <common.h>
10 #include <config.h>
11 #include <net.h>
12 #include <netdev.h>
13 #include <command.h>
14 #include <malloc.h>
15 #include <miiphy.h>
16 #include <linux/mii.h>
17
18 #include <asm/blackfin.h>
19 #include <asm/mach-common/bits/dma.h>
20 #include <asm/mach-common/bits/emac.h>
21 #include <asm/mach-common/bits/pll.h>
22
23 #include "bfin_mac.h"
24
25 #ifndef CONFIG_PHY_ADDR
26 # define CONFIG_PHY_ADDR 1
27 #endif
28 #ifndef CONFIG_PHY_CLOCK_FREQ
29 # define CONFIG_PHY_CLOCK_FREQ 2500000
30 #endif
31
32 #ifdef CONFIG_POST
33 #include <post.h>
34 #endif
35
36 #define RXBUF_BASE_ADDR         0xFF900000
37 #define TXBUF_BASE_ADDR         0xFF800000
38 #define TX_BUF_CNT              1
39
40 #define TOUT_LOOP               1000000
41
42 static ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT];
43 static ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
44 static u16 txIdx;               /* index of the current RX buffer */
45 static u16 rxIdx;               /* index of the current TX buffer */
46
47 /* DMAx_CONFIG values at DMA Restart */
48 static const union {
49         u16 data;
50         ADI_DMA_CONFIG_REG reg;
51 } txdmacfg = {
52         .reg = {
53                 .b_DMA_EN  = 1, /* enabled */
54                 .b_WNR     = 0, /* read from memory */
55                 .b_WDSIZE  = 2, /* wordsize is 32 bits */
56                 .b_DMA2D   = 0,
57                 .b_RESTART = 0,
58                 .b_DI_SEL  = 0,
59                 .b_DI_EN   = 0, /* no interrupt */
60                 .b_NDSIZE  = 5, /* 5 half words is desc size */
61                 .b_FLOW    = 7  /* large desc flow */
62         },
63 };
64
65 static int bfin_miiphy_wait(void)
66 {
67         /* poll the STABUSY bit */
68         while (bfin_read_EMAC_STAADD() & STABUSY)
69                 continue;
70         return 0;
71 }
72
73 static int bfin_miiphy_read(char *devname, uchar addr, uchar reg, ushort *val)
74 {
75         if (bfin_miiphy_wait())
76                 return 1;
77         bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STABUSY);
78         if (bfin_miiphy_wait())
79                 return 1;
80         *val = bfin_read_EMAC_STADAT();
81         return 0;
82 }
83
84 static int bfin_miiphy_write(char *devname, uchar addr, uchar reg, ushort val)
85 {
86         if (bfin_miiphy_wait())
87                 return 1;
88         bfin_write_EMAC_STADAT(val);
89         bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STAOP | STABUSY);
90         return 0;
91 }
92
93 int bfin_EMAC_initialize(bd_t *bis)
94 {
95         struct eth_device *dev;
96         dev = malloc(sizeof(*dev));
97         if (dev == NULL)
98                 hang();
99
100         memset(dev, 0, sizeof(*dev));
101         sprintf(dev->name, "Blackfin EMAC");
102
103         dev->iobase = 0;
104         dev->priv = 0;
105         dev->init = bfin_EMAC_init;
106         dev->halt = bfin_EMAC_halt;
107         dev->send = bfin_EMAC_send;
108         dev->recv = bfin_EMAC_recv;
109         dev->write_hwaddr = bfin_EMAC_setup_addr;
110
111         eth_register(dev);
112
113 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
114         miiphy_register(dev->name, bfin_miiphy_read, bfin_miiphy_write);
115 #endif
116
117         return 0;
118 }
119
120 static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
121                           int length)
122 {
123         int i;
124         int result = 0;
125         unsigned int *buf;
126         buf = (unsigned int *)packet;
127
128         if (length <= 0) {
129                 printf("Ethernet: bad packet size: %d\n", length);
130                 goto out;
131         }
132
133         if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) {
134                 printf("Ethernet: tx DMA error\n");
135                 goto out;
136         }
137
138         for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) {
139                 if (i > TOUT_LOOP) {
140                         puts("Ethernet: tx time out\n");
141                         goto out;
142                 }
143         }
144         txbuf[txIdx]->FrmData->NoBytes = length;
145         memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length);
146         txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData;
147         *pDMA2_NEXT_DESC_PTR = txbuf[txIdx]->Dma;
148         *pDMA2_CONFIG = txdmacfg.data;
149         *pEMAC_OPMODE |= TE;
150
151         for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) {
152                 if (i > TOUT_LOOP) {
153                         puts("Ethernet: tx error\n");
154                         goto out;
155                 }
156         }
157         result = txbuf[txIdx]->StatusWord;
158         txbuf[txIdx]->StatusWord = 0;
159         if ((txIdx + 1) >= TX_BUF_CNT)
160                 txIdx = 0;
161         else
162                 txIdx++;
163  out:
164         debug("BFIN EMAC send: length = %d\n", length);
165         return result;
166 }
167
168 static int bfin_EMAC_recv(struct eth_device *dev)
169 {
170         int length = 0;
171
172         for (;;) {
173                 if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) {
174                         length = -1;
175                         break;
176                 }
177                 if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) {
178                         printf("Ethernet: rx dma overrun\n");
179                         break;
180                 }
181                 if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) {
182                         printf("Ethernet: rx error\n");
183                         break;
184                 }
185                 length = rxbuf[rxIdx]->StatusWord & 0x000007FF;
186                 if (length <= 4) {
187                         printf("Ethernet: bad frame\n");
188                         break;
189                 }
190
191                 debug("%s: len = %d\n", __func__, length - 4);
192
193                 NetRxPackets[rxIdx] =
194                     (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest);
195                 NetReceive(NetRxPackets[rxIdx], length - 4);
196                 *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR;
197                 rxbuf[rxIdx]->StatusWord = 0x00000000;
198                 if ((rxIdx + 1) >= PKTBUFSRX)
199                         rxIdx = 0;
200                 else
201                         rxIdx++;
202         }
203
204         return length;
205 }
206
207 /**************************************************************
208  *
209  * Ethernet Initialization Routine
210  *
211  *************************************************************/
212
213 /* MDC = SCLK / MDC_freq / 2 - 1 */
214 #define MDC_FREQ_TO_DIV(mdc_freq) (get_sclk() / (mdc_freq) / 2 - 1)
215
216 static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
217 {
218         u16 phydat;
219         size_t count;
220
221         /* Enable PHY output */
222         *pVR_CTL |= CLKBUFOE;
223
224         /* Set all the pins to peripheral mode */
225 #ifdef CONFIG_RMII
226         /* grab RMII pins */
227 # if defined(__ADSPBF51x__)
228         *pPORTF_MUX = (*pPORTF_MUX & \
229                 ~(PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
230                 PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
231         *pPORTF_FER |= PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
232         *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
233         *pPORTG_FER |= PG0 | PG1 | PG2;
234 # elif defined(__ADSPBF52x__)
235         *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
236         *pPORTG_FER |= PG14 | PG15;
237         *pPORTH_MUX = (*pPORTH_MUX & ~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK)) | \
238                 PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2;
239         *pPORTH_FER |= PH0 | PH1 | PH2 | PH3 | PH4 | PH5 | PH6 | PH7 | PH8;
240 # else
241         *pPORTH_FER |= PH0 | PH1 | PH4 | PH5 | PH6 | PH8 | PH9 | PH14 | PH15;
242 # endif
243 #else
244         /* grab MII & RMII pins */
245 # if defined(__ADSPBF51x__)
246         *pPORTF_MUX = (*pPORTF_MUX & \
247                 ~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK | PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
248                 PORT_x_MUX_0_FUNC_1 | PORT_x_MUX_1_FUNC_1 | PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
249         *pPORTF_FER |= PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
250         *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
251         *pPORTG_FER |= PG0 | PG1 | PG2;
252 # elif defined(__ADSPBF52x__)
253         *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
254         *pPORTG_FER |= PG14 | PG15;
255         *pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2;
256         *pPORTH_FER = -1; /* all pins */
257 # else
258         *pPORTH_FER = -1; /* all pins */
259 # endif
260 #endif
261
262         /* Odd word alignment for Receive Frame DMA word */
263         /* Configure checksum support and rcve frame word alignment */
264         bfin_write_EMAC_SYSCTL(RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(CONFIG_PHY_CLOCK_FREQ)));
265
266         /* turn on auto-negotiation and wait for link to come up */
267         bfin_miiphy_write(dev->name, CONFIG_PHY_ADDR, MII_BMCR, BMCR_ANENABLE);
268         count = 0;
269         while (1) {
270                 ++count;
271                 if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_BMSR, &phydat))
272                         return -1;
273                 if (phydat & BMSR_LSTATUS)
274                         break;
275                 if (count > 30000) {
276                         printf("%s: link down, check cable\n", dev->name);
277                         return -1;
278                 }
279                 udelay(100);
280         }
281
282         /* see what kind of link we have */
283         if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_LPA, &phydat))
284                 return -1;
285         if (phydat & LPA_DUPLEX)
286                 *opmode = FDMODE;
287         else
288                 *opmode = 0;
289
290         bfin_write_EMAC_MMC_CTL(RSTC | CROLL);
291
292         /* Initialize the TX DMA channel registers */
293         *pDMA2_X_COUNT = 0;
294         *pDMA2_X_MODIFY = 4;
295         *pDMA2_Y_COUNT = 0;
296         *pDMA2_Y_MODIFY = 0;
297
298         /* Initialize the RX DMA channel registers */
299         *pDMA1_X_COUNT = 0;
300         *pDMA1_X_MODIFY = 4;
301         *pDMA1_Y_COUNT = 0;
302         *pDMA1_Y_MODIFY = 0;
303
304         return 0;
305 }
306
307 static int bfin_EMAC_setup_addr(struct eth_device *dev)
308 {
309         *pEMAC_ADDRLO =
310                 dev->enetaddr[0] |
311                 dev->enetaddr[1] << 8 |
312                 dev->enetaddr[2] << 16 |
313                 dev->enetaddr[3] << 24;
314         *pEMAC_ADDRHI =
315                 dev->enetaddr[4] |
316                 dev->enetaddr[5] << 8;
317         return 0;
318 }
319
320 static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
321 {
322         u32 opmode;
323         int dat;
324         int i;
325         debug("Eth_init: ......\n");
326
327         txIdx = 0;
328         rxIdx = 0;
329
330         /* Initialize System Register */
331         if (bfin_miiphy_init(dev, &dat) < 0)
332                 return -1;
333
334         /* Initialize EMAC address */
335         bfin_EMAC_setup_addr(dev);
336
337         /* Initialize TX and RX buffer */
338         for (i = 0; i < PKTBUFSRX; i++) {
339                 rxbuf[i] = SetupRxBuffer(i);
340                 if (i > 0) {
341                         rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR = rxbuf[i]->Dma;
342                         if (i == (PKTBUFSRX - 1))
343                                 rxbuf[i]->Dma[1].NEXT_DESC_PTR = rxbuf[0]->Dma;
344                 }
345         }
346         for (i = 0; i < TX_BUF_CNT; i++) {
347                 txbuf[i] = SetupTxBuffer(i);
348                 if (i > 0) {
349                         txbuf[i - 1]->Dma[1].NEXT_DESC_PTR = txbuf[i]->Dma;
350                         if (i == (TX_BUF_CNT - 1))
351                                 txbuf[i]->Dma[1].NEXT_DESC_PTR = txbuf[0]->Dma;
352                 }
353         }
354
355         /* Set RX DMA */
356         *pDMA1_NEXT_DESC_PTR = rxbuf[0]->Dma;
357         *pDMA1_CONFIG = rxbuf[0]->Dma[0].CONFIG_DATA;
358
359         /* Wait MII done */
360         bfin_miiphy_wait();
361
362         /* We enable only RX here */
363         /* ASTP   : Enable Automatic Pad Stripping
364            PR     : Promiscuous Mode for test
365            PSF    : Receive frames with total length less than 64 bytes.
366            FDMODE : Full Duplex Mode
367            LB     : Internal Loopback for test
368            RE     : Receiver Enable */
369         if (dat == FDMODE)
370                 opmode = ASTP | FDMODE | PSF;
371         else
372                 opmode = ASTP | PSF;
373         opmode |= RE;
374 #ifdef CONFIG_RMII
375         opmode |= TE | RMII;
376 #endif
377         /* Turn on the EMAC */
378         *pEMAC_OPMODE = opmode;
379         return 0;
380 }
381
382 static void bfin_EMAC_halt(struct eth_device *dev)
383 {
384         debug("Eth_halt: ......\n");
385         /* Turn off the EMAC */
386         *pEMAC_OPMODE = 0x00000000;
387         /* Turn off the EMAC RX DMA */
388         *pDMA1_CONFIG = 0x0000;
389         *pDMA2_CONFIG = 0x0000;
390
391 }
392
393 ADI_ETHER_BUFFER *SetupRxBuffer(int no)
394 {
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;
399
400         buf = (void *) (RXBUF_BASE_ADDR + no * total_size);
401         frmbuf = (void *) (RXBUF_BASE_ADDR + no * total_size + nobytes_buffer);
402
403         memset(buf, 0x00, nobytes_buffer);
404         buf->FrmData = frmbuf;
405         memset(frmbuf, 0xfe, RECV_BUFSIZE);
406
407         /* set up first desc to point to receive frame buffer */
408         buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);
409         buf->Dma[0].START_ADDR = (u32) buf->FrmData;
410         buf->Dma[0].CONFIG.b_DMA_EN = 1;        /* enabled */
411         buf->Dma[0].CONFIG.b_WNR = 1;   /* Write to memory */
412         buf->Dma[0].CONFIG.b_WDSIZE = 2;        /* wordsize is 32 bits */
413         buf->Dma[0].CONFIG.b_NDSIZE = 5;        /* 5 half words is desc size. */
414         buf->Dma[0].CONFIG.b_FLOW = 7;  /* large desc flow */
415
416         /* set up second desc to point to status word */
417         buf->Dma[1].NEXT_DESC_PTR = buf->Dma;
418         buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum;
419         buf->Dma[1].CONFIG.b_DMA_EN = 1;        /* enabled */
420         buf->Dma[1].CONFIG.b_WNR = 1;   /* Write to memory */
421         buf->Dma[1].CONFIG.b_WDSIZE = 2;        /* wordsize is 32 bits */
422         buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */
423         buf->Dma[1].CONFIG.b_NDSIZE = 5;        /* must be 0 when FLOW is 0 */
424         buf->Dma[1].CONFIG.b_FLOW = 7;  /* stop */
425
426         return buf;
427 }
428
429 ADI_ETHER_BUFFER *SetupTxBuffer(int no)
430 {
431         ADI_ETHER_FRAME_BUFFER *frmbuf;
432         ADI_ETHER_BUFFER *buf;
433         int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2;   /* ensure a multi. of 4 */
434         int total_size = nobytes_buffer + RECV_BUFSIZE;
435
436         buf = (void *) (TXBUF_BASE_ADDR + no * total_size);
437         frmbuf = (void *) (TXBUF_BASE_ADDR + no * total_size + nobytes_buffer);
438
439         memset(buf, 0x00, nobytes_buffer);
440         buf->FrmData = frmbuf;
441         memset(frmbuf, 0x00, RECV_BUFSIZE);
442
443         /* set up first desc to point to receive frame buffer */
444         buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);
445         buf->Dma[0].START_ADDR = (u32) buf->FrmData;
446         buf->Dma[0].CONFIG.b_DMA_EN = 1;        /* enabled */
447         buf->Dma[0].CONFIG.b_WNR = 0;   /* Read to memory */
448         buf->Dma[0].CONFIG.b_WDSIZE = 2;        /* wordsize is 32 bits */
449         buf->Dma[0].CONFIG.b_NDSIZE = 5;        /* 5 half words is desc size. */
450         buf->Dma[0].CONFIG.b_FLOW = 7;  /* large desc flow */
451
452         /* set up second desc to point to status word */
453         buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]);
454         buf->Dma[1].START_ADDR = (u32) & buf->StatusWord;
455         buf->Dma[1].CONFIG.b_DMA_EN = 1;        /* enabled */
456         buf->Dma[1].CONFIG.b_WNR = 1;   /* Write to memory */
457         buf->Dma[1].CONFIG.b_WDSIZE = 2;        /* wordsize is 32 bits */
458         buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */
459         buf->Dma[1].CONFIG.b_NDSIZE = 0;        /* must be 0 when FLOW is 0 */
460         buf->Dma[1].CONFIG.b_FLOW = 0;  /* stop */
461
462         return buf;
463 }
464
465 #if defined(CONFIG_POST) && defined(CONFIG_SYS_POST_ETHER)
466 int ether_post_test(int flags)
467 {
468         uchar buf[64];
469         int i, value = 0;
470         int length;
471
472         printf("\n--------");
473         bfin_EMAC_init(NULL, NULL);
474         /* construct the package */
475         buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF);
476         buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8);
477         buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16);
478         buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24);
479         buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF);
480         buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8);
481         buf[12] = 0x08;         /* Type: ARP */
482         buf[13] = 0x06;
483         buf[14] = 0x00;         /* Hardware type: Ethernet */
484         buf[15] = 0x01;
485         buf[16] = 0x08;         /* Protocal type: IP */
486         buf[17] = 0x00;
487         buf[18] = 0x06;         /* Hardware size    */
488         buf[19] = 0x04;         /* Protocol size    */
489         buf[20] = 0x00;         /* Opcode: request  */
490         buf[21] = 0x01;
491
492         for (i = 0; i < 42; i++)
493                 buf[i + 22] = i;
494         printf("--------Send 64 bytes......\n");
495         bfin_EMAC_send(NULL, (volatile void *)buf, 64);
496         for (i = 0; i < 100; i++) {
497                 udelay(10000);
498                 if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) {
499                         value = 1;
500                         break;
501                 }
502         }
503         if (value == 0) {
504                 printf("--------EMAC can't receive any data\n");
505                 eth_halt();
506                 return -1;
507         }
508         length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4;
509         for (i = 0; i < length; i++) {
510                 if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) {
511                         printf("--------EMAC receive error data!\n");
512                         eth_halt();
513                         return -1;
514                 }
515         }
516         printf("--------receive %d bytes, matched\n", length);
517         bfin_EMAC_halt(NULL);
518         return 0;
519 }
520 #endif