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