uboot/drivers/net/at91_emac.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2009 BuS Elektronik GmbH & Co. KG
   4 * Jens Scharsig (esw@bus-elektronik.de)
   5 *
   6 * (C) Copyright 2003
   7 * Author : Hamid Ikdoumi (Atmel)
   8 */
   9
  10#include <common.h>
  11#include <asm/io.h>
  12#include <asm/arch/hardware.h>
  13#include <asm/arch/at91_emac.h>
  14#include <asm/arch/clk.h>
  15#include <asm/arch/at91_pio.h>
  16#include <net.h>
  17#include <netdev.h>
  18#include <malloc.h>
  19#include <miiphy.h>
  20#include <linux/mii.h>
  21
  22#undef MII_DEBUG
  23#undef ET_DEBUG
  24
  25#if (CONFIG_SYS_RX_ETH_BUFFER > 1024)
  26#error AT91 EMAC supports max 1024 RX buffers. \
  27        Please decrease the CONFIG_SYS_RX_ETH_BUFFER value
  28#endif
  29
  30#ifndef CONFIG_DRIVER_AT91EMAC_PHYADDR
  31#define CONFIG_DRIVER_AT91EMAC_PHYADDR  0
  32#endif
  33
  34/* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */
  35#if (AT91C_MASTER_CLOCK > 80000000)
  36        #define HCLK_DIV        AT91_EMAC_CFG_MCLK_64
  37#elif (AT91C_MASTER_CLOCK > 40000000)
  38        #define HCLK_DIV        AT91_EMAC_CFG_MCLK_32
  39#elif (AT91C_MASTER_CLOCK > 20000000)
  40        #define HCLK_DIV        AT91_EMAC_CFG_MCLK_16
  41#else
  42        #define HCLK_DIV        AT91_EMAC_CFG_MCLK_8
  43#endif
  44
  45#ifdef ET_DEBUG
  46#define DEBUG_AT91EMAC  1
  47#else
  48#define DEBUG_AT91EMAC  0
  49#endif
  50
  51#ifdef MII_DEBUG
  52#define DEBUG_AT91PHY   1
  53#else
  54#define DEBUG_AT91PHY   0
  55#endif
  56
  57#ifndef CONFIG_DRIVER_AT91EMAC_QUIET
  58#define VERBOSEP        1
  59#else
  60#define VERBOSEP        0
  61#endif
  62
  63#define RBF_ADDR      0xfffffffc
  64#define RBF_OWNER     (1<<0)
  65#define RBF_WRAP      (1<<1)
  66#define RBF_BROADCAST (1<<31)
  67#define RBF_MULTICAST (1<<30)
  68#define RBF_UNICAST   (1<<29)
  69#define RBF_EXTERNAL  (1<<28)
  70#define RBF_UNKNOWN   (1<<27)
  71#define RBF_SIZE      0x07ff
  72#define RBF_LOCAL4    (1<<26)
  73#define RBF_LOCAL3    (1<<25)
  74#define RBF_LOCAL2    (1<<24)
  75#define RBF_LOCAL1    (1<<23)
  76
  77#define RBF_FRAMEMAX CONFIG_SYS_RX_ETH_BUFFER
  78#define RBF_FRAMELEN 0x600
  79
  80typedef struct {
  81        unsigned long addr, size;
  82} rbf_t;
  83
  84typedef struct {
  85        rbf_t           rbfdt[RBF_FRAMEMAX];
  86        unsigned long   rbindex;
  87} emac_device;
  88
  89void at91emac_EnableMDIO(at91_emac_t *at91mac)
  90{
  91        /* Mac CTRL reg set for MDIO enable */
  92        writel(readl(&at91mac->ctl) | AT91_EMAC_CTL_MPE, &at91mac->ctl);
  93}
  94
  95void at91emac_DisableMDIO(at91_emac_t *at91mac)
  96{
  97        /* Mac CTRL reg set for MDIO disable */
  98        writel(readl(&at91mac->ctl) & ~AT91_EMAC_CTL_MPE, &at91mac->ctl);
  99}
 100
 101int  at91emac_read(at91_emac_t *at91mac, unsigned char addr,
 102                unsigned char reg, unsigned short *value)
 103{
 104        unsigned long netstat;
 105        at91emac_EnableMDIO(at91mac);
 106
 107        writel(AT91_EMAC_MAN_HIGH | AT91_EMAC_MAN_RW_R |
 108                AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 |
 109                AT91_EMAC_MAN_PHYA(addr),
 110                &at91mac->man);
 111
 112        do {
 113                netstat = readl(&at91mac->sr);
 114                debug_cond(DEBUG_AT91PHY, "poll SR %08lx\n", netstat);
 115        } while (!(netstat & AT91_EMAC_SR_IDLE));
 116
 117        *value = readl(&at91mac->man) & AT91_EMAC_MAN_DATA_MASK;
 118
 119        at91emac_DisableMDIO(at91mac);
 120
 121        debug_cond(DEBUG_AT91PHY,
 122                "AT91PHY read %p REG(%d)=%x\n", at91mac, reg, *value);
 123
 124        return 0;
 125}
 126
 127int  at91emac_write(at91_emac_t *at91mac, unsigned char addr,
 128                unsigned char reg, unsigned short value)
 129{
 130        unsigned long netstat;
 131        debug_cond(DEBUG_AT91PHY,
 132                "AT91PHY write %p REG(%d)=%p\n", at91mac, reg, &value);
 133
 134        at91emac_EnableMDIO(at91mac);
 135
 136        writel(AT91_EMAC_MAN_HIGH | AT91_EMAC_MAN_RW_W |
 137                AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 |
 138                AT91_EMAC_MAN_PHYA(addr) | (value & AT91_EMAC_MAN_DATA_MASK),
 139                &at91mac->man);
 140
 141        do {
 142                netstat = readl(&at91mac->sr);
 143                debug_cond(DEBUG_AT91PHY, "poll SR %08lx\n", netstat);
 144        } while (!(netstat & AT91_EMAC_SR_IDLE));
 145
 146        at91emac_DisableMDIO(at91mac);
 147
 148        return 0;
 149}
 150
 151#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 152
 153at91_emac_t *get_emacbase_by_name(const char *devname)
 154{
 155        struct eth_device *netdev;
 156
 157        netdev = eth_get_dev_by_name(devname);
 158        return (at91_emac_t *) netdev->iobase;
 159}
 160
 161int at91emac_mii_read(struct mii_dev *bus, int addr, int devad, int reg)
 162{
 163        unsigned short value = 0;
 164        at91_emac_t *emac;
 165
 166        emac = get_emacbase_by_name(bus->name);
 167        at91emac_read(emac , addr, reg, &value);
 168        return value;
 169}
 170
 171
 172int at91emac_mii_write(struct mii_dev *bus, int addr, int devad, int reg,
 173                       u16 value)
 174{
 175        at91_emac_t *emac;
 176
 177        emac = get_emacbase_by_name(bus->name);
 178        at91emac_write(emac, addr, reg, value);
 179        return 0;
 180}
 181
 182#endif
 183
 184static int at91emac_phy_reset(struct eth_device *netdev)
 185{
 186        int i;
 187        u16 status, adv;
 188        at91_emac_t *emac;
 189
 190        emac = (at91_emac_t *) netdev->iobase;
 191
 192        adv = ADVERTISE_CSMA | ADVERTISE_ALL;
 193        at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 194                MII_ADVERTISE, adv);
 195        debug_cond(VERBOSEP, "%s: Starting autonegotiation...\n", netdev->name);
 196        at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMCR,
 197                (BMCR_ANENABLE | BMCR_ANRESTART));
 198
 199        for (i = 0; i < 30000; i++) {
 200                at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 201                        MII_BMSR, &status);
 202                if (status & BMSR_ANEGCOMPLETE)
 203                        break;
 204                udelay(100);
 205        }
 206
 207        if (status & BMSR_ANEGCOMPLETE) {
 208                debug_cond(VERBOSEP,
 209                        "%s: Autonegotiation complete\n", netdev->name);
 210        } else {
 211                printf("%s: Autonegotiation timed out (status=0x%04x)\n",
 212                       netdev->name, status);
 213                return -1;
 214        }
 215        return 0;
 216}
 217
 218static int at91emac_phy_init(struct eth_device *netdev)
 219{
 220        u16 phy_id, status, adv, lpa;
 221        int media, speed, duplex;
 222        int i;
 223        at91_emac_t *emac;
 224
 225        emac = (at91_emac_t *) netdev->iobase;
 226
 227        /* Check if the PHY is up to snuff... */
 228        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 229                MII_PHYSID1, &phy_id);
 230        if (phy_id == 0xffff) {
 231                printf("%s: No PHY present\n", netdev->name);
 232                return -1;
 233        }
 234
 235        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 236                MII_BMSR, &status);
 237
 238        if (!(status & BMSR_LSTATUS)) {
 239                /* Try to re-negotiate if we don't have link already. */
 240                if (at91emac_phy_reset(netdev))
 241                        return -2;
 242
 243                for (i = 0; i < 100000 / 100; i++) {
 244                        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 245                                MII_BMSR, &status);
 246                        if (status & BMSR_LSTATUS)
 247                                break;
 248                        udelay(100);
 249                }
 250        }
 251        if (!(status & BMSR_LSTATUS)) {
 252                debug_cond(VERBOSEP, "%s: link down\n", netdev->name);
 253                return -3;
 254        } else {
 255                at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 256                        MII_ADVERTISE, &adv);
 257                at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 258                        MII_LPA, &lpa);
 259                media = mii_nway_result(lpa & adv);
 260                speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
 261                         ? 1 : 0);
 262                duplex = (media & ADVERTISE_FULL) ? 1 : 0;
 263                debug_cond(VERBOSEP, "%s: link up, %sMbps %s-duplex\n",
 264                       netdev->name,
 265                       speed ? "100" : "10",
 266                       duplex ? "full" : "half");
 267        }
 268        return 0;
 269}
 270
 271int at91emac_UpdateLinkSpeed(at91_emac_t *emac)
 272{
 273        unsigned short stat1;
 274
 275        at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMSR, &stat1);
 276
 277        if (!(stat1 & BMSR_LSTATUS))    /* link status up? */
 278                return -1;
 279
 280        if (stat1 & BMSR_100FULL) {
 281                /*set Emac for 100BaseTX and Full Duplex  */
 282                writel(readl(&emac->cfg) |
 283                        AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD,
 284                        &emac->cfg);
 285                return 0;
 286        }
 287
 288        if (stat1 & BMSR_10FULL) {
 289                /*set MII for 10BaseT and Full Duplex  */
 290                writel((readl(&emac->cfg) &
 291                        ~(AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD)
 292                        ) | AT91_EMAC_CFG_FD,
 293                        &emac->cfg);
 294                return 0;
 295        }
 296
 297        if (stat1 & BMSR_100HALF) {
 298                /*set MII for 100BaseTX and Half Duplex  */
 299                writel((readl(&emac->cfg) &
 300                        ~(AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD)
 301                        ) | AT91_EMAC_CFG_SPD,
 302                        &emac->cfg);
 303                return 0;
 304        }
 305
 306        if (stat1 & BMSR_10HALF) {
 307                /*set MII for 10BaseT and Half Duplex  */
 308                writel((readl(&emac->cfg) &
 309                        ~(AT91_EMAC_CFG_SPD | AT91_EMAC_CFG_FD)),
 310                        &emac->cfg);
 311                return 0;
 312        }
 313        return 0;
 314}
 315
 316static int at91emac_init(struct eth_device *netdev, bd_t *bd)
 317{
 318        int i;
 319        u32 value;
 320        emac_device *dev;
 321        at91_emac_t *emac;
 322        at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIO;
 323
 324        emac = (at91_emac_t *) netdev->iobase;
 325        dev = (emac_device *) netdev->priv;
 326
 327        /* PIO Disable Register */
 328        value = ATMEL_PMX_AA_EMDIO |    ATMEL_PMX_AA_EMDC |
 329                ATMEL_PMX_AA_ERXER |    ATMEL_PMX_AA_ERX1 |
 330                ATMEL_PMX_AA_ERX0 |     ATMEL_PMX_AA_ECRS |
 331                ATMEL_PMX_AA_ETX1 |     ATMEL_PMX_AA_ETX0 |
 332                ATMEL_PMX_AA_ETXEN |    ATMEL_PMX_AA_EREFCK;
 333
 334        writel(value, &pio->pioa.pdr);
 335        writel(value, &pio->pioa.mux.pio2.asr);
 336
 337#ifdef CONFIG_RMII
 338        value = ATMEL_PMX_BA_ERXCK;
 339#else
 340        value = ATMEL_PMX_BA_ERXCK |    ATMEL_PMX_BA_ECOL |
 341                ATMEL_PMX_BA_ERXDV |    ATMEL_PMX_BA_ERX3 |
 342                ATMEL_PMX_BA_ERX2 |     ATMEL_PMX_BA_ETXER |
 343                ATMEL_PMX_BA_ETX3 |     ATMEL_PMX_BA_ETX2;
 344#endif
 345        writel(value, &pio->piob.pdr);
 346        writel(value, &pio->piob.mux.pio2.bsr);
 347
 348        at91_periph_clk_enable(ATMEL_ID_EMAC);
 349
 350        writel(readl(&emac->ctl) | AT91_EMAC_CTL_CSR, &emac->ctl);
 351
 352        /* Init Ethernet buffers */
 353        for (i = 0; i < RBF_FRAMEMAX; i++) {
 354                dev->rbfdt[i].addr = (unsigned long) net_rx_packets[i];
 355                dev->rbfdt[i].size = 0;
 356        }
 357        dev->rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP;
 358        dev->rbindex = 0;
 359        writel((u32) &(dev->rbfdt[0]), &emac->rbqp);
 360
 361        writel(readl(&emac->rsr) &
 362                ~(AT91_EMAC_RSR_OVR | AT91_EMAC_RSR_REC | AT91_EMAC_RSR_BNA),
 363                &emac->rsr);
 364
 365        value = AT91_EMAC_CFG_CAF |     AT91_EMAC_CFG_NBC |
 366                HCLK_DIV;
 367#ifdef CONFIG_RMII
 368        value |= AT91_EMAC_CFG_RMII;
 369#endif
 370        writel(value, &emac->cfg);
 371
 372        writel(readl(&emac->ctl) | AT91_EMAC_CTL_TE | AT91_EMAC_CTL_RE,
 373                &emac->ctl);
 374
 375        if (!at91emac_phy_init(netdev)) {
 376                at91emac_UpdateLinkSpeed(emac);
 377                return 0;
 378        }
 379        return -1;
 380}
 381
 382static void at91emac_halt(struct eth_device *netdev)
 383{
 384        at91_emac_t *emac;
 385
 386        emac = (at91_emac_t *) netdev->iobase;
 387        writel(readl(&emac->ctl) & ~(AT91_EMAC_CTL_TE | AT91_EMAC_CTL_RE),
 388                &emac->ctl);
 389        debug_cond(DEBUG_AT91EMAC, "halt MAC\n");
 390}
 391
 392static int at91emac_send(struct eth_device *netdev, void *packet, int length)
 393{
 394        at91_emac_t *emac;
 395
 396        emac = (at91_emac_t *) netdev->iobase;
 397
 398        while (!(readl(&emac->tsr) & AT91_EMAC_TSR_BNQ))
 399                ;
 400        writel((u32) packet, &emac->tar);
 401        writel(AT91_EMAC_TCR_LEN(length), &emac->tcr);
 402        while (AT91_EMAC_TCR_LEN(readl(&emac->tcr)))
 403                ;
 404        debug_cond(DEBUG_AT91EMAC, "Send %d\n", length);
 405        writel(readl(&emac->tsr) | AT91_EMAC_TSR_COMP, &emac->tsr);
 406        return 0;
 407}
 408
 409static int at91emac_recv(struct eth_device *netdev)
 410{
 411        emac_device *dev;
 412        at91_emac_t *emac;
 413        rbf_t *rbfp;
 414        int size;
 415
 416        emac = (at91_emac_t *) netdev->iobase;
 417        dev = (emac_device *) netdev->priv;
 418
 419        rbfp = &dev->rbfdt[dev->rbindex];
 420        while (rbfp->addr & RBF_OWNER)  {
 421                size = rbfp->size & RBF_SIZE;
 422                net_process_received_packet(net_rx_packets[dev->rbindex], size);
 423
 424                debug_cond(DEBUG_AT91EMAC, "Recv[%ld]: %d bytes @ %lx\n",
 425                        dev->rbindex, size, rbfp->addr);
 426
 427                rbfp->addr &= ~RBF_OWNER;
 428                rbfp->size = 0;
 429                if (dev->rbindex < (RBF_FRAMEMAX-1))
 430                        dev->rbindex++;
 431                else
 432                        dev->rbindex = 0;
 433
 434                rbfp = &(dev->rbfdt[dev->rbindex]);
 435                if (!(rbfp->addr & RBF_OWNER))
 436                        writel(readl(&emac->rsr) | AT91_EMAC_RSR_REC,
 437                                &emac->rsr);
 438        }
 439
 440        if (readl(&emac->isr) & AT91_EMAC_IxR_RBNA) {
 441                /* EMAC silicon bug 41.3.1 workaround 1 */
 442                writel(readl(&emac->ctl) & ~AT91_EMAC_CTL_RE, &emac->ctl);
 443                writel(readl(&emac->ctl) | AT91_EMAC_CTL_RE, &emac->ctl);
 444                dev->rbindex = 0;
 445                printf("%s: reset receiver (EMAC dead lock bug)\n",
 446                        netdev->name);
 447        }
 448        return 0;
 449}
 450
 451static int at91emac_write_hwaddr(struct eth_device *netdev)
 452{
 453        at91_emac_t *emac;
 454        emac = (at91_emac_t *) netdev->iobase;
 455
 456        at91_periph_clk_enable(ATMEL_ID_EMAC);
 457
 458        debug_cond(DEBUG_AT91EMAC,
 459                "init MAC-ADDR %02x:%02x:%02x:%02x:%02x:%02x\n",
 460                netdev->enetaddr[5], netdev->enetaddr[4], netdev->enetaddr[3],
 461                netdev->enetaddr[2], netdev->enetaddr[1], netdev->enetaddr[0]);
 462        writel( (netdev->enetaddr[0] | netdev->enetaddr[1] << 8 |
 463                        netdev->enetaddr[2] << 16 | netdev->enetaddr[3] << 24),
 464                        &emac->sa2l);
 465        writel((netdev->enetaddr[4] | netdev->enetaddr[5] << 8), &emac->sa2h);
 466        debug_cond(DEBUG_AT91EMAC, "init MAC-ADDR %x%x\n",
 467                readl(&emac->sa2h), readl(&emac->sa2l));
 468        return 0;
 469}
 470
 471int at91emac_register(bd_t *bis, unsigned long iobase)
 472{
 473        emac_device *emac;
 474        emac_device *emacfix;
 475        struct eth_device *dev;
 476
 477        if (iobase == 0)
 478                iobase = ATMEL_BASE_EMAC;
 479        emac = malloc(sizeof(*emac)+512);
 480        if (emac == NULL)
 481                return -1;
 482        dev = malloc(sizeof(*dev));
 483        if (dev == NULL) {
 484                free(emac);
 485                return -1;
 486        }
 487        /* alignment as per Errata (64 bytes) is insufficient! */
 488        emacfix = (emac_device *) (((unsigned long) emac + 0x1ff) & 0xFFFFFE00);
 489        memset(emacfix, 0, sizeof(emac_device));
 490
 491        memset(dev, 0, sizeof(*dev));
 492        strcpy(dev->name, "emac");
 493        dev->iobase = iobase;
 494        dev->priv = emacfix;
 495        dev->init = at91emac_init;
 496        dev->halt = at91emac_halt;
 497        dev->send = at91emac_send;
 498        dev->recv = at91emac_recv;
 499        dev->write_hwaddr = at91emac_write_hwaddr;
 500
 501        eth_register(dev);
 502
 503#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 504        int retval;
 505        struct mii_dev *mdiodev = mdio_alloc();
 506        if (!mdiodev)
 507                return -ENOMEM;
 508        strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
 509        mdiodev->read = at91emac_mii_read;
 510        mdiodev->write = at91emac_mii_write;
 511
 512        retval = mdio_register(mdiodev);
 513        if (retval < 0)
 514                return retval;
 515#endif
 516        return 1;
 517}
 518