Commit 8d77c036b57cf813d838f859e11b6a188acdb1fb

Authored by Po-Yu Chuang
Committed by David S. Miller
1 parent 29546a6404

net: add Faraday FTMAC100 10/100 Ethernet driver

FTMAC100 Ethernet Media Access Controller supports 10/100 Mbps and
MII.  This driver has been working on some ARM/NDS32 SoC's including
Faraday A320 and Andes AG101.

Signed-off-by: Po-Yu Chuang <ratbert@faraday-tech.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 4 changed files with 1386 additions and 0 deletions Side-by-side Diff

... ... @@ -2008,6 +2008,15 @@
2008 2008 This driver supports the ethernet MACs in the Broadcom 63xx
2009 2009 MIPS chipset family (BCM63XX).
2010 2010  
  2011 +config FTMAC100
  2012 + tristate "Faraday FTMAC100 10/100 Ethernet support"
  2013 + depends on ARM
  2014 + select MII
  2015 + help
  2016 + This driver supports the FTMAC100 10/100 Ethernet controller
  2017 + from Faraday. It is used on Faraday A320, Andes AG101 and some
  2018 + other ARM/NDS32 SoC's.
  2019 +
2011 2020 source "drivers/net/fs_enet/Kconfig"
2012 2021  
2013 2022 source "drivers/net/octeon/Kconfig"
drivers/net/Makefile
... ... @@ -147,6 +147,7 @@
147 147 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
148 148 obj-$(CONFIG_AX88796) += ax88796.o
149 149 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
  150 +obj-$(CONFIG_FTMAC100) += ftmac100.o
