Commit efdd731957caff85db619636a972b7f5404ea9b4

Authored by Rob Herring
Committed by Wolfgang Denk
1 parent dbee61db43

net: add Calxeda xgmac driver

This adds ethernet driver for Calxeda xgmac found on Highbank SOC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>

Fix: WARNING: __aligned(size) is preferred over
__attribute__((aligned(size)))
Signed-off-by: Wolfgang Denk <wd@denx.de>

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

... ... @@ -1029,6 +1029,9 @@
1029 1029 If this defined, the driver is quiet.
1030 1030 The driver doen't show link status messages.
1031 1031  
  1032 + CONFIG_CALXEDA_XGMAC
  1033 + Support for the Calxeda XGMAC device
  1034 +
1032 1035 CONFIG_DRIVER_LAN91C96
1033 1036 Support for SMSC's LAN91C96 chips.
1034 1037  
drivers/net/Makefile
... ... @@ -31,6 +31,7 @@
31 31 COBJS-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
32 32 COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
33 33 COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o
  34 +COBJS-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o
34 35 COBJS-$(CONFIG_CS8900) += cs8900.o
35 36 COBJS-$(CONFIG_TULIP) += dc2114x.o
36 37 COBJS-$(CONFIG_DESIGNWARE_ETH) += designware.o
drivers/net/calxedaxgmac.c
  1 +/*
  2 + * Copyright 2010-2011 Calxeda, Inc.
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify it
  5 + * under the terms of the GNU General Public License as published by the Free
  6 + * Software Foundation; either version 2 of the License, or (at your option)
  7 + * any later version.
  8 + *
  9 + * This program is distributed in the hope it will be useful, but WITHOUT
  10 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 + * more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License along with
  15 + * this program. If not, see <http://www.gnu.org/licenses/>.
  16 + */
  17 +#include <common.h>
  18 +#include <malloc.h>
  19 +#include <linux/err.h>
  20 +#include <asm/io.h>
  21 +
  22 +#define TX_NUM_DESC 1
  23 +#define RX_NUM_DESC 32
  24 +
  25 +#define MAC_TIMEOUT (5*CONFIG_SYS_HZ)
  26 +
  27 +#define ETH_BUF_SZ 2048
  28 +#define TX_BUF_SZ (ETH_BUF_SZ * TX_NUM_DESC)
  29 +#define RX_BUF_SZ (ETH_BUF_SZ * RX_NUM_DESC)
  30 +
  31 +#define RXSTART 0x00000002
  32 +#define TXSTART 0x00002000
  33 +
  34 +#define RXENABLE 0x00000004
  35 +#define TXENABLE 0x00000008
  36 +
  37 +#define XGMAC_CONTROL_SPD 0x40000000
  38 +#define XGMAC_CONTROL_SPD_MASK 0x60000000
  39 +#define XGMAC_CONTROL_SARC 0x10000000
  40 +#define XGMAC_CONTROL_SARK_MASK 0x18000000
  41 +#define XGMAC_CONTROL_CAR 0x04000000
  42 +#define XGMAC_CONTROL_CAR_MASK 0x06000000
  43 +#define XGMAC_CONTROL_CAR_SHIFT 25
  44 +#define XGMAC_CONTROL_DP 0x01000000
  45 +#define XGMAC_CONTROL_WD 0x00800000
  46 +#define XGMAC_CONTROL_JD 0x00400000
  47 +#define XGMAC_CONTROL_JE 0x00100000
  48 +#define XGMAC_CONTROL_LM 0x00001000
  49 +#define XGMAC_CONTROL_IPC 0x00000400
  50 +#define XGMAC_CONTROL_ACS 0x00000080
  51 +#define XGMAC_CONTROL_DDIC 0x00000010
  52 +#define XGMAC_CONTROL_TE 0x00000008
  53 +#define XGMAC_CONTROL_RE 0x00000004
  54 +
  55 +#define XGMAC_DMA_BUSMODE_RESET 0x00000001
  56 +#define XGMAC_DMA_BUSMODE_DSL 0x00000004
  57 +#define XGMAC_DMA_BUSMODE_DSL_MASK 0x0000007c
  58 +#define XGMAC_DMA_BUSMODE_DSL_SHIFT 2
  59 +#define XGMAC_DMA_BUSMODE_ATDS 0x00000080
  60 +#define XGMAC_DMA_BUSMODE_PBL_MASK 0x00003f00
  61 +#define XGMAC_DMA_BUSMODE_PBL_SHIFT 8
  62 +#define XGMAC_DMA_BUSMODE_FB 0x00010000
  63 +#define XGMAC_DMA_BUSMODE_USP 0x00800000
  64 +#define XGMAC_DMA_BUSMODE_8PBL 0x01000000
  65 +#define XGMAC_DMA_BUSMODE_AAL 0x02000000
  66 +
  67 +#define XGMAC_DMA_AXIMODE_ENLPI 0x80000000
  68 +#define XGMAC_DMA_AXIMODE_MGK 0x40000000
  69 +#define XGMAC_DMA_AXIMODE_WROSR 0x00100000
  70 +#define XGMAC_DMA_AXIMODE_WROSR_MASK 0x00F00000
  71 +#define XGMAC_DMA_AXIMODE_WROSR_SHIFT 20
  72 +#define XGMAC_DMA_AXIMODE_RDOSR 0x00010000
  73 +#define XGMAC_DMA_AXIMODE_RDOSR_MASK 0x000F0000
  74 +#define XGMAC_DMA_AXIMODE_RDOSR_SHIFT 16
  75 +#define XGMAC_DMA_AXIMODE_AAL 0x00001000
  76 +#define XGMAC_DMA_AXIMODE_BLEN256 0x00000080
  77 +#define XGMAC_DMA_AXIMODE_BLEN128 0x00000040
  78 +#define XGMAC_DMA_AXIMODE_BLEN64 0x00000020
  79 +#define XGMAC_DMA_AXIMODE_BLEN32 0x00000010
  80 +#define XGMAC_DMA_AXIMODE_BLEN16 0x00000008
  81 +#define XGMAC_DMA_AXIMODE_BLEN8 0x00000004
  82 +#define XGMAC_DMA_AXIMODE_BLEN4 0x00000002
  83 +#define XGMAC_DMA_AXIMODE_UNDEF 0x00000001
  84 +
  85 +#define XGMAC_CORE_OMR_RTC_SHIFT 3
  86 +#define XGMAC_CORE_OMR_RTC_MASK 0x00000018
  87 +#define XGMAC_CORE_OMR_RTC 0x00000010
  88 +#define XGMAC_CORE_OMR_RSF 0x00000020
  89 +#define XGMAC_CORE_OMR_DT 0x00000040
  90 +#define XGMAC_CORE_OMR_FEF 0x00000080
  91 +#define XGMAC_CORE_OMR_EFC 0x00000100
  92 +#define XGMAC_CORE_OMR_RFA_SHIFT 9
  93 +#define XGMAC_CORE_OMR_RFA_MASK 0x00000E00
  94 +#define XGMAC_CORE_OMR_RFD_SHIFT 12
  95 +#define XGMAC_CORE_OMR_RFD_MASK 0x00007000
  96 +#define XGMAC_CORE_OMR_TTC_SHIFT 16
  97 +#define XGMAC_CORE_OMR_TTC_MASK 0x00030000
  98 +#define XGMAC_CORE_OMR_TTC 0x00020000
  99 +#define XGMAC_CORE_OMR_FTF 0x00100000
  100 +#define XGMAC_CORE_OMR_TSF 0x00200000
  101 +
  102 +#define FIFO_MINUS_1K 0x0
  103 +#define FIFO_MINUS_2K 0x1
  104 +#define FIFO_MINUS_3K 0x2
  105 +#define FIFO_MINUS_4K 0x3
  106 +#define FIFO_MINUS_6K 0x4
  107 +#define FIFO_MINUS_8K 0x5
  108 +#define FIFO_MINUS_12K 0x6
  109 +#define FIFO_MINUS_16K 0x7
  110 +
  111 +#define XGMAC_CORE_FLOW_PT_SHIFT 16
  112 +#define XGMAC_CORE_FLOW_PT_MASK 0xFFFF0000
  113 +#define XGMAC_CORE_FLOW_PT 0x00010000
  114 +#define XGMAC_CORE_FLOW_DZQP 0x00000080
  115 +#define XGMAC_CORE_FLOW_PLT_SHIFT 4
  116 +#define XGMAC_CORE_FLOW_PLT_MASK 0x00000030
  117 +#define XGMAC_CORE_FLOW_PLT 0x00000010
  118 +#define XGMAC_CORE_FLOW_UP 0x00000008
  119 +#define XGMAC_CORE_FLOW_RFE 0x00000004
  120 +#define XGMAC_CORE_FLOW_TFE 0x00000002
  121 +#define XGMAC_CORE_FLOW_FCB 0x00000001
  122 +
  123 +/* XGMAC Descriptor Defines */
  124 +#define MAX_DESC_BUF_SZ (0x2000 - 8)
  125 +
  126 +#define RXDESC_EXT_STATUS 0x00000001
  127 +#define RXDESC_CRC_ERR 0x00000002
  128 +#define RXDESC_RX_ERR 0x00000008
  129 +#define RXDESC_RX_WDOG 0x00000010
  130 +#define RXDESC_FRAME_TYPE 0x00000020
  131 +#define RXDESC_GIANT_FRAME 0x00000080
  132 +#define RXDESC_LAST_SEG 0x00000100
  133 +#define RXDESC_FIRST_SEG 0x00000200
  134 +#define RXDESC_VLAN_FRAME 0x00000400
  135 +#define RXDESC_OVERFLOW_ERR 0x00000800
  136 +#define RXDESC_LENGTH_ERR 0x00001000
  137 +#define RXDESC_SA_FILTER_FAIL 0x00002000
  138 +#define RXDESC_DESCRIPTOR_ERR 0x00004000
  139 +#define RXDESC_ERROR_SUMMARY 0x00008000
  140 +#define RXDESC_FRAME_LEN_OFFSET 16
  141 +#define RXDESC_FRAME_LEN_MASK 0x3fff0000
  142 +#define RXDESC_DA_FILTER_FAIL 0x40000000
  143 +
  144 +#define RXDESC1_END_RING 0x00008000
  145 +
  146 +#define RXDESC_IP_PAYLOAD_MASK 0x00000003
  147 +#define RXDESC_IP_PAYLOAD_UDP 0x00000001
  148 +#define RXDESC_IP_PAYLOAD_TCP 0x00000002
  149 +#define RXDESC_IP_PAYLOAD_ICMP 0x00000003
  150 +#define RXDESC_IP_HEADER_ERR 0x00000008
  151 +#define RXDESC_IP_PAYLOAD_ERR 0x00000010
  152 +#define RXDESC_IPV4_PACKET 0x00000040
  153 +#define RXDESC_IPV6_PACKET 0x00000080
  154 +#define TXDESC_UNDERFLOW_ERR 0x00000001
  155 +#define TXDESC_JABBER_TIMEOUT 0x00000002
  156 +#define TXDESC_LOCAL_FAULT 0x00000004
  157 +#define TXDESC_REMOTE_FAULT 0x00000008
  158 +#define TXDESC_VLAN_FRAME 0x00000010
  159 +#define TXDESC_FRAME_FLUSHED 0x00000020
  160 +#define TXDESC_IP_HEADER_ERR 0x00000040
  161 +#define TXDESC_PAYLOAD_CSUM_ERR 0x00000080
  162 +#define TXDESC_ERROR_SUMMARY 0x00008000
  163 +#define TXDESC_SA_CTRL_INSERT 0x00040000
  164 +#define TXDESC_SA_CTRL_REPLACE 0x00080000
  165 +#define TXDESC_2ND_ADDR_CHAINED 0x00100000
  166 +#define TXDESC_END_RING 0x00200000
  167 +#define TXDESC_CSUM_IP 0x00400000
  168 +#define TXDESC_CSUM_IP_PAYLD 0x00800000
  169 +#define TXDESC_CSUM_ALL 0x00C00000
  170 +#define TXDESC_CRC_EN_REPLACE 0x01000000
  171 +#define TXDESC_CRC_EN_APPEND 0x02000000
  172 +#define TXDESC_DISABLE_PAD 0x04000000
  173 +#define TXDESC_FIRST_SEG 0x10000000
  174 +#define TXDESC_LAST_SEG 0x20000000
  175 +#define TXDESC_INTERRUPT 0x40000000
  176 +
  177 +#define DESC_OWN 0x80000000
  178 +#define DESC_BUFFER1_SZ_MASK 0x00001fff
  179 +#define DESC_BUFFER2_SZ_MASK 0x1fff0000
  180 +#define DESC_BUFFER2_SZ_OFFSET 16
  181 +
  182 +struct xgmac_regs {
  183 + u32 config;
  184 + u32 framefilter;
  185 + u32 resv_1[4];
  186 + u32 flow_control;
  187 + u32 vlantag;
  188 + u32 version;
  189 + u32 vlaninclude;
  190 + u32 resv_2[2];
  191 + u32 pacestretch;
  192 + u32 vlanhash;
  193 + u32 resv_3;
  194 + u32 intreg;
  195 + struct {
  196 + u32 hi; /* 0x40 */
  197 + u32 lo; /* 0x44 */
  198 + } macaddr[16];
  199 + u32 resv_4[0xd0];
  200 + u32 core_opmode; /* 0x400 */
  201 + u32 resv_5[0x2bf];
  202 + u32 busmode; /* 0xf00 */
  203 + u32 txpoll;
  204 + u32 rxpoll;
  205 + u32 rxdesclist;
  206 + u32 txdesclist;
  207 + u32 dma_status;
  208 + u32 dma_opmode;
  209 + u32 intenable;
  210 + u32 resv_6[2];
  211 + u32 axi_mode; /* 0xf28 */
  212 +};
  213 +
  214 +struct xgmac_dma_desc {
  215 + __le32 flags;
  216 + __le32 buf_size;
  217 + __le32 buf1_addr; /* Buffer 1 Address Pointer */
  218 + __le32 buf2_addr; /* Buffer 2 Address Pointer */
  219 + __le32 ext_status;
  220 + __le32 res[3];
  221 +};
  222 +
  223 +/* XGMAC Descriptor Access Helpers */
  224 +static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
  225 +{
  226 + if (buf_sz > MAX_DESC_BUF_SZ)
  227 + p->buf_size = cpu_to_le32(MAX_DESC_BUF_SZ |
  228 + (buf_sz - MAX_DESC_BUF_SZ) << DESC_BUFFER2_SZ_OFFSET);
  229 + else
  230 + p->buf_size = cpu_to_le32(buf_sz);
  231 +}
  232 +
  233 +static inline int desc_get_buf_len(struct xgmac_dma_desc *p)
  234 +{
  235 + u32 len = le32_to_cpu(p->buf_size);
  236 + return (len & DESC_BUFFER1_SZ_MASK) +
  237 + ((len & DESC_BUFFER2_SZ_MASK) >> DESC_BUFFER2_SZ_OFFSET);
  238 +}
  239 +
  240 +static inline void desc_init_rx_desc(struct xgmac_dma_desc *p, int ring_size,
  241 + int buf_sz)
  242 +{
  243 + struct xgmac_dma_desc *end = p + ring_size - 1;
  244 +
  245 + memset(p, 0, sizeof(*p) * ring_size);
  246 +
  247 + for (; p <= end; p++)
  248 + desc_set_buf_len(p, buf_sz);
  249 +
  250 + end->buf_size |= cpu_to_le32(RXDESC1_END_RING);
  251 +}
  252 +
  253 +static inline void desc_init_tx_desc(struct xgmac_dma_desc *p, u32 ring_size)
  254 +{
  255 + memset(p, 0, sizeof(*p) * ring_size);
  256 + p[ring_size - 1].flags = cpu_to_le32(TXDESC_END_RING);
  257 +}
  258 +
  259 +static inline int desc_get_owner(struct xgmac_dma_desc *p)
  260 +{
  261 + return le32_to_cpu(p->flags) & DESC_OWN;
  262 +}
  263 +
  264 +static inline void desc_set_rx_owner(struct xgmac_dma_desc *p)
  265 +{
  266 + /* Clear all fields and set the owner */
  267 + p->flags = cpu_to_le32(DESC_OWN);
  268 +}
  269 +
  270 +static inline void desc_set_tx_owner(struct xgmac_dma_desc *p, u32 flags)
  271 +{
  272 + u32 tmpflags = le32_to_cpu(p->flags);
  273 + tmpflags &= TXDESC_END_RING;
  274 + tmpflags |= flags | DESC_OWN;
  275 + p->flags = cpu_to_le32(tmpflags);
  276 +}
  277 +
  278 +static inline void *desc_get_buf_addr(struct xgmac_dma_desc *p)
  279 +{
  280 + return (void *)le32_to_cpu(p->buf1_addr);
  281 +}
  282 +
  283 +static inline void desc_set_buf_addr(struct xgmac_dma_desc *p,
  284 + void *paddr, int len)
  285 +{
  286 + p->buf1_addr = cpu_to_le32(paddr);
  287 + if (len > MAX_DESC_BUF_SZ)
  288 + p->buf2_addr = cpu_to_le32(paddr + MAX_DESC_BUF_SZ);
  289 +}
  290 +
  291 +static inline void desc_set_buf_addr_and_size(struct xgmac_dma_desc *p,
  292 + void *paddr, int len)
  293 +{
  294 + desc_set_buf_len(p, len);
  295 + desc_set_buf_addr(p, paddr, len);
  296 +}
  297 +
  298 +static inline int desc_get_rx_frame_len(struct xgmac_dma_desc *p)
  299 +{
  300 + u32 data = le32_to_cpu(p->flags);
  301 + u32 len = (data & RXDESC_FRAME_LEN_MASK) >> RXDESC_FRAME_LEN_OFFSET;
  302 + if (data & RXDESC_FRAME_TYPE)
  303 + len -= 4;
  304 +
  305 + return len;
  306 +}
  307 +
  308 +struct calxeda_eth_dev {
  309 + struct xgmac_dma_desc rx_chain[RX_NUM_DESC];
  310 + struct xgmac_dma_desc tx_chain[TX_NUM_DESC];
  311 + char rxbuffer[RX_BUF_SZ];
  312 +
  313 + u32 tx_currdesc;
  314 + u32 rx_currdesc;
  315 +
  316 + struct eth_device *dev;
  317 +} __aligned(32);
  318 +
  319 +/*
  320 + * Initialize a descriptor ring. Calxeda XGMAC is configured to use
  321 + * advanced descriptors.
  322 + */
  323 +
  324 +static void init_rx_desc(struct calxeda_eth_dev *priv)
  325 +{
  326 + struct xgmac_dma_desc *rxdesc = priv->rx_chain;
  327 + struct xgmac_regs *regs = (struct xgmac_regs *)priv->dev->iobase;
  328 + void *rxbuffer = priv->rxbuffer;
  329 + int i;
  330 +
  331 + desc_init_rx_desc(rxdesc, RX_NUM_DESC, ETH_BUF_SZ);
  332 + writel((ulong)rxdesc, &regs->rxdesclist);
  333 +
  334 + for (i = 0; i < RX_NUM_DESC; i++) {
  335 + desc_set_buf_addr(rxdesc + i, rxbuffer + (i * ETH_BUF_SZ),
  336 + ETH_BUF_SZ);
  337 + desc_set_rx_owner(rxdesc + i);
  338 + }
  339 +}
  340 +
  341 +static void init_tx_desc(struct calxeda_eth_dev *priv)
  342 +{
  343 + struct xgmac_regs *regs = (struct xgmac_regs *)priv->dev->iobase;
  344 +
  345 + desc_init_tx_desc(priv->tx_chain, TX_NUM_DESC);
  346 + writel((ulong)priv->tx_chain, &regs->txdesclist);
  347 +}
  348 +
  349 +static int xgmac_reset(struct eth_device *dev)
  350 +{
  351 + struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
  352 + int timeout = MAC_TIMEOUT;
  353 + u32 value;
  354 +
  355 + value = readl(&regs->config) & XGMAC_CONTROL_SPD_MASK;
  356 +
  357 + writel(XGMAC_DMA_BUSMODE_RESET, &regs->busmode);
  358 + while ((timeout-- >= 0) &&
  359 + (readl(&regs->busmode) & XGMAC_DMA_BUSMODE_RESET))
  360 + udelay(1);
  361 +
  362 + writel(value, &regs->config);
  363 +
  364 + return timeout;
  365 +}
  366 +
  367 +static void xgmac_hwmacaddr(struct eth_device *dev)
  368 +{
  369 + struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
  370 + u32 macaddr[2];
  371 +
  372 + memcpy(macaddr, dev->enetaddr, 6);
  373 + writel(macaddr[1], &regs->macaddr[0].hi);
  374 + writel(macaddr[0], &regs->macaddr[0].lo);
  375 +}
  376 +
  377 +static int xgmac_init(struct eth_device *dev, bd_t * bis)
  378 +{
  379 + struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
  380 + struct calxeda_eth_dev *priv = dev->priv;
  381 + int value;
  382 +
  383 + if (xgmac_reset(dev) < 0)
  384 + return -1;
  385 +
  386 + /* set the hardware MAC address */
  387 + xgmac_hwmacaddr(dev);
  388 +
  389 + /* set the AXI bus modes */
  390 + value = XGMAC_DMA_BUSMODE_ATDS |
  391 + (16 << XGMAC_DMA_BUSMODE_PBL_SHIFT) |
  392 + XGMAC_DMA_BUSMODE_FB | XGMAC_DMA_BUSMODE_AAL;
  393 + writel(value, &regs->busmode);
  394 +
  395 + value = XGMAC_DMA_AXIMODE_AAL | XGMAC_DMA_AXIMODE_BLEN16 |
  396 + XGMAC_DMA_AXIMODE_BLEN8 | XGMAC_DMA_AXIMODE_BLEN4;
  397 + writel(value, &regs->axi_mode);
  398 +
  399 + /* set flow control parameters and store and forward mode */
  400 + value = (FIFO_MINUS_12K << XGMAC_CORE_OMR_RFD_SHIFT) |
  401 + (FIFO_MINUS_4K << XGMAC_CORE_OMR_RFA_SHIFT) |
  402 + XGMAC_CORE_OMR_EFC | XGMAC_CORE_OMR_TSF | XGMAC_CORE_OMR_RSF;
  403 + writel(value, &regs->core_opmode);
  404 +
  405 + /* enable pause frames */
  406 + value = (1024 << XGMAC_CORE_FLOW_PT_SHIFT) |
  407 + (1 << XGMAC_CORE_FLOW_PLT_SHIFT) |
  408 + XGMAC_CORE_FLOW_UP | XGMAC_CORE_FLOW_RFE | XGMAC_CORE_FLOW_TFE;
  409 + writel(value, &regs->flow_control);
  410 +
  411 + /* Initialize the descriptor chains */
  412 + init_rx_desc(priv);
  413 + init_tx_desc(priv);
  414 +
  415 + /* must set to 0, or when started up will cause issues */
  416 + priv->tx_currdesc = 0;
  417 + priv->rx_currdesc = 0;
  418 +
  419 + /* set default core values */
  420 + value = readl(&regs->config);
  421 + value &= XGMAC_CONTROL_SPD_MASK;
  422 + value |= XGMAC_CONTROL_DDIC | XGMAC_CONTROL_ACS |
  423 + XGMAC_CONTROL_IPC | XGMAC_CONTROL_CAR;
  424 +
  425 + /* Everything is ready enable both mac and DMA */
  426 + value |= RXENABLE | TXENABLE;
  427 + writel(value, &regs->config);
  428 +
  429 + value = readl(&regs->dma_opmode);
  430 + value |= RXSTART | TXSTART;
  431 + writel(value, &regs->dma_opmode);
  432 +
  433 + return 0;
  434 +}
  435 +
  436 +static int xgmac_tx(struct eth_device *dev, volatile void *packet, int length)
  437 +{
  438 + struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
  439 + struct calxeda_eth_dev *priv = dev->priv;
  440 + u32 currdesc = priv->tx_currdesc;
  441 + struct xgmac_dma_desc *txdesc = &priv->tx_chain[currdesc];
  442 + int timeout;
  443 +
  444 + desc_set_buf_addr_and_size(txdesc, (void *)packet, length);
  445 + desc_set_tx_owner(txdesc, TXDESC_FIRST_SEG |
  446 + TXDESC_LAST_SEG | TXDESC_CRC_EN_APPEND);
  447 +
  448 + /* write poll demand */
  449 + writel(1, &regs->txpoll);
  450 +
  451 + timeout = 1000000;
  452 + while (desc_get_owner(txdesc)) {
  453 + if (timeout-- < 0) {
  454 + printf("xgmac: TX timeout\n");
  455 + return -ETIMEDOUT;
  456 + }
  457 + udelay(1);
  458 + }
  459 +
  460 + priv->tx_currdesc = (currdesc + 1) & (TX_NUM_DESC - 1);
  461 + return 0;
  462 +}
  463 +
  464 +static int xgmac_rx(struct eth_device *dev)
  465 +{
  466 + struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
  467 + struct calxeda_eth_dev *priv = dev->priv;
  468 + u32 currdesc = priv->rx_currdesc;
  469 + struct xgmac_dma_desc *rxdesc = &priv->rx_chain[currdesc];
  470 + int length = 0;
  471 +
  472 + /* check if the host has the desc */
  473 + if (desc_get_owner(rxdesc))
  474 + return -1; /* something bad happened */
  475 +
  476 + length = desc_get_rx_frame_len(rxdesc);
  477 +
  478 + NetReceive((volatile unsigned char *)desc_get_buf_addr(rxdesc), length);
  479 +
  480 + /* set descriptor back to owned by XGMAC */
  481 + desc_set_rx_owner(rxdesc);
  482 + writel(1, &regs->rxpoll);
  483 +
  484 + priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
  485 +
  486 + return length;
  487 +}
  488 +
  489 +static void xgmac_halt(struct eth_device *dev)
  490 +{
  491 + struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
  492 + struct calxeda_eth_dev *priv = dev->priv;
  493 + int value;
  494 +
  495 + /* Disable TX/RX */
  496 + value = readl(&regs->config);
  497 + value &= ~(RXENABLE | TXENABLE);
  498 + writel(value, &regs->config);
  499 +
  500 + /* Disable DMA */
  501 + value = readl(&regs->dma_opmode);
  502 + value &= ~(RXSTART | TXSTART);
  503 + writel(value, &regs->dma_opmode);
  504 +
  505 + /* must set to 0, or when started up will cause issues */
  506 + priv->tx_currdesc = 0;
  507 + priv->rx_currdesc = 0;
  508 +}
  509 +
  510 +int calxedaxgmac_initialize(u32 id, ulong base_addr)
  511 +{
  512 + struct eth_device *dev;
  513 + struct calxeda_eth_dev *priv;
  514 + struct xgmac_regs *regs;
  515 + u32 macaddr[2];
  516 +
  517 + regs = (struct xgmac_regs *)base_addr;
  518 +
  519 + /* check hardware version */
  520 + if (readl(&regs->version) != 0x1012)
  521 + return -1;
  522 +
  523 + dev = malloc(sizeof(*dev));
  524 + if (!dev)
  525 + return 0;
  526 + memset(dev, 0, sizeof(*dev));
  527 +
  528 + /* Structure must be aligned, because it contains the descriptors */
  529 + priv = memalign(32, sizeof(*priv));
  530 + if (!priv) {
  531 + free(dev);
  532 + return 0;
  533 + }
  534 +
  535 + dev->iobase = (int)base_addr;
  536 + dev->priv = priv;
  537 + priv->dev = dev;
  538 + sprintf(dev->name, "xgmac%d", id);
  539 +
  540 + /* The MAC address is already configured, so read it from registers. */
  541 + macaddr[1] = readl(&regs->macaddr[0].hi);
  542 + macaddr[0] = readl(&regs->macaddr[0].lo);
  543 + memcpy(dev->enetaddr, macaddr, 6);
  544 +
  545 + dev->init = xgmac_init;
  546 + dev->send = xgmac_tx;
  547 + dev->recv = xgmac_rx;
  548 + dev->halt = xgmac_halt;
  549 +
  550 + eth_register(dev);
  551 +
  552 + return 1;
  553 +}
... ... @@ -48,6 +48,7 @@
48 48 int au1x00_enet_initialize(bd_t*);
49 49 int ax88180_initialize(bd_t *bis);
50 50 int bfin_EMAC_initialize(bd_t *bis);
  51 +int calxedaxgmac_initialize(u32 id, ulong base_addr);
51 52 int cs8900_initialize(u8 dev_num, int base_addr);
52 53 int davinci_emac_initialize(void);
53 54 int dc21x4x_initialize(bd_t *bis);