1*594d57d0SMatthias Kaehlcke /* 2*594d57d0SMatthias Kaehlcke * Cirrus Logic EP93xx ethernet MAC / MII driver. 3*594d57d0SMatthias Kaehlcke * 4*594d57d0SMatthias Kaehlcke * Copyright (C) 2010, 2009 5*594d57d0SMatthias Kaehlcke * Matthias Kaehlcke <matthias@kaehlcke.net> 6*594d57d0SMatthias Kaehlcke * 7*594d57d0SMatthias Kaehlcke * Copyright (C) 2004, 2005 8*594d57d0SMatthias Kaehlcke * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> 9*594d57d0SMatthias Kaehlcke * 10*594d57d0SMatthias Kaehlcke * Based on the original eth.[ch] Cirrus Logic EP93xx Rev D. Ethernet Driver, 11*594d57d0SMatthias Kaehlcke * which is 12*594d57d0SMatthias Kaehlcke * 13*594d57d0SMatthias Kaehlcke * (C) Copyright 2002 2003 14*594d57d0SMatthias Kaehlcke * Adam Bezanson, Network Audio Technologies, Inc. 15*594d57d0SMatthias Kaehlcke * <bezanson@netaudiotech.com> 16*594d57d0SMatthias Kaehlcke * 17*594d57d0SMatthias Kaehlcke * See file CREDITS for list of people who contributed to this project. 18*594d57d0SMatthias Kaehlcke * 19*594d57d0SMatthias Kaehlcke * This program is free software; you can redistribute it and/or modify 20*594d57d0SMatthias Kaehlcke * it under the terms of the GNU General Public License as published by 21*594d57d0SMatthias Kaehlcke * the Free Software Foundation; either version 2 of the License, or 22*594d57d0SMatthias Kaehlcke * (at your option) any later version. 23*594d57d0SMatthias Kaehlcke * 24*594d57d0SMatthias Kaehlcke * This program is distributed in the hope that it will be useful, but 25*594d57d0SMatthias Kaehlcke * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 26*594d57d0SMatthias Kaehlcke * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 27*594d57d0SMatthias Kaehlcke * for more details. 28*594d57d0SMatthias Kaehlcke * 29*594d57d0SMatthias Kaehlcke * You should have received a copy of the GNU General Public License along 30*594d57d0SMatthias Kaehlcke * with this program; if not, write to the Free Software Foundation, Inc., 31*594d57d0SMatthias Kaehlcke * 675 Mass Ave, Cambridge, MA 02139, USA. 32*594d57d0SMatthias Kaehlcke */ 33*594d57d0SMatthias Kaehlcke 34*594d57d0SMatthias Kaehlcke #include <command.h> 35*594d57d0SMatthias Kaehlcke #include <common.h> 36*594d57d0SMatthias Kaehlcke #include <asm/arch/ep93xx.h> 37*594d57d0SMatthias Kaehlcke #include <asm/io.h> 38*594d57d0SMatthias Kaehlcke #include <malloc.h> 39*594d57d0SMatthias Kaehlcke #include <miiphy.h> 40*594d57d0SMatthias Kaehlcke #include <linux/types.h> 41*594d57d0SMatthias Kaehlcke #include "ep93xx_eth.h" 42*594d57d0SMatthias Kaehlcke 43*594d57d0SMatthias Kaehlcke #define GET_PRIV(eth_dev) ((struct ep93xx_priv *)(eth_dev)->priv) 44*594d57d0SMatthias Kaehlcke #define GET_REGS(eth_dev) (GET_PRIV(eth_dev)->regs) 45*594d57d0SMatthias Kaehlcke 46*594d57d0SMatthias Kaehlcke /* ep93xx_miiphy ops forward declarations */ 47*594d57d0SMatthias Kaehlcke static int ep93xx_miiphy_read(char * const dev, unsigned char const addr, 48*594d57d0SMatthias Kaehlcke unsigned char const reg, unsigned short * const value); 49*594d57d0SMatthias Kaehlcke static int ep93xx_miiphy_write(char * const dev, unsigned char const addr, 50*594d57d0SMatthias Kaehlcke unsigned char const reg, unsigned short const value); 51*594d57d0SMatthias Kaehlcke 52*594d57d0SMatthias Kaehlcke #if defined(EP93XX_MAC_DEBUG) 53*594d57d0SMatthias Kaehlcke /** 54*594d57d0SMatthias Kaehlcke * Dump ep93xx_mac values to the terminal. 55*594d57d0SMatthias Kaehlcke */ 56*594d57d0SMatthias Kaehlcke static void dump_dev(struct eth_device *dev) 57*594d57d0SMatthias Kaehlcke { 58*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 59*594d57d0SMatthias Kaehlcke int i; 60*594d57d0SMatthias Kaehlcke 61*594d57d0SMatthias Kaehlcke printf("\ndump_dev()\n"); 62*594d57d0SMatthias Kaehlcke printf(" rx_dq.base %p\n", priv->rx_dq.base); 63*594d57d0SMatthias Kaehlcke printf(" rx_dq.current %p\n", priv->rx_dq.current); 64*594d57d0SMatthias Kaehlcke printf(" rx_dq.end %p\n", priv->rx_dq.end); 65*594d57d0SMatthias Kaehlcke printf(" rx_sq.base %p\n", priv->rx_sq.base); 66*594d57d0SMatthias Kaehlcke printf(" rx_sq.current %p\n", priv->rx_sq.current); 67*594d57d0SMatthias Kaehlcke printf(" rx_sq.end %p\n", priv->rx_sq.end); 68*594d57d0SMatthias Kaehlcke 69*594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) 70*594d57d0SMatthias Kaehlcke printf(" rx_buffer[%2.d] %p\n", i, NetRxPackets[i]); 71*594d57d0SMatthias Kaehlcke 72*594d57d0SMatthias Kaehlcke printf(" tx_dq.base %p\n", priv->tx_dq.base); 73*594d57d0SMatthias Kaehlcke printf(" tx_dq.current %p\n", priv->tx_dq.current); 74*594d57d0SMatthias Kaehlcke printf(" tx_dq.end %p\n", priv->tx_dq.end); 75*594d57d0SMatthias Kaehlcke printf(" tx_sq.base %p\n", priv->tx_sq.base); 76*594d57d0SMatthias Kaehlcke printf(" tx_sq.current %p\n", priv->tx_sq.current); 77*594d57d0SMatthias Kaehlcke printf(" tx_sq.end %p\n", priv->tx_sq.end); 78*594d57d0SMatthias Kaehlcke } 79*594d57d0SMatthias Kaehlcke 80*594d57d0SMatthias Kaehlcke /** 81*594d57d0SMatthias Kaehlcke * Dump all RX status queue entries to the terminal. 82*594d57d0SMatthias Kaehlcke */ 83*594d57d0SMatthias Kaehlcke static void dump_rx_status_queue(struct eth_device *dev) 84*594d57d0SMatthias Kaehlcke { 85*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 86*594d57d0SMatthias Kaehlcke int i; 87*594d57d0SMatthias Kaehlcke 88*594d57d0SMatthias Kaehlcke printf("\ndump_rx_status_queue()\n"); 89*594d57d0SMatthias Kaehlcke printf(" descriptor address word1 word2\n"); 90*594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) { 91*594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X %08X\n", 92*594d57d0SMatthias Kaehlcke priv->rx_sq.base + i, 93*594d57d0SMatthias Kaehlcke (priv->rx_sq.base + i)->word1, 94*594d57d0SMatthias Kaehlcke (priv->rx_sq.base + i)->word2); 95*594d57d0SMatthias Kaehlcke } 96*594d57d0SMatthias Kaehlcke } 97*594d57d0SMatthias Kaehlcke 98*594d57d0SMatthias Kaehlcke /** 99*594d57d0SMatthias Kaehlcke * Dump all RX descriptor queue entries to the terminal. 100*594d57d0SMatthias Kaehlcke */ 101*594d57d0SMatthias Kaehlcke static void dump_rx_descriptor_queue(struct eth_device *dev) 102*594d57d0SMatthias Kaehlcke { 103*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 104*594d57d0SMatthias Kaehlcke int i; 105*594d57d0SMatthias Kaehlcke 106*594d57d0SMatthias Kaehlcke printf("\ndump_rx_descriptor_queue()\n"); 107*594d57d0SMatthias Kaehlcke printf(" descriptor address word1 word2\n"); 108*594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) { 109*594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X %08X\n", 110*594d57d0SMatthias Kaehlcke priv->rx_dq.base + i, 111*594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word1, 112*594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word2); 113*594d57d0SMatthias Kaehlcke } 114*594d57d0SMatthias Kaehlcke } 115*594d57d0SMatthias Kaehlcke 116*594d57d0SMatthias Kaehlcke /** 117*594d57d0SMatthias Kaehlcke * Dump all TX descriptor queue entries to the terminal. 118*594d57d0SMatthias Kaehlcke */ 119*594d57d0SMatthias Kaehlcke static void dump_tx_descriptor_queue(struct eth_device *dev) 120*594d57d0SMatthias Kaehlcke { 121*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 122*594d57d0SMatthias Kaehlcke int i; 123*594d57d0SMatthias Kaehlcke 124*594d57d0SMatthias Kaehlcke printf("\ndump_tx_descriptor_queue()\n"); 125*594d57d0SMatthias Kaehlcke printf(" descriptor address word1 word2\n"); 126*594d57d0SMatthias Kaehlcke for (i = 0; i < NUMTXDESC; i++) { 127*594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X %08X\n", 128*594d57d0SMatthias Kaehlcke priv->tx_dq.base + i, 129*594d57d0SMatthias Kaehlcke (priv->tx_dq.base + i)->word1, 130*594d57d0SMatthias Kaehlcke (priv->tx_dq.base + i)->word2); 131*594d57d0SMatthias Kaehlcke } 132*594d57d0SMatthias Kaehlcke } 133*594d57d0SMatthias Kaehlcke 134*594d57d0SMatthias Kaehlcke /** 135*594d57d0SMatthias Kaehlcke * Dump all TX status queue entries to the terminal. 136*594d57d0SMatthias Kaehlcke */ 137*594d57d0SMatthias Kaehlcke static void dump_tx_status_queue(struct eth_device *dev) 138*594d57d0SMatthias Kaehlcke { 139*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 140*594d57d0SMatthias Kaehlcke int i; 141*594d57d0SMatthias Kaehlcke 142*594d57d0SMatthias Kaehlcke printf("\ndump_tx_status_queue()\n"); 143*594d57d0SMatthias Kaehlcke printf(" descriptor address word1\n"); 144*594d57d0SMatthias Kaehlcke for (i = 0; i < NUMTXDESC; i++) { 145*594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X\n", 146*594d57d0SMatthias Kaehlcke priv->rx_sq.base + i, 147*594d57d0SMatthias Kaehlcke (priv->rx_sq.base + i)->word1); 148*594d57d0SMatthias Kaehlcke } 149*594d57d0SMatthias Kaehlcke } 150*594d57d0SMatthias Kaehlcke #else 151*594d57d0SMatthias Kaehlcke #define dump_dev(x) 152*594d57d0SMatthias Kaehlcke #define dump_rx_descriptor_queue(x) 153*594d57d0SMatthias Kaehlcke #define dump_rx_status_queue(x) 154*594d57d0SMatthias Kaehlcke #define dump_tx_descriptor_queue(x) 155*594d57d0SMatthias Kaehlcke #define dump_tx_status_queue(x) 156*594d57d0SMatthias Kaehlcke #endif /* defined(EP93XX_MAC_DEBUG) */ 157*594d57d0SMatthias Kaehlcke 158*594d57d0SMatthias Kaehlcke /** 159*594d57d0SMatthias Kaehlcke * Reset the EP93xx MAC by twiddling the soft reset bit and spinning until 160*594d57d0SMatthias Kaehlcke * it's cleared. 161*594d57d0SMatthias Kaehlcke */ 162*594d57d0SMatthias Kaehlcke static void ep93xx_mac_reset(struct eth_device *dev) 163*594d57d0SMatthias Kaehlcke { 164*594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev); 165*594d57d0SMatthias Kaehlcke uint32_t value; 166*594d57d0SMatthias Kaehlcke 167*594d57d0SMatthias Kaehlcke debug("+ep93xx_mac_reset"); 168*594d57d0SMatthias Kaehlcke 169*594d57d0SMatthias Kaehlcke value = readl(&mac->selfctl); 170*594d57d0SMatthias Kaehlcke value |= SELFCTL_RESET; 171*594d57d0SMatthias Kaehlcke writel(value, &mac->selfctl); 172*594d57d0SMatthias Kaehlcke 173*594d57d0SMatthias Kaehlcke while (readl(&mac->selfctl) & SELFCTL_RESET) 174*594d57d0SMatthias Kaehlcke ; /* noop */ 175*594d57d0SMatthias Kaehlcke 176*594d57d0SMatthias Kaehlcke debug("-ep93xx_mac_reset"); 177*594d57d0SMatthias Kaehlcke } 178*594d57d0SMatthias Kaehlcke 179*594d57d0SMatthias Kaehlcke /* Eth device open */ 180*594d57d0SMatthias Kaehlcke static int ep93xx_eth_open(struct eth_device *dev, bd_t *bd) 181*594d57d0SMatthias Kaehlcke { 182*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 183*594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev); 184*594d57d0SMatthias Kaehlcke uchar *mac_addr = dev->enetaddr; 185*594d57d0SMatthias Kaehlcke int i; 186*594d57d0SMatthias Kaehlcke 187*594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_open"); 188*594d57d0SMatthias Kaehlcke 189*594d57d0SMatthias Kaehlcke /* Reset the MAC */ 190*594d57d0SMatthias Kaehlcke ep93xx_mac_reset(dev); 191*594d57d0SMatthias Kaehlcke 192*594d57d0SMatthias Kaehlcke /* Reset the descriptor queues' current and end address values */ 193*594d57d0SMatthias Kaehlcke priv->tx_dq.current = priv->tx_dq.base; 194*594d57d0SMatthias Kaehlcke priv->tx_dq.end = (priv->tx_dq.base + NUMTXDESC); 195*594d57d0SMatthias Kaehlcke 196*594d57d0SMatthias Kaehlcke priv->tx_sq.current = priv->tx_sq.base; 197*594d57d0SMatthias Kaehlcke priv->tx_sq.end = (priv->tx_sq.base + NUMTXDESC); 198*594d57d0SMatthias Kaehlcke 199*594d57d0SMatthias Kaehlcke priv->rx_dq.current = priv->rx_dq.base; 200*594d57d0SMatthias Kaehlcke priv->rx_dq.end = (priv->rx_dq.base + NUMRXDESC); 201*594d57d0SMatthias Kaehlcke 202*594d57d0SMatthias Kaehlcke priv->rx_sq.current = priv->rx_sq.base; 203*594d57d0SMatthias Kaehlcke priv->rx_sq.end = (priv->rx_sq.base + NUMRXDESC); 204*594d57d0SMatthias Kaehlcke 205*594d57d0SMatthias Kaehlcke /* 206*594d57d0SMatthias Kaehlcke * Set the transmit descriptor and status queues' base address, 207*594d57d0SMatthias Kaehlcke * current address, and length registers. Set the maximum frame 208*594d57d0SMatthias Kaehlcke * length and threshold. Enable the transmit descriptor processor. 209*594d57d0SMatthias Kaehlcke */ 210*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_dq.base, &mac->txdq.badd); 211*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_dq.base, &mac->txdq.curadd); 212*594d57d0SMatthias Kaehlcke writel(sizeof(struct tx_descriptor) * NUMTXDESC, &mac->txdq.blen); 213*594d57d0SMatthias Kaehlcke 214*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_sq.base, &mac->txstsq.badd); 215*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_sq.base, &mac->txstsq.curadd); 216*594d57d0SMatthias Kaehlcke writel(sizeof(struct tx_status) * NUMTXDESC, &mac->txstsq.blen); 217*594d57d0SMatthias Kaehlcke 218*594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->txdthrshld); 219*594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->txststhrshld); 220*594d57d0SMatthias Kaehlcke 221*594d57d0SMatthias Kaehlcke writel((TXSTARTMAX << 0) | (PKTSIZE_ALIGN << 16), &mac->maxfrmlen); 222*594d57d0SMatthias Kaehlcke writel(BMCTL_TXEN, &mac->bmctl); 223*594d57d0SMatthias Kaehlcke 224*594d57d0SMatthias Kaehlcke /* 225*594d57d0SMatthias Kaehlcke * Set the receive descriptor and status queues' base address, 226*594d57d0SMatthias Kaehlcke * current address, and length registers. Enable the receive 227*594d57d0SMatthias Kaehlcke * descriptor processor. 228*594d57d0SMatthias Kaehlcke */ 229*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_dq.base, &mac->rxdq.badd); 230*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_dq.base, &mac->rxdq.curadd); 231*594d57d0SMatthias Kaehlcke writel(sizeof(struct rx_descriptor) * NUMRXDESC, &mac->rxdq.blen); 232*594d57d0SMatthias Kaehlcke 233*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_sq.base, &mac->rxstsq.badd); 234*594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_sq.base, &mac->rxstsq.curadd); 235*594d57d0SMatthias Kaehlcke writel(sizeof(struct rx_status) * NUMRXDESC, &mac->rxstsq.blen); 236*594d57d0SMatthias Kaehlcke 237*594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->rxdthrshld); 238*594d57d0SMatthias Kaehlcke 239*594d57d0SMatthias Kaehlcke writel(BMCTL_RXEN, &mac->bmctl); 240*594d57d0SMatthias Kaehlcke 241*594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->rxststhrshld); 242*594d57d0SMatthias Kaehlcke 243*594d57d0SMatthias Kaehlcke /* Wait until the receive descriptor processor is active */ 244*594d57d0SMatthias Kaehlcke while (!(readl(&mac->bmsts) & BMSTS_RXACT)) 245*594d57d0SMatthias Kaehlcke ; /* noop */ 246*594d57d0SMatthias Kaehlcke 247*594d57d0SMatthias Kaehlcke /* 248*594d57d0SMatthias Kaehlcke * Initialize the RX descriptor queue. Clear the TX descriptor queue. 249*594d57d0SMatthias Kaehlcke * Clear the RX and TX status queues. Enqueue the RX descriptor and 250*594d57d0SMatthias Kaehlcke * status entries to the MAC. 251*594d57d0SMatthias Kaehlcke */ 252*594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) { 253*594d57d0SMatthias Kaehlcke /* set buffer address */ 254*594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word1 = (uint32_t)NetRxPackets[i]; 255*594d57d0SMatthias Kaehlcke 256*594d57d0SMatthias Kaehlcke /* set buffer length, clear buffer index and NSOF */ 257*594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word2 = PKTSIZE_ALIGN; 258*594d57d0SMatthias Kaehlcke } 259*594d57d0SMatthias Kaehlcke 260*594d57d0SMatthias Kaehlcke memset(priv->tx_dq.base, 0, 261*594d57d0SMatthias Kaehlcke (sizeof(struct tx_descriptor) * NUMTXDESC)); 262*594d57d0SMatthias Kaehlcke memset(priv->rx_sq.base, 0, 263*594d57d0SMatthias Kaehlcke (sizeof(struct rx_status) * NUMRXDESC)); 264*594d57d0SMatthias Kaehlcke memset(priv->tx_sq.base, 0, 265*594d57d0SMatthias Kaehlcke (sizeof(struct tx_status) * NUMTXDESC)); 266*594d57d0SMatthias Kaehlcke 267*594d57d0SMatthias Kaehlcke writel(NUMRXDESC, &mac->rxdqenq); 268*594d57d0SMatthias Kaehlcke writel(NUMRXDESC, &mac->rxstsqenq); 269*594d57d0SMatthias Kaehlcke 270*594d57d0SMatthias Kaehlcke /* Set the primary MAC address */ 271*594d57d0SMatthias Kaehlcke writel(AFP_IAPRIMARY, &mac->afp); 272*594d57d0SMatthias Kaehlcke writel(mac_addr[0] | (mac_addr[1] << 8) | 273*594d57d0SMatthias Kaehlcke (mac_addr[2] << 16) | (mac_addr[3] << 24), 274*594d57d0SMatthias Kaehlcke &mac->indad); 275*594d57d0SMatthias Kaehlcke writel(mac_addr[4] | (mac_addr[5] << 8), &mac->indad_upper); 276*594d57d0SMatthias Kaehlcke 277*594d57d0SMatthias Kaehlcke /* Turn on RX and TX */ 278*594d57d0SMatthias Kaehlcke writel(RXCTL_IA0 | RXCTL_BA | RXCTL_SRXON | 279*594d57d0SMatthias Kaehlcke RXCTL_RCRCA | RXCTL_MA, &mac->rxctl); 280*594d57d0SMatthias Kaehlcke writel(TXCTL_STXON, &mac->txctl); 281*594d57d0SMatthias Kaehlcke 282*594d57d0SMatthias Kaehlcke /* Dump data structures if we're debugging */ 283*594d57d0SMatthias Kaehlcke dump_dev(dev); 284*594d57d0SMatthias Kaehlcke dump_rx_descriptor_queue(dev); 285*594d57d0SMatthias Kaehlcke dump_rx_status_queue(dev); 286*594d57d0SMatthias Kaehlcke dump_tx_descriptor_queue(dev); 287*594d57d0SMatthias Kaehlcke dump_tx_status_queue(dev); 288*594d57d0SMatthias Kaehlcke 289*594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_open"); 290*594d57d0SMatthias Kaehlcke 291*594d57d0SMatthias Kaehlcke return 1; 292*594d57d0SMatthias Kaehlcke } 293*594d57d0SMatthias Kaehlcke 294*594d57d0SMatthias Kaehlcke /** 295*594d57d0SMatthias Kaehlcke * Halt EP93xx MAC transmit and receive by clearing the TxCTL and RxCTL 296*594d57d0SMatthias Kaehlcke * registers. 297*594d57d0SMatthias Kaehlcke */ 298*594d57d0SMatthias Kaehlcke static void ep93xx_eth_close(struct eth_device *dev) 299*594d57d0SMatthias Kaehlcke { 300*594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev); 301*594d57d0SMatthias Kaehlcke 302*594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_close"); 303*594d57d0SMatthias Kaehlcke 304*594d57d0SMatthias Kaehlcke writel(0x00000000, &mac->rxctl); 305*594d57d0SMatthias Kaehlcke writel(0x00000000, &mac->txctl); 306*594d57d0SMatthias Kaehlcke 307*594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_close"); 308*594d57d0SMatthias Kaehlcke } 309*594d57d0SMatthias Kaehlcke 310*594d57d0SMatthias Kaehlcke /** 311*594d57d0SMatthias Kaehlcke * Copy a frame of data from the MAC into the protocol layer for further 312*594d57d0SMatthias Kaehlcke * processing. 313*594d57d0SMatthias Kaehlcke */ 314*594d57d0SMatthias Kaehlcke static int ep93xx_eth_rcv_packet(struct eth_device *dev) 315*594d57d0SMatthias Kaehlcke { 316*594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev); 317*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 318*594d57d0SMatthias Kaehlcke int len = -1; 319*594d57d0SMatthias Kaehlcke 320*594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_rcv_packet"); 321*594d57d0SMatthias Kaehlcke 322*594d57d0SMatthias Kaehlcke if (RX_STATUS_RFP(priv->rx_sq.current)) { 323*594d57d0SMatthias Kaehlcke if (RX_STATUS_RWE(priv->rx_sq.current)) { 324*594d57d0SMatthias Kaehlcke /* 325*594d57d0SMatthias Kaehlcke * We have a good frame. Extract the frame's length 326*594d57d0SMatthias Kaehlcke * from the current rx_status_queue entry, and copy 327*594d57d0SMatthias Kaehlcke * the frame's data into NetRxPackets[] of the 328*594d57d0SMatthias Kaehlcke * protocol stack. We track the total number of 329*594d57d0SMatthias Kaehlcke * bytes in the frame (nbytes_frame) which will be 330*594d57d0SMatthias Kaehlcke * used when we pass the data off to the protocol 331*594d57d0SMatthias Kaehlcke * layer via NetReceive(). 332*594d57d0SMatthias Kaehlcke */ 333*594d57d0SMatthias Kaehlcke len = RX_STATUS_FRAME_LEN(priv->rx_sq.current); 334*594d57d0SMatthias Kaehlcke 335*594d57d0SMatthias Kaehlcke NetReceive((uchar *)priv->rx_dq.current->word1, len); 336*594d57d0SMatthias Kaehlcke 337*594d57d0SMatthias Kaehlcke debug("reporting %d bytes...\n", len); 338*594d57d0SMatthias Kaehlcke } else { 339*594d57d0SMatthias Kaehlcke /* Do we have an erroneous packet? */ 340*594d57d0SMatthias Kaehlcke error("packet rx error, status %08X %08X", 341*594d57d0SMatthias Kaehlcke priv->rx_sq.current->word1, 342*594d57d0SMatthias Kaehlcke priv->rx_sq.current->word2); 343*594d57d0SMatthias Kaehlcke dump_rx_descriptor_queue(dev); 344*594d57d0SMatthias Kaehlcke dump_rx_status_queue(dev); 345*594d57d0SMatthias Kaehlcke } 346*594d57d0SMatthias Kaehlcke 347*594d57d0SMatthias Kaehlcke /* 348*594d57d0SMatthias Kaehlcke * Clear the associated status queue entry, and 349*594d57d0SMatthias Kaehlcke * increment our current pointers to the next RX 350*594d57d0SMatthias Kaehlcke * descriptor and status queue entries (making sure 351*594d57d0SMatthias Kaehlcke * we wrap properly). 352*594d57d0SMatthias Kaehlcke */ 353*594d57d0SMatthias Kaehlcke memset((void *)priv->rx_sq.current, 0, 354*594d57d0SMatthias Kaehlcke sizeof(struct rx_status)); 355*594d57d0SMatthias Kaehlcke 356*594d57d0SMatthias Kaehlcke priv->rx_sq.current++; 357*594d57d0SMatthias Kaehlcke if (priv->rx_sq.current >= priv->rx_sq.end) 358*594d57d0SMatthias Kaehlcke priv->rx_sq.current = priv->rx_sq.base; 359*594d57d0SMatthias Kaehlcke 360*594d57d0SMatthias Kaehlcke priv->rx_dq.current++; 361*594d57d0SMatthias Kaehlcke if (priv->rx_dq.current >= priv->rx_dq.end) 362*594d57d0SMatthias Kaehlcke priv->rx_dq.current = priv->rx_dq.base; 363*594d57d0SMatthias Kaehlcke 364*594d57d0SMatthias Kaehlcke /* 365*594d57d0SMatthias Kaehlcke * Finally, return the RX descriptor and status entries 366*594d57d0SMatthias Kaehlcke * back to the MAC engine, and loop again, checking for 367*594d57d0SMatthias Kaehlcke * more descriptors to process. 368*594d57d0SMatthias Kaehlcke */ 369*594d57d0SMatthias Kaehlcke writel(1, &mac->rxdqenq); 370*594d57d0SMatthias Kaehlcke writel(1, &mac->rxstsqenq); 371*594d57d0SMatthias Kaehlcke } else { 372*594d57d0SMatthias Kaehlcke len = 0; 373*594d57d0SMatthias Kaehlcke } 374*594d57d0SMatthias Kaehlcke 375*594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_rcv_packet %d", len); 376*594d57d0SMatthias Kaehlcke return len; 377*594d57d0SMatthias Kaehlcke } 378*594d57d0SMatthias Kaehlcke 379*594d57d0SMatthias Kaehlcke /** 380*594d57d0SMatthias Kaehlcke * Send a block of data via ethernet. 381*594d57d0SMatthias Kaehlcke */ 382*594d57d0SMatthias Kaehlcke static int ep93xx_eth_send_packet(struct eth_device *dev, 383*594d57d0SMatthias Kaehlcke volatile void * const packet, int const length) 384*594d57d0SMatthias Kaehlcke { 385*594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev); 386*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev); 387*594d57d0SMatthias Kaehlcke int ret = -1; 388*594d57d0SMatthias Kaehlcke 389*594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_send_packet"); 390*594d57d0SMatthias Kaehlcke 391*594d57d0SMatthias Kaehlcke /* Parameter check */ 392*594d57d0SMatthias Kaehlcke BUG_ON(packet == NULL); 393*594d57d0SMatthias Kaehlcke 394*594d57d0SMatthias Kaehlcke /* 395*594d57d0SMatthias Kaehlcke * Initialize the TX descriptor queue with the new packet's info. 396*594d57d0SMatthias Kaehlcke * Clear the associated status queue entry. Enqueue the packet 397*594d57d0SMatthias Kaehlcke * to the MAC for transmission. 398*594d57d0SMatthias Kaehlcke */ 399*594d57d0SMatthias Kaehlcke 400*594d57d0SMatthias Kaehlcke /* set buffer address */ 401*594d57d0SMatthias Kaehlcke priv->tx_dq.current->word1 = (uint32_t)packet; 402*594d57d0SMatthias Kaehlcke 403*594d57d0SMatthias Kaehlcke /* set buffer length and EOF bit */ 404*594d57d0SMatthias Kaehlcke priv->tx_dq.current->word2 = length | TX_DESC_EOF; 405*594d57d0SMatthias Kaehlcke 406*594d57d0SMatthias Kaehlcke /* clear tx status */ 407*594d57d0SMatthias Kaehlcke priv->tx_sq.current->word1 = 0; 408*594d57d0SMatthias Kaehlcke 409*594d57d0SMatthias Kaehlcke /* enqueue the TX descriptor */ 410*594d57d0SMatthias Kaehlcke writel(1, &mac->txdqenq); 411*594d57d0SMatthias Kaehlcke 412*594d57d0SMatthias Kaehlcke /* wait for the frame to become processed */ 413*594d57d0SMatthias Kaehlcke while (!TX_STATUS_TXFP(priv->tx_sq.current)) 414*594d57d0SMatthias Kaehlcke ; /* noop */ 415*594d57d0SMatthias Kaehlcke 416*594d57d0SMatthias Kaehlcke if (!TX_STATUS_TXWE(priv->tx_sq.current)) { 417*594d57d0SMatthias Kaehlcke error("packet tx error, status %08X", 418*594d57d0SMatthias Kaehlcke priv->tx_sq.current->word1); 419*594d57d0SMatthias Kaehlcke dump_tx_descriptor_queue(dev); 420*594d57d0SMatthias Kaehlcke dump_tx_status_queue(dev); 421*594d57d0SMatthias Kaehlcke 422*594d57d0SMatthias Kaehlcke /* TODO: Add better error handling? */ 423*594d57d0SMatthias Kaehlcke goto eth_send_out; 424*594d57d0SMatthias Kaehlcke } 425*594d57d0SMatthias Kaehlcke 426*594d57d0SMatthias Kaehlcke ret = 0; 427*594d57d0SMatthias Kaehlcke /* Fall through */ 428*594d57d0SMatthias Kaehlcke 429*594d57d0SMatthias Kaehlcke eth_send_out: 430*594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_send_packet %d", ret); 431*594d57d0SMatthias Kaehlcke return ret; 432*594d57d0SMatthias Kaehlcke } 433*594d57d0SMatthias Kaehlcke 434*594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII) 435*594d57d0SMatthias Kaehlcke int ep93xx_miiphy_initialize(bd_t * const bd) 436*594d57d0SMatthias Kaehlcke { 437*594d57d0SMatthias Kaehlcke miiphy_register("ep93xx_eth0", ep93xx_miiphy_read, ep93xx_miiphy_write); 438*594d57d0SMatthias Kaehlcke return 0; 439*594d57d0SMatthias Kaehlcke } 440*594d57d0SMatthias Kaehlcke #endif 441*594d57d0SMatthias Kaehlcke 442*594d57d0SMatthias Kaehlcke /** 443*594d57d0SMatthias Kaehlcke * Initialize the EP93xx MAC. The MAC hardware is reset. Buffers are 444*594d57d0SMatthias Kaehlcke * allocated, if necessary, for the TX and RX descriptor and status queues, 445*594d57d0SMatthias Kaehlcke * as well as for received packets. The EP93XX MAC hardware is initialized. 446*594d57d0SMatthias Kaehlcke * Transmit and receive operations are enabled. 447*594d57d0SMatthias Kaehlcke */ 448*594d57d0SMatthias Kaehlcke int ep93xx_eth_initialize(u8 dev_num, int base_addr) 449*594d57d0SMatthias Kaehlcke { 450*594d57d0SMatthias Kaehlcke int ret = -1; 451*594d57d0SMatthias Kaehlcke struct eth_device *dev; 452*594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv; 453*594d57d0SMatthias Kaehlcke 454*594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_initialize"); 455*594d57d0SMatthias Kaehlcke 456*594d57d0SMatthias Kaehlcke priv = malloc(sizeof(*priv)); 457*594d57d0SMatthias Kaehlcke if (!priv) { 458*594d57d0SMatthias Kaehlcke error("malloc() failed"); 459*594d57d0SMatthias Kaehlcke goto eth_init_failed_0; 460*594d57d0SMatthias Kaehlcke } 461*594d57d0SMatthias Kaehlcke memset(priv, 0, sizeof(*priv)); 462*594d57d0SMatthias Kaehlcke 463*594d57d0SMatthias Kaehlcke priv->regs = (struct mac_regs *)base_addr; 464*594d57d0SMatthias Kaehlcke 465*594d57d0SMatthias Kaehlcke priv->tx_dq.base = calloc(NUMTXDESC, 466*594d57d0SMatthias Kaehlcke sizeof(struct tx_descriptor)); 467*594d57d0SMatthias Kaehlcke if (priv->tx_dq.base == NULL) { 468*594d57d0SMatthias Kaehlcke error("calloc() failed"); 469*594d57d0SMatthias Kaehlcke goto eth_init_failed_1; 470*594d57d0SMatthias Kaehlcke } 471*594d57d0SMatthias Kaehlcke 472*594d57d0SMatthias Kaehlcke priv->tx_sq.base = calloc(NUMTXDESC, 473*594d57d0SMatthias Kaehlcke sizeof(struct tx_status)); 474*594d57d0SMatthias Kaehlcke if (priv->tx_sq.base == NULL) { 475*594d57d0SMatthias Kaehlcke error("calloc() failed"); 476*594d57d0SMatthias Kaehlcke goto eth_init_failed_2; 477*594d57d0SMatthias Kaehlcke } 478*594d57d0SMatthias Kaehlcke 479*594d57d0SMatthias Kaehlcke priv->rx_dq.base = calloc(NUMRXDESC, 480*594d57d0SMatthias Kaehlcke sizeof(struct rx_descriptor)); 481*594d57d0SMatthias Kaehlcke if (priv->rx_dq.base == NULL) { 482*594d57d0SMatthias Kaehlcke error("calloc() failed"); 483*594d57d0SMatthias Kaehlcke goto eth_init_failed_3; 484*594d57d0SMatthias Kaehlcke } 485*594d57d0SMatthias Kaehlcke 486*594d57d0SMatthias Kaehlcke priv->rx_sq.base = calloc(NUMRXDESC, 487*594d57d0SMatthias Kaehlcke sizeof(struct rx_status)); 488*594d57d0SMatthias Kaehlcke if (priv->rx_sq.base == NULL) { 489*594d57d0SMatthias Kaehlcke error("calloc() failed"); 490*594d57d0SMatthias Kaehlcke goto eth_init_failed_4; 491*594d57d0SMatthias Kaehlcke } 492*594d57d0SMatthias Kaehlcke 493*594d57d0SMatthias Kaehlcke dev = malloc(sizeof *dev); 494*594d57d0SMatthias Kaehlcke if (dev == NULL) { 495*594d57d0SMatthias Kaehlcke error("malloc() failed"); 496*594d57d0SMatthias Kaehlcke goto eth_init_failed_5; 497*594d57d0SMatthias Kaehlcke } 498*594d57d0SMatthias Kaehlcke memset(dev, 0, sizeof *dev); 499*594d57d0SMatthias Kaehlcke 500*594d57d0SMatthias Kaehlcke dev->iobase = base_addr; 501*594d57d0SMatthias Kaehlcke dev->priv = priv; 502*594d57d0SMatthias Kaehlcke dev->init = ep93xx_eth_open; 503*594d57d0SMatthias Kaehlcke dev->halt = ep93xx_eth_close; 504*594d57d0SMatthias Kaehlcke dev->send = ep93xx_eth_send_packet; 505*594d57d0SMatthias Kaehlcke dev->recv = ep93xx_eth_rcv_packet; 506*594d57d0SMatthias Kaehlcke 507*594d57d0SMatthias Kaehlcke sprintf(dev->name, "ep93xx_eth-%hu", dev_num); 508*594d57d0SMatthias Kaehlcke 509*594d57d0SMatthias Kaehlcke eth_register(dev); 510*594d57d0SMatthias Kaehlcke 511*594d57d0SMatthias Kaehlcke /* Done! */ 512*594d57d0SMatthias Kaehlcke ret = 1; 513*594d57d0SMatthias Kaehlcke goto eth_init_done; 514*594d57d0SMatthias Kaehlcke 515*594d57d0SMatthias Kaehlcke eth_init_failed_5: 516*594d57d0SMatthias Kaehlcke free(priv->rx_sq.base); 517*594d57d0SMatthias Kaehlcke /* Fall through */ 518*594d57d0SMatthias Kaehlcke 519*594d57d0SMatthias Kaehlcke eth_init_failed_4: 520*594d57d0SMatthias Kaehlcke free(priv->rx_dq.base); 521*594d57d0SMatthias Kaehlcke /* Fall through */ 522*594d57d0SMatthias Kaehlcke 523*594d57d0SMatthias Kaehlcke eth_init_failed_3: 524*594d57d0SMatthias Kaehlcke free(priv->tx_sq.base); 525*594d57d0SMatthias Kaehlcke /* Fall through */ 526*594d57d0SMatthias Kaehlcke 527*594d57d0SMatthias Kaehlcke eth_init_failed_2: 528*594d57d0SMatthias Kaehlcke free(priv->tx_dq.base); 529*594d57d0SMatthias Kaehlcke /* Fall through */ 530*594d57d0SMatthias Kaehlcke 531*594d57d0SMatthias Kaehlcke eth_init_failed_1: 532*594d57d0SMatthias Kaehlcke free(priv); 533*594d57d0SMatthias Kaehlcke /* Fall through */ 534*594d57d0SMatthias Kaehlcke 535*594d57d0SMatthias Kaehlcke eth_init_failed_0: 536*594d57d0SMatthias Kaehlcke /* Fall through */ 537*594d57d0SMatthias Kaehlcke 538*594d57d0SMatthias Kaehlcke eth_init_done: 539*594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_initialize %d", ret); 540*594d57d0SMatthias Kaehlcke return ret; 541*594d57d0SMatthias Kaehlcke } 542*594d57d0SMatthias Kaehlcke 543*594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII) 544*594d57d0SMatthias Kaehlcke 545*594d57d0SMatthias Kaehlcke /** 546*594d57d0SMatthias Kaehlcke * Maximum MII address we support 547*594d57d0SMatthias Kaehlcke */ 548*594d57d0SMatthias Kaehlcke #define MII_ADDRESS_MAX 31 549*594d57d0SMatthias Kaehlcke 550*594d57d0SMatthias Kaehlcke /** 551*594d57d0SMatthias Kaehlcke * Maximum MII register address we support 552*594d57d0SMatthias Kaehlcke */ 553*594d57d0SMatthias Kaehlcke #define MII_REGISTER_MAX 31 554*594d57d0SMatthias Kaehlcke 555*594d57d0SMatthias Kaehlcke /** 556*594d57d0SMatthias Kaehlcke * Read a 16-bit value from an MII register. 557*594d57d0SMatthias Kaehlcke */ 558*594d57d0SMatthias Kaehlcke static int ep93xx_miiphy_read(char * const dev, unsigned char const addr, 559*594d57d0SMatthias Kaehlcke unsigned char const reg, unsigned short * const value) 560*594d57d0SMatthias Kaehlcke { 561*594d57d0SMatthias Kaehlcke struct mac_regs *mac = (struct mac_regs *)MAC_BASE; 562*594d57d0SMatthias Kaehlcke int ret = -1; 563*594d57d0SMatthias Kaehlcke uint32_t self_ctl; 564*594d57d0SMatthias Kaehlcke 565*594d57d0SMatthias Kaehlcke debug("+ep93xx_miiphy_read"); 566*594d57d0SMatthias Kaehlcke 567*594d57d0SMatthias Kaehlcke /* Parameter checks */ 568*594d57d0SMatthias Kaehlcke BUG_ON(dev == NULL); 569*594d57d0SMatthias Kaehlcke BUG_ON(addr > MII_ADDRESS_MAX); 570*594d57d0SMatthias Kaehlcke BUG_ON(reg > MII_REGISTER_MAX); 571*594d57d0SMatthias Kaehlcke BUG_ON(value == NULL); 572*594d57d0SMatthias Kaehlcke 573*594d57d0SMatthias Kaehlcke /* 574*594d57d0SMatthias Kaehlcke * Save the current SelfCTL register value. Set MAC to suppress 575*594d57d0SMatthias Kaehlcke * preamble bits. Wait for any previous MII command to complete 576*594d57d0SMatthias Kaehlcke * before issuing the new command. 577*594d57d0SMatthias Kaehlcke */ 578*594d57d0SMatthias Kaehlcke self_ctl = readl(&mac->selfctl); 579*594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII_SUPPRESS_PREAMBLE) 580*594d57d0SMatthias Kaehlcke writel(self_ctl & ~(1 << 8), &mac->selfctl); 581*594d57d0SMatthias Kaehlcke #endif /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */ 582*594d57d0SMatthias Kaehlcke 583*594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY) 584*594d57d0SMatthias Kaehlcke ; /* noop */ 585*594d57d0SMatthias Kaehlcke 586*594d57d0SMatthias Kaehlcke /* 587*594d57d0SMatthias Kaehlcke * Issue the MII 'read' command. Wait for the command to complete. 588*594d57d0SMatthias Kaehlcke * Read the MII data value. 589*594d57d0SMatthias Kaehlcke */ 590*594d57d0SMatthias Kaehlcke writel(MIICMD_OPCODE_READ | ((uint32_t)addr << 5) | (uint32_t)reg, 591*594d57d0SMatthias Kaehlcke &mac->miicmd); 592*594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY) 593*594d57d0SMatthias Kaehlcke ; /* noop */ 594*594d57d0SMatthias Kaehlcke 595*594d57d0SMatthias Kaehlcke *value = (unsigned short)readl(&mac->miidata); 596*594d57d0SMatthias Kaehlcke 597*594d57d0SMatthias Kaehlcke /* Restore the saved SelfCTL value and return. */ 598*594d57d0SMatthias Kaehlcke writel(self_ctl, &mac->selfctl); 599*594d57d0SMatthias Kaehlcke 600*594d57d0SMatthias Kaehlcke ret = 0; 601*594d57d0SMatthias Kaehlcke /* Fall through */ 602*594d57d0SMatthias Kaehlcke 603*594d57d0SMatthias Kaehlcke debug("-ep93xx_miiphy_read"); 604*594d57d0SMatthias Kaehlcke return ret; 605*594d57d0SMatthias Kaehlcke } 606*594d57d0SMatthias Kaehlcke 607*594d57d0SMatthias Kaehlcke /** 608*594d57d0SMatthias Kaehlcke * Write a 16-bit value to an MII register. 609*594d57d0SMatthias Kaehlcke */ 610*594d57d0SMatthias Kaehlcke static int ep93xx_miiphy_write(char * const dev, unsigned char const addr, 611*594d57d0SMatthias Kaehlcke unsigned char const reg, unsigned short const value) 612*594d57d0SMatthias Kaehlcke { 613*594d57d0SMatthias Kaehlcke struct mac_regs *mac = (struct mac_regs *)MAC_BASE; 614*594d57d0SMatthias Kaehlcke int ret = -1; 615*594d57d0SMatthias Kaehlcke uint32_t self_ctl; 616*594d57d0SMatthias Kaehlcke 617*594d57d0SMatthias Kaehlcke debug("+ep93xx_miiphy_write"); 618*594d57d0SMatthias Kaehlcke 619*594d57d0SMatthias Kaehlcke /* Parameter checks */ 620*594d57d0SMatthias Kaehlcke BUG_ON(dev == NULL); 621*594d57d0SMatthias Kaehlcke BUG_ON(addr > MII_ADDRESS_MAX); 622*594d57d0SMatthias Kaehlcke BUG_ON(reg > MII_REGISTER_MAX); 623*594d57d0SMatthias Kaehlcke 624*594d57d0SMatthias Kaehlcke /* 625*594d57d0SMatthias Kaehlcke * Save the current SelfCTL register value. Set MAC to suppress 626*594d57d0SMatthias Kaehlcke * preamble bits. Wait for any previous MII command to complete 627*594d57d0SMatthias Kaehlcke * before issuing the new command. 628*594d57d0SMatthias Kaehlcke */ 629*594d57d0SMatthias Kaehlcke self_ctl = readl(&mac->selfctl); 630*594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII_SUPPRESS_PREAMBLE) 631*594d57d0SMatthias Kaehlcke writel(self_ctl & ~(1 << 8), &mac->selfctl); 632*594d57d0SMatthias Kaehlcke #endif /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */ 633*594d57d0SMatthias Kaehlcke 634*594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY) 635*594d57d0SMatthias Kaehlcke ; /* noop */ 636*594d57d0SMatthias Kaehlcke 637*594d57d0SMatthias Kaehlcke /* Issue the MII 'write' command. Wait for the command to complete. */ 638*594d57d0SMatthias Kaehlcke writel((uint32_t)value, &mac->miidata); 639*594d57d0SMatthias Kaehlcke writel(MIICMD_OPCODE_WRITE | ((uint32_t)addr << 5) | (uint32_t)reg, 640*594d57d0SMatthias Kaehlcke &mac->miicmd); 641*594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY) 642*594d57d0SMatthias Kaehlcke ; /* noop */ 643*594d57d0SMatthias Kaehlcke 644*594d57d0SMatthias Kaehlcke /* Restore the saved SelfCTL value and return. */ 645*594d57d0SMatthias Kaehlcke writel(self_ctl, &mac->selfctl); 646*594d57d0SMatthias Kaehlcke 647*594d57d0SMatthias Kaehlcke ret = 0; 648*594d57d0SMatthias Kaehlcke /* Fall through */ 649*594d57d0SMatthias Kaehlcke 650*594d57d0SMatthias Kaehlcke debug("-ep93xx_miiphy_write"); 651*594d57d0SMatthias Kaehlcke return ret; 652*594d57d0SMatthias Kaehlcke } 653*594d57d0SMatthias Kaehlcke #endif /* defined(CONFIG_MII) */ 654