150 151  
151 152 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
152 153 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
drivers/net/ftmac100.c
Changes suppressed. Click to show
  1 +/*
  2 + * Faraday FTMAC100 10/100 Ethernet
  3 + *
  4 + * (C) Copyright 2009-2011 Faraday Technology
  5 + * Po-Yu Chuang <ratbert@faraday-tech.com>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 + */
  21 +
  22 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  23 +
  24 +#include <linux/dma-mapping.h>
  25 +#include <linux/etherdevice.h>
  26 +#include <linux/ethtool.h>
  27 +#include <linux/init.h>
  28 +#include <linux/io.h>
  29 +#include <linux/mii.h>
  30 +#include <linux/module.h>
  31 +#include <linux/netdevice.h>
  32 +#include <linux/platform_device.h>
  33 +
  34 +#include "ftmac100.h"
  35 +
  36 +#define DRV_NAME "ftmac100"
  37 +#define DRV_VERSION "0.2"
  38 +
  39 +#define RX_QUEUE_ENTRIES 128 /* must be power of 2 */
  40 +#define TX_QUEUE_ENTRIES 16 /* must be power of 2 */
  41 +
  42 +#define MAX_PKT_SIZE 1518
  43 +#define RX_BUF_SIZE 2044 /* must be smaller than 0x7ff */
  44 +
  45 +#if MAX_PKT_SIZE > 0x7ff
  46 +#error invalid MAX_PKT_SIZE
  47 +#endif
  48 +
  49 +#if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
  50 +#error invalid RX_BUF_SIZE
  51 +#endif
  52 +
  53 +/******************************************************************************
  54 + * private data
  55 + *****************************************************************************/
  56 +struct ftmac100_descs {
  57 + struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
  58 + struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
  59 +};
  60 +
  61 +struct ftmac100 {
  62 + struct resource *res;
  63 + void __iomem *base;
  64 + int irq;
  65 +
  66 + struct ftmac100_descs *descs;
  67 + dma_addr_t descs_dma_addr;
  68 +
  69 + unsigned int rx_pointer;
  70 + unsigned int tx_clean_pointer;
  71 + unsigned int tx_pointer;
  72 + unsigned int tx_pending;
  73 +
  74 + spinlock_t tx_lock;
  75 +
  76 + struct net_device *netdev;
  77 + struct device *dev;
  78 + struct napi_struct napi;
  79 +
  80 + struct mii_if_info mii;
  81 +};
  82 +
  83 +static int ftmac100_alloc_rx_page(struct ftmac100 *priv, struct ftmac100_rxdes *rxdes);
  84 +
  85 +/******************************************************************************
  86 + * internal functions (hardware register access)
  87 + *****************************************************************************/
  88 +#define INT_MASK_ALL_ENABLED (FTMAC100_INT_RPKT_FINISH | \
  89 + FTMAC100_INT_NORXBUF | \
  90 + FTMAC100_INT_XPKT_OK | \
  91 + FTMAC100_INT_XPKT_LOST | \
  92 + FTMAC100_INT_RPKT_LOST | \
  93 + FTMAC100_INT_AHB_ERR | \
  94 + FTMAC100_INT_PHYSTS_CHG)
  95 +
  96 +#define INT_MASK_ALL_DISABLED 0
  97 +
  98 +static void ftmac100_enable_all_int(struct ftmac100 *priv)
  99 +{
  100 + iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
  101 +}
  102 +
  103 +static void ftmac100_disable_all_int(struct ftmac100 *priv)
  104 +{
  105 + iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
  106 +}
  107 +
  108 +static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
  109 +{
  110 + iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
  111 +}
  112 +
  113 +static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
  114 +{
  115 + iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
  116 +}
  117 +
  118 +static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
  119 +{
  120 + iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
  121 +}
  122 +
  123 +static int ftmac100_reset(struct ftmac100 *priv)
  124 +{
  125 + struct net_device *netdev = priv->netdev;
  126 + int i;
  127 +
  128 + /* NOTE: reset clears all registers */
  129 + iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
  130 +
  131 + for (i = 0; i < 5; i++) {
  132 + unsigned int maccr;
  133 +
  134 + maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
  135 + if (!(maccr & FTMAC100_MACCR_SW_RST)) {
  136 + /*
  137 + * FTMAC100_MACCR_SW_RST cleared does not indicate
  138 + * that hardware reset completed (what the f*ck).
  139 + * We still need to wait for a while.
  140 + */
  141 + usleep_range(500, 1000);
  142 + return 0;
  143 + }
  144 +
  145 + usleep_range(1000, 10000);
  146 + }
  147 +
  148 + netdev_err(netdev, "software reset failed\n");
  149 + return -EIO;
  150 +}
  151 +
  152 +static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
  153 +{
  154 + unsigned int maddr = mac[0] << 8 | mac[1];
  155 + unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
  156 +
  157 + iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
  158 + iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
  159 +}
  160 +
  161 +#define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \
  162 + FTMAC100_MACCR_RCV_EN | \
  163 + FTMAC100_MACCR_XDMA_EN | \
  164 + FTMAC100_MACCR_RDMA_EN | \
  165 + FTMAC100_MACCR_CRC_APD | \
  166 + FTMAC100_MACCR_FULLDUP | \
  167 + FTMAC100_MACCR_RX_RUNT | \
  168 + FTMAC100_MACCR_RX_BROADPKT)
  169 +
  170 +static int ftmac100_start_hw(struct ftmac100 *priv)
  171 +{
  172 + struct net_device *netdev = priv->netdev;
  173 +
  174 + if (ftmac100_reset(priv))
  175 + return -EIO;
  176 +
  177 + /* setup ring buffer base registers */
  178 + ftmac100_set_rx_ring_base(priv,
  179 + priv->descs_dma_addr +
  180 + offsetof(struct ftmac100_descs, rxdes));
  181 + ftmac100_set_tx_ring_base(priv,
  182 + priv->descs_dma_addr +
  183 + offsetof(struct ftmac100_descs, txdes));
  184 +
  185 + iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
  186 +
  187 + ftmac100_set_mac(priv, netdev->dev_addr);
  188 +
  189 + iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
  190 + return 0;
  191 +}
  192 +
  193 +static void ftmac100_stop_hw(struct ftmac100 *priv)
  194 +{
  195 + iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
  196 +}
  197 +
  198 +/******************************************************************************
  199 + * internal functions (receive descriptor)
  200 + *****************************************************************************/
  201 +static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
  202 +{
  203 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
  204 +}
  205 +
  206 +static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
  207 +{
  208 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
  209 +}
  210 +
  211 +static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
  212 +{
  213 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
  214 +}
  215 +
  216 +static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
  217 +{
  218 + /* clear status bits */
  219 + rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
  220 +}
  221 +
  222 +static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
  223 +{
  224 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
  225 +}
  226 +
  227 +static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
  228 +{
  229 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
  230 +}
  231 +
  232 +static bool ftmac100_rxdes_frame_too_long(struct ftmac100_rxdes *rxdes)
  233 +{
  234 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FTL);
  235 +}
  236 +
  237 +static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
  238 +{
  239 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
  240 +}
  241 +
  242 +static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
  243 +{
  244 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
  245 +}
  246 +
  247 +static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
  248 +{
  249 + return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
  250 +}
  251 +
  252 +static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
  253 +{
  254 + return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
  255 +}
  256 +
  257 +static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
  258 + unsigned int size)
  259 +{
  260 + rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
  261 + rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
  262 +}
  263 +
  264 +static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
  265 +{
  266 + rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
  267 +}
  268 +
  269 +static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
  270 + dma_addr_t addr)
  271 +{
  272 + rxdes->rxdes2 = cpu_to_le32(addr);
  273 +}
  274 +
  275 +static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
  276 +{
  277 + return le32_to_cpu(rxdes->rxdes2);
  278 +}
  279 +
  280 +/*
  281 + * rxdes3 is not used by hardware. We use it to keep track of page.
  282 + * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
  283 + */
  284 +static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
  285 +{
  286 + rxdes->rxdes3 = (unsigned int)page;
  287 +}
  288 +
  289 +static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
  290 +{
  291 + return (struct page *)rxdes->rxdes3;
  292 +}
  293 +
  294 +/******************************************************************************
  295 + * internal functions (receive)
  296 + *****************************************************************************/
  297 +static int ftmac100_next_rx_pointer(int pointer)
  298 +{
  299 + return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
  300 +}
  301 +
  302 +static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
  303 +{
  304 + priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
  305 +}
  306 +
  307 +static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
  308 +{
  309 + return &priv->descs->rxdes[priv->rx_pointer];
  310 +}
  311 +
  312 +static struct ftmac100_rxdes *
  313 +ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
  314 +{
  315 + struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
  316 +
  317 + while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
  318 + if (ftmac100_rxdes_first_segment(rxdes))
  319 + return rxdes;
  320 +
  321 + ftmac100_rxdes_set_dma_own(rxdes);
  322 + ftmac100_rx_pointer_advance(priv);
  323 + rxdes = ftmac100_current_rxdes(priv);
  324 + }
  325 +
  326 + return NULL;
  327 +}
  328 +
  329 +static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
  330 + struct ftmac100_rxdes *rxdes)
  331 +{
  332 + struct net_device *netdev = priv->netdev;
  333 + bool error = false;
  334 +
  335 + if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
  336 + if (net_ratelimit())
  337 + netdev_info(netdev, "rx err\n");
  338 +
  339 + netdev->stats.rx_errors++;
  340 + error = true;
  341 + }
  342 +
  343 + if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
  344 + if (net_ratelimit())
  345 + netdev_info(netdev, "rx crc err\n");
  346 +
  347 + netdev->stats.rx_crc_errors++;
  348 + error = true;
  349 + }
  350 +
  351 + if (unlikely(ftmac100_rxdes_frame_too_long(rxdes))) {
  352 + if (net_ratelimit())
  353 + netdev_info(netdev, "rx frame too long\n");
  354 +
  355 + netdev->stats.rx_length_errors++;
  356 + error = true;
  357 + } else if (unlikely(ftmac100_rxdes_runt(rxdes))) {
  358 + if (net_ratelimit())
  359 + netdev_info(netdev, "rx runt\n");
  360 +
  361 + netdev->stats.rx_length_errors++;
  362 + error = true;
  363 + } else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
  364 + if (net_ratelimit())
  365 + netdev_info(netdev, "rx odd nibble\n");
  366 +
  367 + netdev->stats.rx_length_errors++;
  368 + error = true;
  369 + }
  370 +
  371 + return error;
  372 +}
  373 +
  374 +static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
  375 +{
  376 + struct net_device *netdev = priv->netdev;
  377 + struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
  378 + bool done = false;
  379 +
  380 + if (net_ratelimit())
  381 + netdev_dbg(netdev, "drop packet %p\n", rxdes);
  382 +
  383 + do {
  384 + if (ftmac100_rxdes_last_segment(rxdes))
  385 + done = true;
  386 +
  387 + ftmac100_rxdes_set_dma_own(rxdes);
  388 + ftmac100_rx_pointer_advance(priv);
  389 + rxdes = ftmac100_current_rxdes(priv);
  390 + } while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
  391 +
  392 + netdev->stats.rx_dropped++;
  393 +}
  394 +
  395 +static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
  396 +{
  397 + struct net_device *netdev = priv->netdev;
  398 + struct ftmac100_rxdes *rxdes;
  399 + struct sk_buff *skb;
  400 + struct page *page;
  401 + dma_addr_t map;
  402 + int length;
  403 +
  404 + rxdes = ftmac100_rx_locate_first_segment(priv);
  405 + if (!rxdes)
  406 + return false;
  407 +
  408 + if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
  409 + ftmac100_rx_drop_packet(priv);
  410 + return true;
  411 + }
  412 +
  413 + /*
  414 + * It is impossible to get multi-segment packets
  415 + * because we always provide big enough receive buffers.
  416 + */
  417 + if (unlikely(!ftmac100_rxdes_last_segment(rxdes)))
  418 + BUG();
  419 +
  420 + /* start processing */
  421 + skb = netdev_alloc_skb_ip_align(netdev, 128);
  422 + if (unlikely(!skb)) {
  423 + if (net_ratelimit())
  424 + netdev_err(netdev, "rx skb alloc failed\n");
  425 +
  426 + ftmac100_rx_drop_packet(priv);
  427 + return true;
  428 + }
  429 +
  430 + if (unlikely(ftmac100_rxdes_multicast(rxdes)))
  431 + netdev->stats.multicast++;
  432 +
  433 + map = ftmac100_rxdes_get_dma_addr(rxdes);
  434 + dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
  435 +
  436 + length = ftmac100_rxdes_frame_length(rxdes);
  437 + page = ftmac100_rxdes_get_page(rxdes);
  438 + skb_fill_page_desc(skb, 0, page, 0, length);
  439 + skb->len += length;
  440 + skb->data_len += length;
  441 + skb->truesize += length;
  442 + __pskb_pull_tail(skb, min(length, 64));
  443 +
  444 + ftmac100_alloc_rx_page(priv, rxdes);
  445 +
  446 + ftmac100_rx_pointer_advance(priv);
  447 +
  448 + skb->protocol = eth_type_trans(skb, netdev);
  449 +
  450 + netdev->stats.rx_packets++;
  451 + netdev->stats.rx_bytes += skb->len;
  452 +
  453 + /* push packet to protocol stack */
  454 + netif_receive_skb(skb);
  455 +
  456 + (*processed)++;
  457 + return true;
  458 +}
  459 +
  460 +/******************************************************************************
  461 + * internal functions (transmit descriptor)
  462 + *****************************************************************************/
  463 +static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
  464 +{
  465 + /* clear all except end of ring bit */
  466 + txdes->txdes0 = 0;
  467 + txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
  468 + txdes->txdes2 = 0;
  469 + txdes->txdes3 = 0;
  470 +}
  471 +
  472 +static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
  473 +{
  474 + return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
  475 +}
  476 +
  477 +static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
  478 +{
  479 + /*
  480 + * Make sure dma own bit will not be set before any other
  481 + * descriptor fields.
  482 + */
  483 + wmb();
  484 + txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
  485 +}
  486 +
  487 +static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
  488 +{
  489 + return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
  490 +}
  491 +
  492 +static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
  493 +{
  494 + return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
  495 +}
  496 +
  497 +static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
  498 +{
  499 + txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
  500 +}
  501 +
  502 +static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
  503 +{
  504 + txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
  505 +}
  506 +
  507 +static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
  508 +{
  509 + txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
  510 +}
  511 +
  512 +static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
  513 +{
  514 + txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
  515 +}
  516 +
  517 +static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
  518 + unsigned int len)
  519 +{
  520 + txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
  521 +}
  522 +
  523 +static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
  524 + dma_addr_t addr)
  525 +{
  526 + txdes->txdes2 = cpu_to_le32(addr);
  527 +}
  528 +
  529 +static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
  530 +{
  531 + return le32_to_cpu(txdes->txdes2);
  532 +}
  533 +
  534 +/*
  535 + * txdes3 is not used by hardware. We use it to keep track of socket buffer.
  536 + * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
  537 + */
  538 +static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
  539 +{
  540 + txdes->txdes3 = (unsigned int)skb;
  541 +}
  542 +
  543 +static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
  544 +{
  545 + return (struct sk_buff *)txdes->txdes3;
  546 +}
  547 +
  548 +/******************************************************************************
  549 + * internal functions (transmit)
  550 + *****************************************************************************/
  551 +static int ftmac100_next_tx_pointer(int pointer)
  552 +{
  553 + return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
  554 +}
  555 +
  556 +static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
  557 +{
  558 + priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
  559 +}
  560 +
  561 +static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
  562 +{
  563 + priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
  564 +}
  565 +
  566 +static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
  567 +{
  568 + return &priv->descs->txdes[priv->tx_pointer];
  569 +}
  570 +
  571 +static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
  572 +{
  573 + return &priv->descs->txdes[priv->tx_clean_pointer];
  574 +}
  575 +
  576 +static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
  577 +{
  578 + struct net_device *netdev = priv->netdev;
  579 + struct ftmac100_txdes *txdes;
  580 + struct sk_buff *skb;
  581 + dma_addr_t map;
  582 +
  583 + if (priv->tx_pending == 0)
  584 + return false;
  585 +
  586 + txdes = ftmac100_current_clean_txdes(priv);
  587 +
  588 + if (ftmac100_txdes_owned_by_dma(txdes))
  589 + return false;
  590 +
  591 + skb = ftmac100_txdes_get_skb(txdes);
  592 + map = ftmac100_txdes_get_dma_addr(txdes);
  593 +
  594 + if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
  595 + ftmac100_txdes_late_collision(txdes))) {
  596 + /*
  597 + * packet transmitted to ethernet lost due to late collision
  598 + * or excessive collision
  599 + */
  600 + netdev->stats.tx_aborted_errors++;
  601 + } else {
  602 + netdev->stats.tx_packets++;
  603 + netdev->stats.tx_bytes += skb->len;
  604 + }
  605 +
  606 + dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
  607 + dev_kfree_skb(skb);
  608 +
  609 + ftmac100_txdes_reset(txdes);
  610 +
  611 + ftmac100_tx_clean_pointer_advance(priv);
  612 +
  613 + spin_lock(&priv->tx_lock);
  614 + priv->tx_pending--;
  615 + spin_unlock(&priv->tx_lock);
  616 + netif_wake_queue(netdev);
  617 +
  618 + return true;
  619 +}
  620 +
  621 +static void ftmac100_tx_complete(struct ftmac100 *priv)
  622 +{
  623 + while (ftmac100_tx_complete_packet(priv))
  624 + ;
  625 +}
  626 +
  627 +static int ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
  628 + dma_addr_t map)
  629 +{
  630 + struct net_device *netdev = priv->netdev;
  631 + struct ftmac100_txdes *txdes;
  632 + unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
  633 +
  634 + txdes = ftmac100_current_txdes(priv);
  635 + ftmac100_tx_pointer_advance(priv);
  636 +
  637 + /* setup TX descriptor */
  638 + ftmac100_txdes_set_skb(txdes, skb);
  639 + ftmac100_txdes_set_dma_addr(txdes, map);
  640 +
  641 + ftmac100_txdes_set_first_segment(txdes);
  642 + ftmac100_txdes_set_last_segment(txdes);
  643 + ftmac100_txdes_set_txint(txdes);
  644 + ftmac100_txdes_set_buffer_size(txdes, len);
  645 +
  646 + spin_lock(&priv->tx_lock);
  647 + priv->tx_pending++;
  648 + if (priv->tx_pending == TX_QUEUE_ENTRIES)
  649 + netif_stop_queue(netdev);
  650 +
  651 + /* start transmit */
  652 + ftmac100_txdes_set_dma_own(txdes);
  653 + spin_unlock(&priv->tx_lock);
  654 +
  655 + ftmac100_txdma_start_polling(priv);
  656 + return NETDEV_TX_OK;
  657 +}
  658 +
  659 +/******************************************************************************
  660 + * internal functions (buffer)
  661 + *****************************************************************************/
  662 +static int ftmac100_alloc_rx_page(struct ftmac100 *priv, struct ftmac100_rxdes *rxdes)
  663 +{
  664 + struct net_device *netdev = priv->netdev;
  665 + struct page *page;
  666 + dma_addr_t map;
  667 +
  668 + page = alloc_page(GFP_KERNEL);
  669 + if (!page) {
  670 + if (net_ratelimit())
  671 + netdev_err(netdev, "failed to allocate rx page\n");
  672 + return -ENOMEM;
  673 + }
  674 +
  675 + map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
  676 + if (unlikely(dma_mapping_error(priv->dev, map))) {
  677 + if (net_ratelimit())
  678 + netdev_err(netdev, "failed to map rx page\n");
  679 + __free_page(page);
  680 + return -ENOMEM;
  681 + }
  682 +
  683 + ftmac100_rxdes_set_page(rxdes, page);
  684 + ftmac100_rxdes_set_dma_addr(rxdes, map);
  685 + ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
  686 + ftmac100_rxdes_set_dma_own(rxdes);
  687 + return 0;
  688 +}
  689 +
  690 +static void ftmac100_free_buffers(struct ftmac100 *priv)
  691 +{
  692 + int i;
  693 +
  694 + for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
  695 + struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
  696 + struct page *page = ftmac100_rxdes_get_page(rxdes);
  697 + dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
  698 +
  699 + if (!page)
  700 + continue;
  701 +
  702 + dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
  703 + __free_page(page);
  704 + }
  705 +
  706 + for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
  707 + struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
  708 + struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
  709 + dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
  710 +
  711 + if (!skb)
  712 + continue;
  713 +
  714 + dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
  715 + dev_kfree_skb(skb);
  716 + }
  717 +
  718 + dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
  719 + priv->descs, priv->descs_dma_addr);
  720 +}
  721 +
  722 +static int ftmac100_alloc_buffers(struct ftmac100 *priv)
  723 +{
  724 + int i;
  725 +
  726 + priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
  727 + &priv->descs_dma_addr, GFP_KERNEL);
  728 + if (!priv->descs)
  729 + return -ENOMEM;
  730 +
  731 + memset(priv->descs, 0, sizeof(struct ftmac100_descs));
  732 +
  733 + /* initialize RX ring */
  734 + ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
  735 +
  736 + for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
  737 + struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
  738 +
  739 + if (ftmac100_alloc_rx_page(priv, rxdes))
  740 + goto err;
  741 + }
  742 +
  743 + /* initialize TX ring */
  744 + ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
  745 + return 0;
  746 +
  747 +err:
  748 + ftmac100_free_buffers(priv);
  749 + return -ENOMEM;
  750 +}
  751 +
  752 +/******************************************************************************
  753 + * struct mii_if_info functions
  754 + *****************************************************************************/
  755 +static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
  756 +{
  757 + struct ftmac100 *priv = netdev_priv(netdev);
  758 + unsigned int phycr;
  759 + int i;
  760 +
  761 + phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
  762 + FTMAC100_PHYCR_REGAD(reg) |
  763 + FTMAC100_PHYCR_MIIRD;
  764 +
  765 + iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
  766 +
  767 + for (i = 0; i < 10; i++) {
  768 + phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
  769 +
  770 + if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
  771 + return phycr & FTMAC100_PHYCR_MIIRDATA;
  772 +
  773 + usleep_range(100, 1000);
  774 + }
  775 +
  776 + netdev_err(netdev, "mdio read timed out\n");
  777 + return 0;
  778 +}
  779 +
  780 +static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
  781 + int data)
  782 +{
  783 + struct ftmac100 *priv = netdev_priv(netdev);
  784 + unsigned int phycr;
  785 + int i;
  786 +
  787 + phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
  788 + FTMAC100_PHYCR_REGAD(reg) |
  789 + FTMAC100_PHYCR_MIIWR;
  790 +
  791 + data = FTMAC100_PHYWDATA_MIIWDATA(data);
  792 +
  793 + iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
  794 + iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
  795 +
  796 + for (i = 0; i < 10; i++) {
  797 + phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
  798 +
  799 + if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
  800 + return;
  801 +
  802 + usleep_range(100, 1000);
  803 + }
  804 +
  805 + netdev_err(netdev, "mdio write timed out\n");
  806 +}
  807 +
  808 +/******************************************************************************
  809 + * struct ethtool_ops functions
  810 + *****************************************************************************/
  811 +static void ftmac100_get_drvinfo(struct net_device *netdev,
  812 + struct ethtool_drvinfo *info)
  813 +{
  814 + strcpy(info->driver, DRV_NAME);
  815 + strcpy(info->version, DRV_VERSION);
  816 + strcpy(info->bus_info, dev_name(&netdev->dev));
  817 +}
  818 +
  819 +static int ftmac100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
  820 +{
  821 + struct ftmac100 *priv = netdev_priv(netdev);
  822 + return mii_ethtool_gset(&priv->mii, cmd);
  823 +}
  824 +
  825 +static int ftmac100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
  826 +{
  827 + struct ftmac100 *priv = netdev_priv(netdev);
  828 + return mii_ethtool_sset(&priv->mii, cmd);
  829 +}
  830 +
  831 +static int ftmac100_nway_reset(struct net_device *netdev)
  832 +{
  833 + struct ftmac100 *priv = netdev_priv(netdev);
  834 + return mii_nway_restart(&priv->mii);
  835 +}
  836 +
  837 +static u32 ftmac100_get_link(struct net_device *netdev)
  838 +{
  839 + struct ftmac100 *priv = netdev_priv(netdev);
  840 + return mii_link_ok(&priv->mii);
  841 +}
  842 +
  843 +static const struct ethtool_ops ftmac100_ethtool_ops = {
  844 + .set_settings = ftmac100_set_settings,
  845 + .get_settings = ftmac100_get_settings,
  846 + .get_drvinfo = ftmac100_get_drvinfo,
  847 + .nway_reset = ftmac100_nway_reset,
  848 + .get_link = ftmac100_get_link,
  849 +};
  850 +
  851 +/******************************************************************************
  852 + * interrupt handler
  853 + *****************************************************************************/
  854 +static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
  855 +{
  856 + struct net_device *netdev = dev_id;
  857 + struct ftmac100 *priv = netdev_priv(netdev);
  858 +
  859 + if (likely(netif_running(netdev))) {
  860 + /* Disable interrupts for polling */
  861 + ftmac100_disable_all_int(priv);
  862 + napi_schedule(&priv->napi);
  863 + }
  864 +
  865 + return IRQ_HANDLED;
  866 +}
  867 +
  868 +/******************************************************************************
  869 + * struct napi_struct functions
  870 + *****************************************************************************/
  871 +static int ftmac100_poll(struct napi_struct *napi, int budget)
  872 +{
  873 + struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
  874 + struct net_device *netdev = priv->netdev;
  875 + unsigned int status;
  876 + bool completed = true;
  877 + int rx = 0;
  878 +
  879 + status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
  880 +
  881 + if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
  882 + /*
  883 + * FTMAC100_INT_RPKT_FINISH:
  884 + * RX DMA has received packets into RX buffer successfully
  885 + *
  886 + * FTMAC100_INT_NORXBUF:
  887 + * RX buffer unavailable
  888 + */
  889 + bool retry;
  890 +
  891 + do {
  892 + retry = ftmac100_rx_packet(priv, &rx);
  893 + } while (retry && rx < budget);
  894 +
  895 + if (retry && rx == budget)
  896 + completed = false;
  897 + }
  898 +
  899 + if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
  900 + /*
  901 + * FTMAC100_INT_XPKT_OK:
  902 + * packet transmitted to ethernet successfully
  903 + *
  904 + * FTMAC100_INT_XPKT_LOST:
  905 + * packet transmitted to ethernet lost due to late
  906 + * collision or excessive collision
  907 + */
  908 + ftmac100_tx_complete(priv);
  909 + }
  910 +
  911 + if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
  912 + FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
  913 + if (net_ratelimit())
  914 + netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
  915 + status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
  916 + status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
  917 + status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
  918 + status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
  919 +
  920 + if (status & FTMAC100_INT_NORXBUF) {
  921 + /* RX buffer unavailable */
  922 + netdev->stats.rx_over_errors++;
  923 + }
  924 +
  925 + if (status & FTMAC100_INT_RPKT_LOST) {
  926 + /* received packet lost due to RX FIFO full */
  927 + netdev->stats.rx_fifo_errors++;
  928 + }
  929 +
  930 + if (status & FTMAC100_INT_PHYSTS_CHG) {
  931 + /* PHY link status change */
  932 + mii_check_link(&priv->mii);
  933 + }
  934 + }
  935 +
  936 + if (completed) {
  937 + /* stop polling */
  938 + napi_complete(napi);
  939 + ftmac100_enable_all_int(priv);
  940 + }
  941 +
  942 + return rx;
  943 +}
  944 +
  945 +/******************************************************************************
  946 + * struct net_device_ops functions
  947 + *****************************************************************************/
  948 +static int ftmac100_open(struct net_device *netdev)
  949 +{
  950 + struct ftmac100 *priv = netdev_priv(netdev);
  951 + int err;
  952 +
  953 + err = ftmac100_alloc_buffers(priv);
  954 + if (err) {
  955 + netdev_err(netdev, "failed to allocate buffers\n");
  956 + goto err_alloc;
  957 + }
  958 +
  959 + err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
  960 + if (err) {
  961 + netdev_err(netdev, "failed to request irq %d\n", priv->irq);
  962 + goto err_irq;
  963 + }
  964 +
  965 + priv->rx_pointer = 0;
  966 + priv->tx_clean_pointer = 0;
  967 + priv->tx_pointer = 0;
  968 + priv->tx_pending = 0;
  969 +
  970 + err = ftmac100_start_hw(priv);
  971 + if (err)
  972 + goto err_hw;
  973 +
  974 + napi_enable(&priv->napi);
  975 + netif_start_queue(netdev);
  976 +
  977 + ftmac100_enable_all_int(priv);
  978 +
  979 + return 0;
  980 +
  981 +err_hw:
  982 + free_irq(priv->irq, netdev);
  983 +err_irq:
  984 + ftmac100_free_buffers(priv);
  985 +err_alloc:
  986 + return err;
  987 +}
  988 +
  989 +static int ftmac100_stop(struct net_device *netdev)
  990 +{
  991 + struct ftmac100 *priv = netdev_priv(netdev);
  992 +
  993 + ftmac100_disable_all_int(priv);
  994 + netif_stop_queue(netdev);
  995 + napi_disable(&priv->napi);
  996 + ftmac100_stop_hw(priv);
  997 + free_irq(priv->irq, netdev);
  998 + ftmac100_free_buffers(priv);
  999 +
  1000 + return 0;
  1001 +}
  1002 +
  1003 +static int ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
  1004 +{
  1005 + struct ftmac100 *priv = netdev_priv(netdev);
  1006 + dma_addr_t map;
  1007 +
  1008 + if (unlikely(skb->len > MAX_PKT_SIZE)) {
  1009 + if (net_ratelimit())
  1010 + netdev_dbg(netdev, "tx packet too big\n");
  1011 +
  1012 + netdev->stats.tx_dropped++;
  1013 + dev_kfree_skb(skb);
  1014 + return NETDEV_TX_OK;
  1015 + }
  1016 +
  1017 + map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
  1018 + if (unlikely(dma_mapping_error(priv->dev, map))) {
  1019 + /* drop packet */
  1020 + if (net_ratelimit())
  1021 + netdev_err(netdev, "map socket buffer failed\n");
  1022 +
  1023 + netdev->stats.tx_dropped++;
  1024 + dev_kfree_skb(skb);
  1025 + return NETDEV_TX_OK;
  1026 + }
  1027 +
  1028 + return ftmac100_xmit(priv, skb, map);
  1029 +}
  1030 +
  1031 +/* optional */
  1032 +static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
  1033 +{
  1034 + struct ftmac100 *priv = netdev_priv(netdev);
  1035 + struct mii_ioctl_data *data = if_mii(ifr);
  1036 +
  1037 + return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
  1038 +}
  1039 +
  1040 +static const struct net_device_ops ftmac100_netdev_ops = {
  1041 + .ndo_open = ftmac100_open,
  1042 + .ndo_stop = ftmac100_stop,
  1043 + .ndo_start_xmit = ftmac100_hard_start_xmit,
  1044 + .ndo_set_mac_address = eth_mac_addr,
  1045 + .ndo_validate_addr = eth_validate_addr,
  1046 + .ndo_do_ioctl = ftmac100_do_ioctl,
  1047 +};
  1048 +
  1049 +/******************************************************************************
  1050 + * struct platform_driver functions
  1051 + *****************************************************************************/
  1052 +static int ftmac100_probe(struct platform_device *pdev)
  1053 +{
  1054 + struct resource *res;
  1055 + int irq;
  1056 + struct net_device *netdev;
  1057 + struct ftmac100 *priv;
  1058 + int err;
  1059 +
  1060 + if (!pdev)
  1061 + return -ENODEV;
  1062 +
  1063 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  1064 + if (!res)
  1065 + return -ENXIO;
  1066 +
  1067 + irq = platform_get_irq(pdev, 0);
  1068 + if (irq < 0)
  1069 + return irq;
  1070 +
  1071 + /* setup net_device */
  1072 + netdev = alloc_etherdev(sizeof(*priv));
  1073 + if (!netdev) {
  1074 + err = -ENOMEM;
  1075 + goto err_alloc_etherdev;
  1076 + }
  1077 +
  1078 + SET_NETDEV_DEV(netdev, &pdev->dev);
  1079 + SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
  1080 + netdev->netdev_ops = &ftmac100_netdev_ops;
  1081 +
  1082 + platform_set_drvdata(pdev, netdev);
  1083 +
  1084 + /* setup private data */
  1085 + priv = netdev_priv(netdev);
  1086 + priv->netdev = netdev;
  1087 + priv->dev = &pdev->dev;
  1088 +
  1089 + spin_lock_init(&priv->tx_lock);
  1090 +
  1091 + /* initialize NAPI */
  1092 + netif_napi_add(netdev, &priv->napi, ftmac100_poll, 64);
  1093 +
  1094 + /* map io memory */
  1095 + priv->res = request_mem_region(res->start, resource_size(res),
  1096 + dev_name(&pdev->dev));
  1097 + if (!priv->res) {
  1098 + dev_err(&pdev->dev, "Could not reserve memory region\n");
  1099 + err = -ENOMEM;
  1100 + goto err_req_mem;
  1101 + }
  1102 +
  1103 + priv->base = ioremap(res->start, res->end - res->start);
  1104 + if (!priv->base) {
  1105 + dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
  1106 + err = -EIO;
  1107 + goto err_ioremap;
  1108 + }
  1109 +
  1110 + priv->irq = irq;
  1111 +
  1112 + /* initialize struct mii_if_info */
  1113 + priv->mii.phy_id = 0;
  1114 + priv->mii.phy_id_mask = 0x1f;
  1115 + priv->mii.reg_num_mask = 0x1f;
  1116 + priv->mii.dev = netdev;
  1117 + priv->mii.mdio_read = ftmac100_mdio_read;
  1118 + priv->mii.mdio_write = ftmac100_mdio_write;
  1119 +
  1120 + /* register network device */
  1121 + err = register_netdev(netdev);
  1122 + if (err) {
  1123 + dev_err(&pdev->dev, "Failed to register netdev\n");
  1124 + goto err_register_netdev;
  1125 + }
  1126 +
  1127 + netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
  1128 +
  1129 + if (!is_valid_ether_addr(netdev->dev_addr)) {
  1130 + random_ether_addr(netdev->dev_addr);
  1131 + netdev_info(netdev, "generated random MAC address %pM\n",
  1132 + netdev->dev_addr);
  1133 + }
  1134 +
  1135 + return 0;
  1136 +
  1137 +err_register_netdev:
  1138 + iounmap(priv->base);
  1139 +err_ioremap:
  1140 + release_resource(priv->res);
  1141 +err_req_mem:
  1142 + netif_napi_del(&priv->napi);
  1143 + platform_set_drvdata(pdev, NULL);
  1144 + free_netdev(netdev);
  1145 +err_alloc_etherdev:
  1146 + return err;
  1147 +}
  1148 +
  1149 +static int __exit ftmac100_remove(struct platform_device *pdev)
  1150 +{
  1151 + struct net_device *netdev;
  1152 + struct ftmac100 *priv;
  1153 +
  1154 + netdev = platform_get_drvdata(pdev);
  1155 + priv = netdev_priv(netdev);
  1156 +
  1157 + unregister_netdev(netdev);
  1158 +
  1159 + iounmap(priv->base);
  1160 + release_resource(priv->res);
  1161 +
  1162 + netif_napi_del(&priv->napi);
  1163 + platform_set_drvdata(pdev, NULL);
  1164 + free_netdev(netdev);
  1165 + return 0;
  1166 +}
  1167 +
  1168 +static struct platform_driver ftmac100_driver = {
  1169 + .probe = ftmac100_probe,
  1170 + .remove = __exit_p(ftmac100_remove),
  1171 + .driver = {
  1172 + .name = DRV_NAME,
  1173 + .owner = THIS_MODULE,
  1174 + },
  1175 +};
  1176 +
  1177 +/******************************************************************************
  1178 + * initialization / finalization
  1179 + *****************************************************************************/
  1180 +static int __init ftmac100_init(void)
  1181 +{
  1182 + pr_info("Loading version " DRV_VERSION " ...\n");
  1183 + return platform_driver_register(&ftmac100_driver);
  1184 +}
  1185 +
  1186 +static void __exit ftmac100_exit(void)
  1187 +{
  1188 + platform_driver_unregister(&ftmac100_driver);
  1189 +}
  1190 +
  1191 +module_init(ftmac100_init);
  1192 +module_exit(ftmac100_exit);
  1193 +
  1194 +MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
  1195 +MODULE_DESCRIPTION("FTMAC100 driver");
  1196 +MODULE_LICENSE("GPL");
