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