uboot/drivers/net/sunxi_wemac.c
<<
>>
Prefs
   1/*
   2 * sunxi_wemac.c -- Allwinner A10 ethernet driver
   3 *
   4 * (C) Copyright 2012, Stefan Roese <sr@denx.de>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <malloc.h>
  11#include <net.h>
  12#include <miiphy.h>
  13#include <linux/err.h>
  14#include <asm/io.h>
  15#include <asm/arch/clock.h>
  16#include <asm/arch/gpio.h>
  17
  18/* EMAC register  */
  19struct wemac_regs {
  20        u32 ctl;        /* 0x00 */
  21        u32 tx_mode;    /* 0x04 */
  22        u32 tx_flow;    /* 0x08 */
  23        u32 tx_ctl0;    /* 0x0c */
  24        u32 tx_ctl1;    /* 0x10 */
  25        u32 tx_ins;     /* 0x14 */
  26        u32 tx_pl0;     /* 0x18 */
  27        u32 tx_pl1;     /* 0x1c */
  28        u32 tx_sta;     /* 0x20 */
  29        u32 tx_io_data; /* 0x24 */
  30        u32 tx_io_data1; /* 0x28 */
  31        u32 tx_tsvl0;   /* 0x2c */
  32        u32 tx_tsvh0;   /* 0x30 */
  33        u32 tx_tsvl1;   /* 0x34 */
  34        u32 tx_tsvh1;   /* 0x38 */
  35        u32 rx_ctl;     /* 0x3c */
  36        u32 rx_hash0;   /* 0x40 */
  37        u32 rx_hash1;   /* 0x44 */
  38        u32 rx_sta;     /* 0x48 */
  39        u32 rx_io_data; /* 0x4c */
  40        u32 rx_fbc;     /* 0x50 */
  41        u32 int_ctl;    /* 0x54 */
  42        u32 int_sta;    /* 0x58 */
  43        u32 mac_ctl0;   /* 0x5c */
  44        u32 mac_ctl1;   /* 0x60 */
  45        u32 mac_ipgt;   /* 0x64 */
  46        u32 mac_ipgr;   /* 0x68 */
  47        u32 mac_clrt;   /* 0x6c */
  48        u32 mac_maxf;   /* 0x70 */
  49        u32 mac_supp;   /* 0x74 */
  50        u32 mac_test;   /* 0x78 */
  51        u32 mac_mcfg;   /* 0x7c */
  52        u32 mac_mcmd;   /* 0x80 */
  53        u32 mac_madr;   /* 0x84 */
  54        u32 mac_mwtd;   /* 0x88 */
  55        u32 mac_mrdd;   /* 0x8c */
  56        u32 mac_mind;   /* 0x90 */
  57        u32 mac_ssrr;   /* 0x94 */
  58        u32 mac_a0;     /* 0x98 */
  59        u32 mac_a1;     /* 0x9c */
  60};
  61
  62/* SRAMC register  */
  63struct sunxi_sramc_regs {
  64        u32 ctrl0;
  65        u32 ctrl1;
  66};
  67
  68/* 0: Disable       1: Aborted frame enable(default) */
  69#define EMAC_TX_AB_M            (0x1 << 0)
  70/* 0: CPU           1: DMA(default) */
  71#define EMAC_TX_TM              (0x1 << 1)
  72
  73#define EMAC_TX_SETUP           (0)
  74
  75/* 0: DRQ asserted  1: DRQ automatically(default) */
  76#define EMAC_RX_DRQ_MODE        (0x1 << 1)
  77/* 0: CPU           1: DMA(default) */
  78#define EMAC_RX_TM              (0x1 << 2)
  79/* 0: Normal(default)        1: Pass all Frames */
  80#define EMAC_RX_PA              (0x1 << 4)
  81/* 0: Normal(default)        1: Pass Control Frames */
  82#define EMAC_RX_PCF             (0x1 << 5)
  83/* 0: Normal(default)        1: Pass Frames with CRC Error */
  84#define EMAC_RX_PCRCE           (0x1 << 6)
  85/* 0: Normal(default)        1: Pass Frames with Length Error */
  86#define EMAC_RX_PLE             (0x1 << 7)
  87/* 0: Normal                 1: Pass Frames length out of range(default) */
  88#define EMAC_RX_POR             (0x1 << 8)
  89/* 0: Not accept             1: Accept unicast Packets(default) */
  90#define EMAC_RX_UCAD            (0x1 << 16)
  91/* 0: Normal(default)        1: DA Filtering */
  92#define EMAC_RX_DAF             (0x1 << 17)
  93/* 0: Not accept             1: Accept multicast Packets(default) */
  94#define EMAC_RX_MCO             (0x1 << 20)
  95/* 0: Disable(default)       1: Enable Hash filter */
  96#define EMAC_RX_MHF             (0x1 << 21)
  97/* 0: Not accept             1: Accept Broadcast Packets(default) */
  98#define EMAC_RX_BCO             (0x1 << 22)
  99/* 0: Disable(default)       1: Enable SA Filtering */
 100#define EMAC_RX_SAF             (0x1 << 24)
 101/* 0: Normal(default)        1: Inverse Filtering */
 102#define EMAC_RX_SAIF            (0x1 << 25)
 103
 104#define EMAC_RX_SETUP           (EMAC_RX_POR | EMAC_RX_UCAD | EMAC_RX_DAF | \
 105                                 EMAC_RX_MCO | EMAC_RX_BCO)
 106
 107/* 0: Disable                1: Enable Receive Flow Control(default) */
 108#define EMAC_MAC_CTL0_RFC       (0x1 << 2)
 109/* 0: Disable                1: Enable Transmit Flow Control(default) */
 110#define EMAC_MAC_CTL0_TFC       (0x1 << 3)
 111
 112#define EMAC_MAC_CTL0_SETUP     (EMAC_MAC_CTL0_RFC | EMAC_MAC_CTL0_TFC)
 113
 114/* 0: Disable                1: Enable MAC Frame Length Checking(default) */
 115#define EMAC_MAC_CTL1_FLC       (0x1 << 1)
 116/* 0: Disable(default)       1: Enable Huge Frame */
 117#define EMAC_MAC_CTL1_HF        (0x1 << 2)
 118/* 0: Disable(default)       1: Enable MAC Delayed CRC */
 119#define EMAC_MAC_CTL1_DCRC      (0x1 << 3)
 120/* 0: Disable                1: Enable MAC CRC(default) */
 121#define EMAC_MAC_CTL1_CRC       (0x1 << 4)
 122/* 0: Disable                1: Enable MAC PAD Short frames(default) */
 123#define EMAC_MAC_CTL1_PC        (0x1 << 5)
 124/* 0: Disable(default)       1: Enable MAC PAD Short frames and append CRC */
 125#define EMAC_MAC_CTL1_VC        (0x1 << 6)
 126/* 0: Disable(default)       1: Enable MAC auto detect Short frames */
 127#define EMAC_MAC_CTL1_ADP       (0x1 << 7)
 128/* 0: Disable(default)       1: Enable */
 129#define EMAC_MAC_CTL1_PRE       (0x1 << 8)
 130/* 0: Disable(default)       1: Enable */
 131#define EMAC_MAC_CTL1_LPE       (0x1 << 9)
 132/* 0: Disable(default)       1: Enable no back off */
 133#define EMAC_MAC_CTL1_NB        (0x1 << 12)
 134/* 0: Disable(default)       1: Enable */
 135#define EMAC_MAC_CTL1_BNB       (0x1 << 13)
 136/* 0: Disable(default)       1: Enable */
 137#define EMAC_MAC_CTL1_ED        (0x1 << 14)
 138
 139#define EMAC_MAC_CTL1_SETUP     (EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC | \
 140                                 EMAC_MAC_CTL1_PC)
 141
 142#define EMAC_MAC_IPGT           0x15
 143
 144#define EMAC_MAC_NBTB_IPG1      0xC
 145#define EMAC_MAC_NBTB_IPG2      0x12
 146
 147#define EMAC_MAC_CW             0x37
 148#define EMAC_MAC_RM             0xF
 149
 150#define EMAC_MAC_MFL            0x0600
 151
 152/* Receive status */
 153#define EMAC_CRCERR             (1 << 4)
 154#define EMAC_LENERR             (3 << 5)
 155
 156#define DMA_CPU_TRRESHOLD       2000
 157
 158struct wemac_eth_dev {
 159        u32 speed;
 160        u32 duplex;
 161        u32 phy_configured;
 162        int link_printed;
 163};
 164
 165struct wemac_rxhdr {
 166        s16 rx_len;
 167        u16 rx_status;
 168};
 169
 170static void wemac_inblk_32bit(void *reg, void *data, int count)
 171{
 172        int cnt = (count + 3) >> 2;
 173
 174        if (cnt) {
 175                u32 *buf = data;
 176
 177                do {
 178                        u32 x = readl(reg);
 179                        *buf++ = x;
 180                } while (--cnt);
 181        }
 182}
 183
 184static void wemac_outblk_32bit(void *reg, void *data, int count)
 185{
 186        int cnt = (count + 3) >> 2;
 187
 188        if (cnt) {
 189                const u32 *buf = data;
 190
 191                do {
 192                        writel(*buf++, reg);
 193                } while (--cnt);
 194        }
 195}
 196
 197/*
 198 * Read a word from phyxcer
 199 */
 200static int wemac_phy_read(const char *devname, unsigned char addr,
 201                          unsigned char reg, unsigned short *value)
 202{
 203        struct eth_device *dev = eth_get_dev_by_name(devname);
 204        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 205
 206        /* issue the phy address and reg */
 207        writel(addr << 8 | reg, &regs->mac_madr);
 208
 209        /* pull up the phy io line */
 210        writel(0x1, &regs->mac_mcmd);
 211
 212        /* Wait read complete */
 213        mdelay(1);
 214
 215        /* push down the phy io line */
 216        writel(0x0, &regs->mac_mcmd);
 217
 218        /* and write data */
 219        *value = readl(&regs->mac_mrdd);
 220
 221        return 0;
 222}
 223
 224/*
 225 * Write a word to phyxcer
 226 */
 227static int wemac_phy_write(const char *devname, unsigned char addr,
 228                           unsigned char reg, unsigned short value)
 229{
 230        struct eth_device *dev = eth_get_dev_by_name(devname);
 231        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 232
 233        /* issue the phy address and reg */
 234        writel(addr << 8 | reg, &regs->mac_madr);
 235
 236        /* pull up the phy io line */
 237        writel(0x1, &regs->mac_mcmd);
 238
 239        /* Wait write complete */
 240        mdelay(1);
 241
 242        /* push down the phy io line */
 243        writel(0x0, &regs->mac_mcmd);
 244
 245        /* and write data */
 246        writel(value, &regs->mac_mwtd);
 247
 248        return 0;
 249}
 250
 251static void emac_setup(struct eth_device *dev)
 252{
 253        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 254        u32 reg_val;
 255        u16 phy_val;
 256        u32 duplex_flag;
 257
 258        /* Set up TX */
 259        writel(EMAC_TX_SETUP, &regs->tx_mode);
 260
 261        /* Set up RX */
 262        writel(EMAC_RX_SETUP, &regs->rx_ctl);
 263
 264        /* Set MAC */
 265        /* Set MAC CTL0 */
 266        writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
 267
 268        /* Set MAC CTL1 */
 269        wemac_phy_read(dev->name, 1, 0, &phy_val);
 270        debug("PHY SETUP, reg 0 value: %x\n", phy_val);
 271        duplex_flag = !!(phy_val & (1 << 8));
 272
 273        reg_val = 0;
 274        if (duplex_flag)
 275                reg_val = (0x1 << 0);
 276        writel(EMAC_MAC_CTL1_SETUP | reg_val, &regs->mac_ctl1);
 277
 278        /* Set up IPGT */
 279        writel(EMAC_MAC_IPGT, &regs->mac_ipgt);
 280
 281        /* Set up IPGR */
 282        writel(EMAC_MAC_NBTB_IPG2 | (EMAC_MAC_NBTB_IPG1 << 8), &regs->mac_ipgr);
 283
 284        /* Set up Collison window */
 285        writel(EMAC_MAC_RM | (EMAC_MAC_CW << 8), &regs->mac_clrt);
 286
 287        /* Set up Max Frame Length */
 288        writel(EMAC_MAC_MFL, &regs->mac_maxf);
 289}
 290
 291static void wemac_reset(struct eth_device *dev)
 292{
 293        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 294
 295        debug("resetting device\n");
 296
 297        /* RESET device */
 298        writel(0, &regs->ctl);
 299        udelay(200);
 300
 301        writel(1, &regs->ctl);
 302        udelay(200);
 303}
 304
 305static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
 306{
 307        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 308        struct wemac_eth_dev *priv = dev->priv;
 309        u16 phy_reg;
 310
 311        /* Init EMAC */
 312
 313        /* Flush RX FIFO */
 314        setbits_le32(&regs->rx_ctl, 0x8);
 315        udelay(1);
 316
 317        /* Init MAC */
 318
 319        /* Soft reset MAC */
 320        clrbits_le32(&regs->mac_ctl0, 1 << 15);
 321
 322        /* Set MII clock */
 323        clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
 324
 325        /* Clear RX counter */
 326        writel(0x0, &regs->rx_fbc);
 327        udelay(1);
 328
 329        /* Set up EMAC */
 330        emac_setup(dev);
 331
 332        writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 |
 333               dev->enetaddr[2], &regs->mac_a1);
 334        writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 |
 335               dev->enetaddr[5], &regs->mac_a0);
 336
 337        mdelay(1);
 338
 339        wemac_reset(dev);
 340
 341        /* PHY POWER UP */
 342        wemac_phy_read(dev->name, 1, 0, &phy_reg);
 343        wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11)));
 344        mdelay(1);
 345
 346        wemac_phy_read(dev->name, 1, 0, &phy_reg);
 347
 348        priv->speed = miiphy_speed(dev->name, 0);
 349        priv->duplex = miiphy_duplex(dev->name, 0);
 350
 351        /* Print link status only once */
 352        if (!priv->link_printed) {
 353                printf("ENET Speed is %d Mbps - %s duplex connection\n",
 354                       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
 355                priv->link_printed = 1;
 356        }
 357
 358        /* Set EMAC SPEED depend on PHY */
 359        clrsetbits_le32(&regs->mac_supp, 1 << 8,
 360                        ((phy_reg & (1 << 13)) >> 13) << 8);
 361
 362        /* Set duplex depend on phy */
 363        clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
 364                        ((phy_reg & (1 << 8)) >> 8) << 0);
 365
 366        /* Enable RX/TX */
 367        setbits_le32(&regs->ctl, 0x7);
 368
 369        return 0;
 370}
 371
 372static void sunxi_wemac_eth_halt(struct eth_device *dev)
 373{
 374        /* Nothing to do here */
 375}
 376
 377static int sunxi_wemac_eth_recv(struct eth_device *dev)
 378{
 379        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 380        struct wemac_rxhdr rxhdr;
 381        u32 rxcount;
 382        u32 reg_val;
 383        int rx_len;
 384        int rx_status;
 385        int good_packet;
 386
 387        /* Check packet ready or not */
 388
 389        /*
 390         * Race warning: The first packet might arrive with
 391         * the interrupts disabled, but the second will fix
 392         */
 393        rxcount = readl(&regs->rx_fbc);
 394        if (!rxcount) {
 395                /* Had one stuck? */
 396                rxcount = readl(&regs->rx_fbc);
 397                if (!rxcount)
 398                        return 0;
 399        }
 400
 401        reg_val = readl(&regs->rx_io_data);
 402        if (reg_val != 0x0143414d) {
 403                /* Disable RX */
 404                clrbits_le32(&regs->ctl, 1 << 2);
 405
 406                /* Flush RX FIFO */
 407                setbits_le32(&regs->rx_ctl, 1 << 3);
 408                while (readl(&regs->rx_ctl) & (1 << 3))
 409                        ;
 410
 411                /* Enable RX */
 412                setbits_le32(&regs->ctl, 1 << 2);
 413
 414                return 0;
 415        }
 416
 417        /*
 418         * A packet ready now
 419         * Get status/length
 420         */
 421        good_packet = 1;
 422
 423        wemac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
 424
 425        rx_len = rxhdr.rx_len;
 426        rx_status = rxhdr.rx_status;
 427
 428        /* Packet Status check */
 429        if (rx_len < 0x40) {
 430                good_packet = 0;
 431                debug("RX: Bad Packet (runt)\n");
 432        }
 433
 434        /* rx_status is identical to RSR register. */
 435        if (0 & rx_status & (EMAC_CRCERR | EMAC_LENERR)) {
 436                good_packet = 0;
 437                if (rx_status & EMAC_CRCERR)
 438                        printf("crc error\n");
 439                if (rx_status & EMAC_LENERR)
 440                        printf("length error\n");
 441        }
 442
 443        /* Move data from WEMAC */
 444        if (good_packet) {
 445                if (rx_len > DMA_CPU_TRRESHOLD) {
 446                        printf("Received packet is too big (len=%d)\n", rx_len);
 447                } else {
 448                        wemac_inblk_32bit((void *)&regs->rx_io_data,
 449                                          NetRxPackets[0], rx_len);
 450
 451                        /* Pass to upper layer */
 452                        NetReceive(NetRxPackets[0], rx_len);
 453                        return rx_len;
 454                }
 455        }
 456
 457        return 0;
 458}
 459
 460static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len)
 461{
 462        struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
 463
 464        /* Select channel 0 */
 465        writel(0, &regs->tx_ins);
 466
 467        /* Write packet */
 468        wemac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
 469
 470        /* Set TX len */
 471        writel(len, &regs->tx_pl0);
 472
 473        /* Start translate from fifo to phy */
 474        setbits_le32(&regs->tx_ctl0, 1);
 475
 476        return 0;
 477}
 478
 479int sunxi_wemac_initialize(void)
 480{
 481        struct sunxi_ccm_reg *const ccm =
 482                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 483        struct sunxi_sramc_regs *sram =
 484                (struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
 485        struct eth_device *dev;
 486        struct wemac_eth_dev *priv;
 487        int pin;
 488
 489        dev = malloc(sizeof(*dev));
 490        if (dev == NULL)
 491                return -ENOMEM;
 492
 493        priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev));
 494        if (!priv) {
 495                free(dev);
 496                return -ENOMEM;
 497        }
 498
 499        memset(dev, 0, sizeof(*dev));
 500        memset(priv, 0, sizeof(struct wemac_eth_dev));
 501
 502        /* Map SRAM to EMAC */
 503        setbits_le32(&sram->ctrl1, 0x5 << 2);
 504
 505        /* Configure pin mux settings for MII Ethernet */
 506        for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
 507                sunxi_gpio_set_cfgpin(pin, 2);
 508
 509        /* Set up clock gating */
 510        setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC);
 511
 512        dev->iobase = SUNXI_EMAC_BASE;
 513        dev->priv = priv;
 514        dev->init = sunxi_wemac_eth_init;
 515        dev->halt = sunxi_wemac_eth_halt;
 516        dev->send = sunxi_wemac_eth_send;
 517        dev->recv = sunxi_wemac_eth_recv;
 518        strcpy(dev->name, "wemac");
 519
 520        eth_register(dev);
 521
 522        miiphy_register(dev->name, wemac_phy_read, wemac_phy_write);
 523
 524        return 0;
 525}
 526