drivers/net/ftmac100.h
  1 +/*
  2 + * Faraday FTMAC100 10/100 Ethernet
  3 + *
  4 + * (C) Copyright 2009-2011 Faraday Technology
  5 + * Po-Yu Chuang <ratbert@faraday-tech.com>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 + */
  21 +
  22 +#ifndef __FTMAC100_H
  23 +#define __FTMAC100_H
  24 +
  25 +#define FTMAC100_OFFSET_ISR 0x00
  26 +#define FTMAC100_OFFSET_IMR 0x04
  27 +#define FTMAC100_OFFSET_MAC_MADR 0x08
  28 +#define FTMAC100_OFFSET_MAC_LADR 0x0c
  29 +#define FTMAC100_OFFSET_MAHT0 0x10
  30 +#define FTMAC100_OFFSET_MAHT1 0x14
  31 +#define FTMAC100_OFFSET_TXPD 0x18
  32 +#define FTMAC100_OFFSET_RXPD 0x1c
  33 +#define FTMAC100_OFFSET_TXR_BADR 0x20
  34 +#define FTMAC100_OFFSET_RXR_BADR 0x24
  35 +#define FTMAC100_OFFSET_ITC 0x28
  36 +#define FTMAC100_OFFSET_APTC 0x2c
  37 +#define FTMAC100_OFFSET_DBLAC 0x30
  38 +#define FTMAC100_OFFSET_MACCR 0x88
  39 +#define FTMAC100_OFFSET_MACSR 0x8c
  40 +#define FTMAC100_OFFSET_PHYCR 0x90
  41 +#define FTMAC100_OFFSET_PHYWDATA 0x94
  42 +#define FTMAC100_OFFSET_FCR 0x98
  43 +#define FTMAC100_OFFSET_BPR 0x9c
  44 +#define FTMAC100_OFFSET_TS 0xc4
  45 +#define FTMAC100_OFFSET_DMAFIFOS 0xc8
  46 +#define FTMAC100_OFFSET_TM 0xcc
  47 +#define FTMAC100_OFFSET_TX_MCOL_SCOL 0xd4
  48 +#define FTMAC100_OFFSET_RPF_AEP 0xd8
  49 +#define FTMAC100_OFFSET_XM_PG 0xdc
  50 +#define FTMAC100_OFFSET_RUNT_TLCC 0xe0
  51 +#define FTMAC100_OFFSET_CRCER_FTL 0xe4
  52 +#define FTMAC100_OFFSET_RLC_RCC 0xe8
  53 +#define FTMAC100_OFFSET_BROC 0xec
  54 +#define FTMAC100_OFFSET_MULCA 0xf0
  55 +#define FTMAC100_OFFSET_RP 0xf4
  56 +#define FTMAC100_OFFSET_XP 0xf8
  57 +
  58 +/*
  59 + * Interrupt status register & interrupt mask register
  60 + */
  61 +#define FTMAC100_INT_RPKT_FINISH (1 << 0)
  62 +#define FTMAC100_INT_NORXBUF (1 << 1)
  63 +#define FTMAC100_INT_XPKT_FINISH (1 << 2)
  64 +#define FTMAC100_INT_NOTXBUF (1 << 3)
  65 +#define FTMAC100_INT_XPKT_OK (1 << 4)
  66 +#define FTMAC100_INT_XPKT_LOST (1 << 5)
  67 +#define FTMAC100_INT_RPKT_SAV (1 << 6)
  68 +#define FTMAC100_INT_RPKT_LOST (1 << 7)
  69 +#define FTMAC100_INT_AHB_ERR (1 << 8)
  70 +#define FTMAC100_INT_PHYSTS_CHG (1 << 9)
  71 +
  72 +/*
  73 + * Interrupt timer control register
  74 + */
  75 +#define FTMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
  76 +#define FTMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
  77 +#define FTMAC100_ITC_RXINT_TIME_SEL (1 << 7)
  78 +#define FTMAC100_ITC_TXINT_CNT(x) (((x) & 0xf) << 8)
  79 +#define FTMAC100_ITC_TXINT_THR(x) (((x) & 0x7) << 12)
  80 +#define FTMAC100_ITC_TXINT_TIME_SEL (1 << 15)
  81 +
  82 +/*
  83 + * Automatic polling timer control register
  84 + */
  85 +#define FTMAC100_APTC_RXPOLL_CNT(x) (((x) & 0xf) << 0)
  86 +#define FTMAC100_APTC_RXPOLL_TIME_SEL (1 << 4)
  87 +#define FTMAC100_APTC_TXPOLL_CNT(x) (((x) & 0xf) << 8)
  88 +#define FTMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
  89 +
  90 +/*
  91 + * DMA burst length and arbitration control register
  92 + */
  93 +#define FTMAC100_DBLAC_INCR4_EN (1 << 0)
  94 +#define FTMAC100_DBLAC_INCR8_EN (1 << 1)
  95 +#define FTMAC100_DBLAC_INCR16_EN (1 << 2)
  96 +#define FTMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 3)
  97 +#define FTMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 6)
  98 +#define FTMAC100_DBLAC_RX_THR_EN (1 << 9)
  99 +
  100 +/*
  101 + * MAC control register
  102 + */
  103 +#define FTMAC100_MACCR_XDMA_EN (1 << 0)
  104 +#define FTMAC100_MACCR_RDMA_EN (1 << 1)
  105 +#define FTMAC100_MACCR_SW_RST (1 << 2)
  106 +#define FTMAC100_MACCR_LOOP_EN (1 << 3)
  107 +#define FTMAC100_MACCR_CRC_DIS (1 << 4)
  108 +#define FTMAC100_MACCR_XMT_EN (1 << 5)
  109 +#define FTMAC100_MACCR_ENRX_IN_HALFTX (1 << 6)
  110 +#define FTMAC100_MACCR_RCV_EN (1 << 8)
  111 +#define FTMAC100_MACCR_HT_MULTI_EN (1 << 9)
  112 +#define FTMAC100_MACCR_RX_RUNT (1 << 10)
  113 +#define FTMAC100_MACCR_RX_FTL (1 << 11)
  114 +#define FTMAC100_MACCR_RCV_ALL (1 << 12)
  115 +#define FTMAC100_MACCR_CRC_APD (1 << 14)
  116 +#define FTMAC100_MACCR_FULLDUP (1 << 15)
  117 +#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
  118 +#define FTMAC100_MACCR_RX_BROADPKT (1 << 17)
  119 +
  120 +/*
  121 + * PHY control register
  122 + */
  123 +#define FTMAC100_PHYCR_MIIRDATA 0xffff
  124 +#define FTMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
  125 +#define FTMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
  126 +#define FTMAC100_PHYCR_MIIRD (1 << 26)
  127 +#define FTMAC100_PHYCR_MIIWR (1 << 27)
  128 +
  129 +/*
  130 + * PHY write data register
  131 + */
  132 +#define FTMAC100_PHYWDATA_MIIWDATA(x) ((x) & 0xffff)
  133 +
  134 +/*
  135 + * Transmit descriptor, aligned to 16 bytes
  136 + */
  137 +struct ftmac100_txdes {
  138 + unsigned int txdes0;
  139 + unsigned int txdes1;
  140 + unsigned int txdes2; /* TXBUF_BADR */
  141 + unsigned int txdes3; /* not used by HW */
  142 +} __attribute__ ((aligned(16)));
  143 +
  144 +#define FTMAC100_TXDES0_TXPKT_LATECOL (1 << 0)
  145 +#define FTMAC100_TXDES0_TXPKT_EXSCOL (1 << 1)
  146 +#define FTMAC100_TXDES0_TXDMA_OWN (1 << 31)
  147 +
  148 +#define FTMAC100_TXDES1_TXBUF_SIZE(x) ((x) & 0x7ff)
  149 +#define FTMAC100_TXDES1_LTS (1 << 27)
  150 +#define FTMAC100_TXDES1_FTS (1 << 28)
  151 +#define FTMAC100_TXDES1_TX2FIC (1 << 29)
  152 +#define FTMAC100_TXDES1_TXIC (1 << 30)
  153 +#define FTMAC100_TXDES1_EDOTR (1 << 31)
  154 +
  155 +/*
  156 + * Receive descriptor, aligned to 16 bytes
  157 + */
  158 +struct ftmac100_rxdes {
  159 + unsigned int rxdes0;
  160 + unsigned int rxdes1;
  161 + unsigned int rxdes2; /* RXBUF_BADR */
  162 + unsigned int rxdes3; /* not used by HW */
  163 +} __attribute__ ((aligned(16)));
  164 +
  165 +#define FTMAC100_RXDES0_RFL 0x7ff
  166 +#define FTMAC100_RXDES0_MULTICAST (1 << 16)
  167 +#define FTMAC100_RXDES0_BROADCAST (1 << 17)
  168 +#define FTMAC100_RXDES0_RX_ERR (1 << 18)
  169 +#define FTMAC100_RXDES0_CRC_ERR (1 << 19)
  170 +#define FTMAC100_RXDES0_FTL (1 << 20)
  171 +#define FTMAC100_RXDES0_RUNT (1 << 21)
  172 +#define FTMAC100_RXDES0_RX_ODD_NB (1 << 22)
  173 +#define FTMAC100_RXDES0_LRS (1 << 28)
  174 +#define FTMAC100_RXDES0_FRS (1 << 29)
  175 +#define FTMAC100_RXDES0_RXDMA_OWN (1 << 31)
  176 +
  177 +#define FTMAC100_RXDES1_RXBUF_SIZE(x) ((x) & 0x7ff)
  178 +#define FTMAC100_RXDES1_EDORR (1 << 31)
  179 +
  180 +#endif /* __FTMAC100_H */