1594d57d0SMatthias Kaehlcke /*
2594d57d0SMatthias Kaehlcke * Cirrus Logic EP93xx ethernet MAC / MII driver.
3594d57d0SMatthias Kaehlcke *
4594d57d0SMatthias Kaehlcke * Copyright (C) 2010, 2009
5594d57d0SMatthias Kaehlcke * Matthias Kaehlcke <matthias@kaehlcke.net>
6594d57d0SMatthias Kaehlcke *
7594d57d0SMatthias Kaehlcke * Copyright (C) 2004, 2005
8594d57d0SMatthias Kaehlcke * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
9594d57d0SMatthias Kaehlcke *
10594d57d0SMatthias Kaehlcke * Based on the original eth.[ch] Cirrus Logic EP93xx Rev D. Ethernet Driver,
11594d57d0SMatthias Kaehlcke * which is
12594d57d0SMatthias Kaehlcke *
13594d57d0SMatthias Kaehlcke * (C) Copyright 2002 2003
14594d57d0SMatthias Kaehlcke * Adam Bezanson, Network Audio Technologies, Inc.
15594d57d0SMatthias Kaehlcke * <bezanson@netaudiotech.com>
16594d57d0SMatthias Kaehlcke *
171a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
18594d57d0SMatthias Kaehlcke */
19594d57d0SMatthias Kaehlcke
20594d57d0SMatthias Kaehlcke #include <command.h>
21594d57d0SMatthias Kaehlcke #include <common.h>
22594d57d0SMatthias Kaehlcke #include <asm/arch/ep93xx.h>
23594d57d0SMatthias Kaehlcke #include <asm/io.h>
24594d57d0SMatthias Kaehlcke #include <malloc.h>
25594d57d0SMatthias Kaehlcke #include <miiphy.h>
26594d57d0SMatthias Kaehlcke #include <linux/types.h>
27594d57d0SMatthias Kaehlcke #include "ep93xx_eth.h"
28594d57d0SMatthias Kaehlcke
29594d57d0SMatthias Kaehlcke #define GET_PRIV(eth_dev) ((struct ep93xx_priv *)(eth_dev)->priv)
30594d57d0SMatthias Kaehlcke #define GET_REGS(eth_dev) (GET_PRIV(eth_dev)->regs)
31594d57d0SMatthias Kaehlcke
32594d57d0SMatthias Kaehlcke /* ep93xx_miiphy ops forward declarations */
335a49f174SJoe Hershberger static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
345a49f174SJoe Hershberger int reg);
355a49f174SJoe Hershberger static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
365a49f174SJoe Hershberger int reg, u16 value);
37594d57d0SMatthias Kaehlcke
38594d57d0SMatthias Kaehlcke #if defined(EP93XX_MAC_DEBUG)
39594d57d0SMatthias Kaehlcke /**
40594d57d0SMatthias Kaehlcke * Dump ep93xx_mac values to the terminal.
41594d57d0SMatthias Kaehlcke */
dump_dev(struct eth_device * dev)42594d57d0SMatthias Kaehlcke static void dump_dev(struct eth_device *dev)
43594d57d0SMatthias Kaehlcke {
44594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
45594d57d0SMatthias Kaehlcke int i;
46594d57d0SMatthias Kaehlcke
47594d57d0SMatthias Kaehlcke printf("\ndump_dev()\n");
48594d57d0SMatthias Kaehlcke printf(" rx_dq.base %p\n", priv->rx_dq.base);
49594d57d0SMatthias Kaehlcke printf(" rx_dq.current %p\n", priv->rx_dq.current);
50594d57d0SMatthias Kaehlcke printf(" rx_dq.end %p\n", priv->rx_dq.end);
51594d57d0SMatthias Kaehlcke printf(" rx_sq.base %p\n", priv->rx_sq.base);
52594d57d0SMatthias Kaehlcke printf(" rx_sq.current %p\n", priv->rx_sq.current);
53594d57d0SMatthias Kaehlcke printf(" rx_sq.end %p\n", priv->rx_sq.end);
54594d57d0SMatthias Kaehlcke
55594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++)
561fd92db8SJoe Hershberger printf(" rx_buffer[%2.d] %p\n", i, net_rx_packets[i]);
57594d57d0SMatthias Kaehlcke
58594d57d0SMatthias Kaehlcke printf(" tx_dq.base %p\n", priv->tx_dq.base);
59594d57d0SMatthias Kaehlcke printf(" tx_dq.current %p\n", priv->tx_dq.current);
60594d57d0SMatthias Kaehlcke printf(" tx_dq.end %p\n", priv->tx_dq.end);
61594d57d0SMatthias Kaehlcke printf(" tx_sq.base %p\n", priv->tx_sq.base);
62594d57d0SMatthias Kaehlcke printf(" tx_sq.current %p\n", priv->tx_sq.current);
63594d57d0SMatthias Kaehlcke printf(" tx_sq.end %p\n", priv->tx_sq.end);
64594d57d0SMatthias Kaehlcke }
65594d57d0SMatthias Kaehlcke
66594d57d0SMatthias Kaehlcke /**
67594d57d0SMatthias Kaehlcke * Dump all RX status queue entries to the terminal.
68594d57d0SMatthias Kaehlcke */
dump_rx_status_queue(struct eth_device * dev)69594d57d0SMatthias Kaehlcke static void dump_rx_status_queue(struct eth_device *dev)
70594d57d0SMatthias Kaehlcke {
71594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
72594d57d0SMatthias Kaehlcke int i;
73594d57d0SMatthias Kaehlcke
74594d57d0SMatthias Kaehlcke printf("\ndump_rx_status_queue()\n");
75594d57d0SMatthias Kaehlcke printf(" descriptor address word1 word2\n");
76594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) {
77594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X %08X\n",
78594d57d0SMatthias Kaehlcke priv->rx_sq.base + i,
79594d57d0SMatthias Kaehlcke (priv->rx_sq.base + i)->word1,
80594d57d0SMatthias Kaehlcke (priv->rx_sq.base + i)->word2);
81594d57d0SMatthias Kaehlcke }
82594d57d0SMatthias Kaehlcke }
83594d57d0SMatthias Kaehlcke
84594d57d0SMatthias Kaehlcke /**
85594d57d0SMatthias Kaehlcke * Dump all RX descriptor queue entries to the terminal.
86594d57d0SMatthias Kaehlcke */
dump_rx_descriptor_queue(struct eth_device * dev)87594d57d0SMatthias Kaehlcke static void dump_rx_descriptor_queue(struct eth_device *dev)
88594d57d0SMatthias Kaehlcke {
89594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
90594d57d0SMatthias Kaehlcke int i;
91594d57d0SMatthias Kaehlcke
92594d57d0SMatthias Kaehlcke printf("\ndump_rx_descriptor_queue()\n");
93594d57d0SMatthias Kaehlcke printf(" descriptor address word1 word2\n");
94594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) {
95594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X %08X\n",
96594d57d0SMatthias Kaehlcke priv->rx_dq.base + i,
97594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word1,
98594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word2);
99594d57d0SMatthias Kaehlcke }
100594d57d0SMatthias Kaehlcke }
101594d57d0SMatthias Kaehlcke
102594d57d0SMatthias Kaehlcke /**
103594d57d0SMatthias Kaehlcke * Dump all TX descriptor queue entries to the terminal.
104594d57d0SMatthias Kaehlcke */
dump_tx_descriptor_queue(struct eth_device * dev)105594d57d0SMatthias Kaehlcke static void dump_tx_descriptor_queue(struct eth_device *dev)
106594d57d0SMatthias Kaehlcke {
107594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
108594d57d0SMatthias Kaehlcke int i;
109594d57d0SMatthias Kaehlcke
110594d57d0SMatthias Kaehlcke printf("\ndump_tx_descriptor_queue()\n");
111594d57d0SMatthias Kaehlcke printf(" descriptor address word1 word2\n");
112594d57d0SMatthias Kaehlcke for (i = 0; i < NUMTXDESC; i++) {
113594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X %08X\n",
114594d57d0SMatthias Kaehlcke priv->tx_dq.base + i,
115594d57d0SMatthias Kaehlcke (priv->tx_dq.base + i)->word1,
116594d57d0SMatthias Kaehlcke (priv->tx_dq.base + i)->word2);
117594d57d0SMatthias Kaehlcke }
118594d57d0SMatthias Kaehlcke }
119594d57d0SMatthias Kaehlcke
120594d57d0SMatthias Kaehlcke /**
121594d57d0SMatthias Kaehlcke * Dump all TX status queue entries to the terminal.
122594d57d0SMatthias Kaehlcke */
dump_tx_status_queue(struct eth_device * dev)123594d57d0SMatthias Kaehlcke static void dump_tx_status_queue(struct eth_device *dev)
124594d57d0SMatthias Kaehlcke {
125594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
126594d57d0SMatthias Kaehlcke int i;
127594d57d0SMatthias Kaehlcke
128594d57d0SMatthias Kaehlcke printf("\ndump_tx_status_queue()\n");
129594d57d0SMatthias Kaehlcke printf(" descriptor address word1\n");
130594d57d0SMatthias Kaehlcke for (i = 0; i < NUMTXDESC; i++) {
131594d57d0SMatthias Kaehlcke printf(" [ %p ] %08X\n",
132594d57d0SMatthias Kaehlcke priv->rx_sq.base + i,
133594d57d0SMatthias Kaehlcke (priv->rx_sq.base + i)->word1);
134594d57d0SMatthias Kaehlcke }
135594d57d0SMatthias Kaehlcke }
136594d57d0SMatthias Kaehlcke #else
137594d57d0SMatthias Kaehlcke #define dump_dev(x)
138594d57d0SMatthias Kaehlcke #define dump_rx_descriptor_queue(x)
139594d57d0SMatthias Kaehlcke #define dump_rx_status_queue(x)
140594d57d0SMatthias Kaehlcke #define dump_tx_descriptor_queue(x)
141594d57d0SMatthias Kaehlcke #define dump_tx_status_queue(x)
142594d57d0SMatthias Kaehlcke #endif /* defined(EP93XX_MAC_DEBUG) */
143594d57d0SMatthias Kaehlcke
144594d57d0SMatthias Kaehlcke /**
145594d57d0SMatthias Kaehlcke * Reset the EP93xx MAC by twiddling the soft reset bit and spinning until
146594d57d0SMatthias Kaehlcke * it's cleared.
147594d57d0SMatthias Kaehlcke */
ep93xx_mac_reset(struct eth_device * dev)148594d57d0SMatthias Kaehlcke static void ep93xx_mac_reset(struct eth_device *dev)
149594d57d0SMatthias Kaehlcke {
150594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev);
151594d57d0SMatthias Kaehlcke uint32_t value;
152594d57d0SMatthias Kaehlcke
153594d57d0SMatthias Kaehlcke debug("+ep93xx_mac_reset");
154594d57d0SMatthias Kaehlcke
155594d57d0SMatthias Kaehlcke value = readl(&mac->selfctl);
156594d57d0SMatthias Kaehlcke value |= SELFCTL_RESET;
157594d57d0SMatthias Kaehlcke writel(value, &mac->selfctl);
158594d57d0SMatthias Kaehlcke
159594d57d0SMatthias Kaehlcke while (readl(&mac->selfctl) & SELFCTL_RESET)
160594d57d0SMatthias Kaehlcke ; /* noop */
161594d57d0SMatthias Kaehlcke
162594d57d0SMatthias Kaehlcke debug("-ep93xx_mac_reset");
163594d57d0SMatthias Kaehlcke }
164594d57d0SMatthias Kaehlcke
165594d57d0SMatthias Kaehlcke /* Eth device open */
ep93xx_eth_open(struct eth_device * dev,bd_t * bd)166594d57d0SMatthias Kaehlcke static int ep93xx_eth_open(struct eth_device *dev, bd_t *bd)
167594d57d0SMatthias Kaehlcke {
168594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
169594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev);
170594d57d0SMatthias Kaehlcke uchar *mac_addr = dev->enetaddr;
171594d57d0SMatthias Kaehlcke int i;
172594d57d0SMatthias Kaehlcke
173594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_open");
174594d57d0SMatthias Kaehlcke
175594d57d0SMatthias Kaehlcke /* Reset the MAC */
176594d57d0SMatthias Kaehlcke ep93xx_mac_reset(dev);
177594d57d0SMatthias Kaehlcke
178594d57d0SMatthias Kaehlcke /* Reset the descriptor queues' current and end address values */
179594d57d0SMatthias Kaehlcke priv->tx_dq.current = priv->tx_dq.base;
180594d57d0SMatthias Kaehlcke priv->tx_dq.end = (priv->tx_dq.base + NUMTXDESC);
181594d57d0SMatthias Kaehlcke
182594d57d0SMatthias Kaehlcke priv->tx_sq.current = priv->tx_sq.base;
183594d57d0SMatthias Kaehlcke priv->tx_sq.end = (priv->tx_sq.base + NUMTXDESC);
184594d57d0SMatthias Kaehlcke
185594d57d0SMatthias Kaehlcke priv->rx_dq.current = priv->rx_dq.base;
186594d57d0SMatthias Kaehlcke priv->rx_dq.end = (priv->rx_dq.base + NUMRXDESC);
187594d57d0SMatthias Kaehlcke
188594d57d0SMatthias Kaehlcke priv->rx_sq.current = priv->rx_sq.base;
189594d57d0SMatthias Kaehlcke priv->rx_sq.end = (priv->rx_sq.base + NUMRXDESC);
190594d57d0SMatthias Kaehlcke
191594d57d0SMatthias Kaehlcke /*
192594d57d0SMatthias Kaehlcke * Set the transmit descriptor and status queues' base address,
193594d57d0SMatthias Kaehlcke * current address, and length registers. Set the maximum frame
194594d57d0SMatthias Kaehlcke * length and threshold. Enable the transmit descriptor processor.
195594d57d0SMatthias Kaehlcke */
196594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_dq.base, &mac->txdq.badd);
197594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_dq.base, &mac->txdq.curadd);
198594d57d0SMatthias Kaehlcke writel(sizeof(struct tx_descriptor) * NUMTXDESC, &mac->txdq.blen);
199594d57d0SMatthias Kaehlcke
200594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_sq.base, &mac->txstsq.badd);
201594d57d0SMatthias Kaehlcke writel((uint32_t)priv->tx_sq.base, &mac->txstsq.curadd);
202594d57d0SMatthias Kaehlcke writel(sizeof(struct tx_status) * NUMTXDESC, &mac->txstsq.blen);
203594d57d0SMatthias Kaehlcke
204594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->txdthrshld);
205594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->txststhrshld);
206594d57d0SMatthias Kaehlcke
207594d57d0SMatthias Kaehlcke writel((TXSTARTMAX << 0) | (PKTSIZE_ALIGN << 16), &mac->maxfrmlen);
208594d57d0SMatthias Kaehlcke writel(BMCTL_TXEN, &mac->bmctl);
209594d57d0SMatthias Kaehlcke
210594d57d0SMatthias Kaehlcke /*
211594d57d0SMatthias Kaehlcke * Set the receive descriptor and status queues' base address,
212594d57d0SMatthias Kaehlcke * current address, and length registers. Enable the receive
213594d57d0SMatthias Kaehlcke * descriptor processor.
214594d57d0SMatthias Kaehlcke */
215594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_dq.base, &mac->rxdq.badd);
216594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_dq.base, &mac->rxdq.curadd);
217594d57d0SMatthias Kaehlcke writel(sizeof(struct rx_descriptor) * NUMRXDESC, &mac->rxdq.blen);
218594d57d0SMatthias Kaehlcke
219594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_sq.base, &mac->rxstsq.badd);
220594d57d0SMatthias Kaehlcke writel((uint32_t)priv->rx_sq.base, &mac->rxstsq.curadd);
221594d57d0SMatthias Kaehlcke writel(sizeof(struct rx_status) * NUMRXDESC, &mac->rxstsq.blen);
222594d57d0SMatthias Kaehlcke
223594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->rxdthrshld);
224594d57d0SMatthias Kaehlcke
225594d57d0SMatthias Kaehlcke writel(BMCTL_RXEN, &mac->bmctl);
226594d57d0SMatthias Kaehlcke
227594d57d0SMatthias Kaehlcke writel(0x00040000, &mac->rxststhrshld);
228594d57d0SMatthias Kaehlcke
229594d57d0SMatthias Kaehlcke /* Wait until the receive descriptor processor is active */
230594d57d0SMatthias Kaehlcke while (!(readl(&mac->bmsts) & BMSTS_RXACT))
231594d57d0SMatthias Kaehlcke ; /* noop */
232594d57d0SMatthias Kaehlcke
233594d57d0SMatthias Kaehlcke /*
234594d57d0SMatthias Kaehlcke * Initialize the RX descriptor queue. Clear the TX descriptor queue.
235594d57d0SMatthias Kaehlcke * Clear the RX and TX status queues. Enqueue the RX descriptor and
236594d57d0SMatthias Kaehlcke * status entries to the MAC.
237594d57d0SMatthias Kaehlcke */
238594d57d0SMatthias Kaehlcke for (i = 0; i < NUMRXDESC; i++) {
239594d57d0SMatthias Kaehlcke /* set buffer address */
2401fd92db8SJoe Hershberger (priv->rx_dq.base + i)->word1 = (uint32_t)net_rx_packets[i];
241594d57d0SMatthias Kaehlcke
242594d57d0SMatthias Kaehlcke /* set buffer length, clear buffer index and NSOF */
243594d57d0SMatthias Kaehlcke (priv->rx_dq.base + i)->word2 = PKTSIZE_ALIGN;
244594d57d0SMatthias Kaehlcke }
245594d57d0SMatthias Kaehlcke
246594d57d0SMatthias Kaehlcke memset(priv->tx_dq.base, 0,
247594d57d0SMatthias Kaehlcke (sizeof(struct tx_descriptor) * NUMTXDESC));
248594d57d0SMatthias Kaehlcke memset(priv->rx_sq.base, 0,
249594d57d0SMatthias Kaehlcke (sizeof(struct rx_status) * NUMRXDESC));
250594d57d0SMatthias Kaehlcke memset(priv->tx_sq.base, 0,
251594d57d0SMatthias Kaehlcke (sizeof(struct tx_status) * NUMTXDESC));
252594d57d0SMatthias Kaehlcke
253594d57d0SMatthias Kaehlcke writel(NUMRXDESC, &mac->rxdqenq);
254594d57d0SMatthias Kaehlcke writel(NUMRXDESC, &mac->rxstsqenq);
255594d57d0SMatthias Kaehlcke
256594d57d0SMatthias Kaehlcke /* Set the primary MAC address */
257594d57d0SMatthias Kaehlcke writel(AFP_IAPRIMARY, &mac->afp);
258594d57d0SMatthias Kaehlcke writel(mac_addr[0] | (mac_addr[1] << 8) |
259594d57d0SMatthias Kaehlcke (mac_addr[2] << 16) | (mac_addr[3] << 24),
260594d57d0SMatthias Kaehlcke &mac->indad);
261594d57d0SMatthias Kaehlcke writel(mac_addr[4] | (mac_addr[5] << 8), &mac->indad_upper);
262594d57d0SMatthias Kaehlcke
263594d57d0SMatthias Kaehlcke /* Turn on RX and TX */
264594d57d0SMatthias Kaehlcke writel(RXCTL_IA0 | RXCTL_BA | RXCTL_SRXON |
265594d57d0SMatthias Kaehlcke RXCTL_RCRCA | RXCTL_MA, &mac->rxctl);
266594d57d0SMatthias Kaehlcke writel(TXCTL_STXON, &mac->txctl);
267594d57d0SMatthias Kaehlcke
268594d57d0SMatthias Kaehlcke /* Dump data structures if we're debugging */
269594d57d0SMatthias Kaehlcke dump_dev(dev);
270594d57d0SMatthias Kaehlcke dump_rx_descriptor_queue(dev);
271594d57d0SMatthias Kaehlcke dump_rx_status_queue(dev);
272594d57d0SMatthias Kaehlcke dump_tx_descriptor_queue(dev);
273594d57d0SMatthias Kaehlcke dump_tx_status_queue(dev);
274594d57d0SMatthias Kaehlcke
275594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_open");
276594d57d0SMatthias Kaehlcke
277594d57d0SMatthias Kaehlcke return 1;
278594d57d0SMatthias Kaehlcke }
279594d57d0SMatthias Kaehlcke
280594d57d0SMatthias Kaehlcke /**
281594d57d0SMatthias Kaehlcke * Halt EP93xx MAC transmit and receive by clearing the TxCTL and RxCTL
282594d57d0SMatthias Kaehlcke * registers.
283594d57d0SMatthias Kaehlcke */
ep93xx_eth_close(struct eth_device * dev)284594d57d0SMatthias Kaehlcke static void ep93xx_eth_close(struct eth_device *dev)
285594d57d0SMatthias Kaehlcke {
286594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev);
287594d57d0SMatthias Kaehlcke
288594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_close");
289594d57d0SMatthias Kaehlcke
290594d57d0SMatthias Kaehlcke writel(0x00000000, &mac->rxctl);
291594d57d0SMatthias Kaehlcke writel(0x00000000, &mac->txctl);
292594d57d0SMatthias Kaehlcke
293594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_close");
294594d57d0SMatthias Kaehlcke }
295594d57d0SMatthias Kaehlcke
296594d57d0SMatthias Kaehlcke /**
297594d57d0SMatthias Kaehlcke * Copy a frame of data from the MAC into the protocol layer for further
298594d57d0SMatthias Kaehlcke * processing.
299594d57d0SMatthias Kaehlcke */
ep93xx_eth_rcv_packet(struct eth_device * dev)300594d57d0SMatthias Kaehlcke static int ep93xx_eth_rcv_packet(struct eth_device *dev)
301594d57d0SMatthias Kaehlcke {
302594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev);
303594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
304594d57d0SMatthias Kaehlcke int len = -1;
305594d57d0SMatthias Kaehlcke
306594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_rcv_packet");
307594d57d0SMatthias Kaehlcke
308594d57d0SMatthias Kaehlcke if (RX_STATUS_RFP(priv->rx_sq.current)) {
309594d57d0SMatthias Kaehlcke if (RX_STATUS_RWE(priv->rx_sq.current)) {
310594d57d0SMatthias Kaehlcke /*
311594d57d0SMatthias Kaehlcke * We have a good frame. Extract the frame's length
312594d57d0SMatthias Kaehlcke * from the current rx_status_queue entry, and copy
3131fd92db8SJoe Hershberger * the frame's data into net_rx_packets[] of the
314594d57d0SMatthias Kaehlcke * protocol stack. We track the total number of
315594d57d0SMatthias Kaehlcke * bytes in the frame (nbytes_frame) which will be
316594d57d0SMatthias Kaehlcke * used when we pass the data off to the protocol
3171fd92db8SJoe Hershberger * layer via net_process_received_packet().
318594d57d0SMatthias Kaehlcke */
319594d57d0SMatthias Kaehlcke len = RX_STATUS_FRAME_LEN(priv->rx_sq.current);
320594d57d0SMatthias Kaehlcke
3211fd92db8SJoe Hershberger net_process_received_packet(
3221fd92db8SJoe Hershberger (uchar *)priv->rx_dq.current->word1, len);
323594d57d0SMatthias Kaehlcke
324594d57d0SMatthias Kaehlcke debug("reporting %d bytes...\n", len);
325594d57d0SMatthias Kaehlcke } else {
326594d57d0SMatthias Kaehlcke /* Do we have an erroneous packet? */
327*90aa625cSMasahiro Yamada pr_err("packet rx error, status %08X %08X",
328594d57d0SMatthias Kaehlcke priv->rx_sq.current->word1,
329594d57d0SMatthias Kaehlcke priv->rx_sq.current->word2);
330594d57d0SMatthias Kaehlcke dump_rx_descriptor_queue(dev);
331594d57d0SMatthias Kaehlcke dump_rx_status_queue(dev);
332594d57d0SMatthias Kaehlcke }
333594d57d0SMatthias Kaehlcke
334594d57d0SMatthias Kaehlcke /*
335594d57d0SMatthias Kaehlcke * Clear the associated status queue entry, and
336594d57d0SMatthias Kaehlcke * increment our current pointers to the next RX
337594d57d0SMatthias Kaehlcke * descriptor and status queue entries (making sure
338594d57d0SMatthias Kaehlcke * we wrap properly).
339594d57d0SMatthias Kaehlcke */
340594d57d0SMatthias Kaehlcke memset((void *)priv->rx_sq.current, 0,
341594d57d0SMatthias Kaehlcke sizeof(struct rx_status));
342594d57d0SMatthias Kaehlcke
343594d57d0SMatthias Kaehlcke priv->rx_sq.current++;
344594d57d0SMatthias Kaehlcke if (priv->rx_sq.current >= priv->rx_sq.end)
345594d57d0SMatthias Kaehlcke priv->rx_sq.current = priv->rx_sq.base;
346594d57d0SMatthias Kaehlcke
347594d57d0SMatthias Kaehlcke priv->rx_dq.current++;
348594d57d0SMatthias Kaehlcke if (priv->rx_dq.current >= priv->rx_dq.end)
349594d57d0SMatthias Kaehlcke priv->rx_dq.current = priv->rx_dq.base;
350594d57d0SMatthias Kaehlcke
351594d57d0SMatthias Kaehlcke /*
352594d57d0SMatthias Kaehlcke * Finally, return the RX descriptor and status entries
353594d57d0SMatthias Kaehlcke * back to the MAC engine, and loop again, checking for
354594d57d0SMatthias Kaehlcke * more descriptors to process.
355594d57d0SMatthias Kaehlcke */
356594d57d0SMatthias Kaehlcke writel(1, &mac->rxdqenq);
357594d57d0SMatthias Kaehlcke writel(1, &mac->rxstsqenq);
358594d57d0SMatthias Kaehlcke } else {
359594d57d0SMatthias Kaehlcke len = 0;
360594d57d0SMatthias Kaehlcke }
361594d57d0SMatthias Kaehlcke
362594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_rcv_packet %d", len);
363594d57d0SMatthias Kaehlcke return len;
364594d57d0SMatthias Kaehlcke }
365594d57d0SMatthias Kaehlcke
366594d57d0SMatthias Kaehlcke /**
367594d57d0SMatthias Kaehlcke * Send a block of data via ethernet.
368594d57d0SMatthias Kaehlcke */
ep93xx_eth_send_packet(struct eth_device * dev,void * const packet,int const length)369594d57d0SMatthias Kaehlcke static int ep93xx_eth_send_packet(struct eth_device *dev,
37010cbe3b6SJoe Hershberger void * const packet, int const length)
371594d57d0SMatthias Kaehlcke {
372594d57d0SMatthias Kaehlcke struct mac_regs *mac = GET_REGS(dev);
373594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv = GET_PRIV(dev);
374594d57d0SMatthias Kaehlcke int ret = -1;
375594d57d0SMatthias Kaehlcke
376594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_send_packet");
377594d57d0SMatthias Kaehlcke
378594d57d0SMatthias Kaehlcke /* Parameter check */
379594d57d0SMatthias Kaehlcke BUG_ON(packet == NULL);
380594d57d0SMatthias Kaehlcke
381594d57d0SMatthias Kaehlcke /*
382594d57d0SMatthias Kaehlcke * Initialize the TX descriptor queue with the new packet's info.
383594d57d0SMatthias Kaehlcke * Clear the associated status queue entry. Enqueue the packet
384594d57d0SMatthias Kaehlcke * to the MAC for transmission.
385594d57d0SMatthias Kaehlcke */
386594d57d0SMatthias Kaehlcke
387594d57d0SMatthias Kaehlcke /* set buffer address */
388594d57d0SMatthias Kaehlcke priv->tx_dq.current->word1 = (uint32_t)packet;
389594d57d0SMatthias Kaehlcke
390594d57d0SMatthias Kaehlcke /* set buffer length and EOF bit */
391594d57d0SMatthias Kaehlcke priv->tx_dq.current->word2 = length | TX_DESC_EOF;
392594d57d0SMatthias Kaehlcke
393594d57d0SMatthias Kaehlcke /* clear tx status */
394594d57d0SMatthias Kaehlcke priv->tx_sq.current->word1 = 0;
395594d57d0SMatthias Kaehlcke
396594d57d0SMatthias Kaehlcke /* enqueue the TX descriptor */
397594d57d0SMatthias Kaehlcke writel(1, &mac->txdqenq);
398594d57d0SMatthias Kaehlcke
399594d57d0SMatthias Kaehlcke /* wait for the frame to become processed */
400594d57d0SMatthias Kaehlcke while (!TX_STATUS_TXFP(priv->tx_sq.current))
401594d57d0SMatthias Kaehlcke ; /* noop */
402594d57d0SMatthias Kaehlcke
403594d57d0SMatthias Kaehlcke if (!TX_STATUS_TXWE(priv->tx_sq.current)) {
404*90aa625cSMasahiro Yamada pr_err("packet tx error, status %08X",
405594d57d0SMatthias Kaehlcke priv->tx_sq.current->word1);
406594d57d0SMatthias Kaehlcke dump_tx_descriptor_queue(dev);
407594d57d0SMatthias Kaehlcke dump_tx_status_queue(dev);
408594d57d0SMatthias Kaehlcke
409594d57d0SMatthias Kaehlcke /* TODO: Add better error handling? */
410594d57d0SMatthias Kaehlcke goto eth_send_out;
411594d57d0SMatthias Kaehlcke }
412594d57d0SMatthias Kaehlcke
413594d57d0SMatthias Kaehlcke ret = 0;
414594d57d0SMatthias Kaehlcke /* Fall through */
415594d57d0SMatthias Kaehlcke
416594d57d0SMatthias Kaehlcke eth_send_out:
417594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_send_packet %d", ret);
418594d57d0SMatthias Kaehlcke return ret;
419594d57d0SMatthias Kaehlcke }
420594d57d0SMatthias Kaehlcke
421594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII)
ep93xx_miiphy_initialize(bd_t * const bd)422594d57d0SMatthias Kaehlcke int ep93xx_miiphy_initialize(bd_t * const bd)
423594d57d0SMatthias Kaehlcke {
4245a49f174SJoe Hershberger int retval;
4255a49f174SJoe Hershberger struct mii_dev *mdiodev = mdio_alloc();
4265a49f174SJoe Hershberger if (!mdiodev)
4275a49f174SJoe Hershberger return -ENOMEM;
4285a49f174SJoe Hershberger strncpy(mdiodev->name, "ep93xx_eth0", MDIO_NAME_LEN);
4295a49f174SJoe Hershberger mdiodev->read = ep93xx_miiphy_read;
4305a49f174SJoe Hershberger mdiodev->write = ep93xx_miiphy_write;
4315a49f174SJoe Hershberger
4325a49f174SJoe Hershberger retval = mdio_register(mdiodev);
4335a49f174SJoe Hershberger if (retval < 0)
4345a49f174SJoe Hershberger return retval;
435594d57d0SMatthias Kaehlcke return 0;
436594d57d0SMatthias Kaehlcke }
437594d57d0SMatthias Kaehlcke #endif
438594d57d0SMatthias Kaehlcke
439594d57d0SMatthias Kaehlcke /**
440594d57d0SMatthias Kaehlcke * Initialize the EP93xx MAC. The MAC hardware is reset. Buffers are
441594d57d0SMatthias Kaehlcke * allocated, if necessary, for the TX and RX descriptor and status queues,
442594d57d0SMatthias Kaehlcke * as well as for received packets. The EP93XX MAC hardware is initialized.
443594d57d0SMatthias Kaehlcke * Transmit and receive operations are enabled.
444594d57d0SMatthias Kaehlcke */
ep93xx_eth_initialize(u8 dev_num,int base_addr)445594d57d0SMatthias Kaehlcke int ep93xx_eth_initialize(u8 dev_num, int base_addr)
446594d57d0SMatthias Kaehlcke {
447594d57d0SMatthias Kaehlcke int ret = -1;
448594d57d0SMatthias Kaehlcke struct eth_device *dev;
449594d57d0SMatthias Kaehlcke struct ep93xx_priv *priv;
450594d57d0SMatthias Kaehlcke
451594d57d0SMatthias Kaehlcke debug("+ep93xx_eth_initialize");
452594d57d0SMatthias Kaehlcke
453594d57d0SMatthias Kaehlcke priv = malloc(sizeof(*priv));
454594d57d0SMatthias Kaehlcke if (!priv) {
455*90aa625cSMasahiro Yamada pr_err("malloc() failed");
456594d57d0SMatthias Kaehlcke goto eth_init_failed_0;
457594d57d0SMatthias Kaehlcke }
458594d57d0SMatthias Kaehlcke memset(priv, 0, sizeof(*priv));
459594d57d0SMatthias Kaehlcke
460594d57d0SMatthias Kaehlcke priv->regs = (struct mac_regs *)base_addr;
461594d57d0SMatthias Kaehlcke
462594d57d0SMatthias Kaehlcke priv->tx_dq.base = calloc(NUMTXDESC,
463594d57d0SMatthias Kaehlcke sizeof(struct tx_descriptor));
464594d57d0SMatthias Kaehlcke if (priv->tx_dq.base == NULL) {
465*90aa625cSMasahiro Yamada pr_err("calloc() failed");
466594d57d0SMatthias Kaehlcke goto eth_init_failed_1;
467594d57d0SMatthias Kaehlcke }
468594d57d0SMatthias Kaehlcke
469594d57d0SMatthias Kaehlcke priv->tx_sq.base = calloc(NUMTXDESC,
470594d57d0SMatthias Kaehlcke sizeof(struct tx_status));
471594d57d0SMatthias Kaehlcke if (priv->tx_sq.base == NULL) {
472*90aa625cSMasahiro Yamada pr_err("calloc() failed");
473594d57d0SMatthias Kaehlcke goto eth_init_failed_2;
474594d57d0SMatthias Kaehlcke }
475594d57d0SMatthias Kaehlcke
476594d57d0SMatthias Kaehlcke priv->rx_dq.base = calloc(NUMRXDESC,
477594d57d0SMatthias Kaehlcke sizeof(struct rx_descriptor));
478594d57d0SMatthias Kaehlcke if (priv->rx_dq.base == NULL) {
479*90aa625cSMasahiro Yamada pr_err("calloc() failed");
480594d57d0SMatthias Kaehlcke goto eth_init_failed_3;
481594d57d0SMatthias Kaehlcke }
482594d57d0SMatthias Kaehlcke
483594d57d0SMatthias Kaehlcke priv->rx_sq.base = calloc(NUMRXDESC,
484594d57d0SMatthias Kaehlcke sizeof(struct rx_status));
485594d57d0SMatthias Kaehlcke if (priv->rx_sq.base == NULL) {
486*90aa625cSMasahiro Yamada pr_err("calloc() failed");
487594d57d0SMatthias Kaehlcke goto eth_init_failed_4;
488594d57d0SMatthias Kaehlcke }
489594d57d0SMatthias Kaehlcke
490594d57d0SMatthias Kaehlcke dev = malloc(sizeof *dev);
491594d57d0SMatthias Kaehlcke if (dev == NULL) {
492*90aa625cSMasahiro Yamada pr_err("malloc() failed");
493594d57d0SMatthias Kaehlcke goto eth_init_failed_5;
494594d57d0SMatthias Kaehlcke }
495594d57d0SMatthias Kaehlcke memset(dev, 0, sizeof *dev);
496594d57d0SMatthias Kaehlcke
497594d57d0SMatthias Kaehlcke dev->iobase = base_addr;
498594d57d0SMatthias Kaehlcke dev->priv = priv;
499594d57d0SMatthias Kaehlcke dev->init = ep93xx_eth_open;
500594d57d0SMatthias Kaehlcke dev->halt = ep93xx_eth_close;
501594d57d0SMatthias Kaehlcke dev->send = ep93xx_eth_send_packet;
502594d57d0SMatthias Kaehlcke dev->recv = ep93xx_eth_rcv_packet;
503594d57d0SMatthias Kaehlcke
504594d57d0SMatthias Kaehlcke sprintf(dev->name, "ep93xx_eth-%hu", dev_num);
505594d57d0SMatthias Kaehlcke
506594d57d0SMatthias Kaehlcke eth_register(dev);
507594d57d0SMatthias Kaehlcke
508594d57d0SMatthias Kaehlcke /* Done! */
509594d57d0SMatthias Kaehlcke ret = 1;
510594d57d0SMatthias Kaehlcke goto eth_init_done;
511594d57d0SMatthias Kaehlcke
512594d57d0SMatthias Kaehlcke eth_init_failed_5:
513594d57d0SMatthias Kaehlcke free(priv->rx_sq.base);
514594d57d0SMatthias Kaehlcke /* Fall through */
515594d57d0SMatthias Kaehlcke
516594d57d0SMatthias Kaehlcke eth_init_failed_4:
517594d57d0SMatthias Kaehlcke free(priv->rx_dq.base);
518594d57d0SMatthias Kaehlcke /* Fall through */
519594d57d0SMatthias Kaehlcke
520594d57d0SMatthias Kaehlcke eth_init_failed_3:
521594d57d0SMatthias Kaehlcke free(priv->tx_sq.base);
522594d57d0SMatthias Kaehlcke /* Fall through */
523594d57d0SMatthias Kaehlcke
524594d57d0SMatthias Kaehlcke eth_init_failed_2:
525594d57d0SMatthias Kaehlcke free(priv->tx_dq.base);
526594d57d0SMatthias Kaehlcke /* Fall through */
527594d57d0SMatthias Kaehlcke
528594d57d0SMatthias Kaehlcke eth_init_failed_1:
529594d57d0SMatthias Kaehlcke free(priv);
530594d57d0SMatthias Kaehlcke /* Fall through */
531594d57d0SMatthias Kaehlcke
532594d57d0SMatthias Kaehlcke eth_init_failed_0:
533594d57d0SMatthias Kaehlcke /* Fall through */
534594d57d0SMatthias Kaehlcke
535594d57d0SMatthias Kaehlcke eth_init_done:
536594d57d0SMatthias Kaehlcke debug("-ep93xx_eth_initialize %d", ret);
537594d57d0SMatthias Kaehlcke return ret;
538594d57d0SMatthias Kaehlcke }
539594d57d0SMatthias Kaehlcke
540594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII)
541594d57d0SMatthias Kaehlcke
542594d57d0SMatthias Kaehlcke /**
543594d57d0SMatthias Kaehlcke * Maximum MII address we support
544594d57d0SMatthias Kaehlcke */
545594d57d0SMatthias Kaehlcke #define MII_ADDRESS_MAX 31
546594d57d0SMatthias Kaehlcke
547594d57d0SMatthias Kaehlcke /**
548594d57d0SMatthias Kaehlcke * Maximum MII register address we support
549594d57d0SMatthias Kaehlcke */
550594d57d0SMatthias Kaehlcke #define MII_REGISTER_MAX 31
551594d57d0SMatthias Kaehlcke
552594d57d0SMatthias Kaehlcke /**
553594d57d0SMatthias Kaehlcke * Read a 16-bit value from an MII register.
554594d57d0SMatthias Kaehlcke */
ep93xx_miiphy_read(struct mii_dev * bus,int addr,int devad,int reg)5555a49f174SJoe Hershberger static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
5565a49f174SJoe Hershberger int reg)
557594d57d0SMatthias Kaehlcke {
5585a49f174SJoe Hershberger unsigned short value = 0;
559594d57d0SMatthias Kaehlcke struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
560594d57d0SMatthias Kaehlcke int ret = -1;
561594d57d0SMatthias Kaehlcke uint32_t self_ctl;
562594d57d0SMatthias Kaehlcke
563594d57d0SMatthias Kaehlcke debug("+ep93xx_miiphy_read");
564594d57d0SMatthias Kaehlcke
565594d57d0SMatthias Kaehlcke /* Parameter checks */
5665a49f174SJoe Hershberger BUG_ON(bus->name == NULL);
567594d57d0SMatthias Kaehlcke BUG_ON(addr > MII_ADDRESS_MAX);
568594d57d0SMatthias Kaehlcke BUG_ON(reg > MII_REGISTER_MAX);
569594d57d0SMatthias Kaehlcke
570594d57d0SMatthias Kaehlcke /*
571594d57d0SMatthias Kaehlcke * Save the current SelfCTL register value. Set MAC to suppress
572594d57d0SMatthias Kaehlcke * preamble bits. Wait for any previous MII command to complete
573594d57d0SMatthias Kaehlcke * before issuing the new command.
574594d57d0SMatthias Kaehlcke */
575594d57d0SMatthias Kaehlcke self_ctl = readl(&mac->selfctl);
576594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII_SUPPRESS_PREAMBLE)
577594d57d0SMatthias Kaehlcke writel(self_ctl & ~(1 << 8), &mac->selfctl);
578594d57d0SMatthias Kaehlcke #endif /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */
579594d57d0SMatthias Kaehlcke
580594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY)
581594d57d0SMatthias Kaehlcke ; /* noop */
582594d57d0SMatthias Kaehlcke
583594d57d0SMatthias Kaehlcke /*
584594d57d0SMatthias Kaehlcke * Issue the MII 'read' command. Wait for the command to complete.
585594d57d0SMatthias Kaehlcke * Read the MII data value.
586594d57d0SMatthias Kaehlcke */
587594d57d0SMatthias Kaehlcke writel(MIICMD_OPCODE_READ | ((uint32_t)addr << 5) | (uint32_t)reg,
588594d57d0SMatthias Kaehlcke &mac->miicmd);
589594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY)
590594d57d0SMatthias Kaehlcke ; /* noop */
591594d57d0SMatthias Kaehlcke
5925a49f174SJoe Hershberger value = (unsigned short)readl(&mac->miidata);
593594d57d0SMatthias Kaehlcke
594594d57d0SMatthias Kaehlcke /* Restore the saved SelfCTL value and return. */
595594d57d0SMatthias Kaehlcke writel(self_ctl, &mac->selfctl);
596594d57d0SMatthias Kaehlcke
597594d57d0SMatthias Kaehlcke ret = 0;
598594d57d0SMatthias Kaehlcke /* Fall through */
599594d57d0SMatthias Kaehlcke
600594d57d0SMatthias Kaehlcke debug("-ep93xx_miiphy_read");
6015a49f174SJoe Hershberger if (ret < 0)
602594d57d0SMatthias Kaehlcke return ret;
6035a49f174SJoe Hershberger return value;
604594d57d0SMatthias Kaehlcke }
605594d57d0SMatthias Kaehlcke
606594d57d0SMatthias Kaehlcke /**
607594d57d0SMatthias Kaehlcke * Write a 16-bit value to an MII register.
608594d57d0SMatthias Kaehlcke */
ep93xx_miiphy_write(struct mii_dev * bus,int addr,int devad,int reg,u16 value)6095a49f174SJoe Hershberger static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
6105a49f174SJoe Hershberger int reg, u16 value)
611594d57d0SMatthias Kaehlcke {
612594d57d0SMatthias Kaehlcke struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
613594d57d0SMatthias Kaehlcke int ret = -1;
614594d57d0SMatthias Kaehlcke uint32_t self_ctl;
615594d57d0SMatthias Kaehlcke
616594d57d0SMatthias Kaehlcke debug("+ep93xx_miiphy_write");
617594d57d0SMatthias Kaehlcke
618594d57d0SMatthias Kaehlcke /* Parameter checks */
6195a49f174SJoe Hershberger BUG_ON(bus->name == NULL);
620594d57d0SMatthias Kaehlcke BUG_ON(addr > MII_ADDRESS_MAX);
621594d57d0SMatthias Kaehlcke BUG_ON(reg > MII_REGISTER_MAX);
622594d57d0SMatthias Kaehlcke
623594d57d0SMatthias Kaehlcke /*
624594d57d0SMatthias Kaehlcke * Save the current SelfCTL register value. Set MAC to suppress
625594d57d0SMatthias Kaehlcke * preamble bits. Wait for any previous MII command to complete
626594d57d0SMatthias Kaehlcke * before issuing the new command.
627594d57d0SMatthias Kaehlcke */
628594d57d0SMatthias Kaehlcke self_ctl = readl(&mac->selfctl);
629594d57d0SMatthias Kaehlcke #if defined(CONFIG_MII_SUPPRESS_PREAMBLE)
630594d57d0SMatthias Kaehlcke writel(self_ctl & ~(1 << 8), &mac->selfctl);
631594d57d0SMatthias Kaehlcke #endif /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */
632594d57d0SMatthias Kaehlcke
633594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY)
634594d57d0SMatthias Kaehlcke ; /* noop */
635594d57d0SMatthias Kaehlcke
636594d57d0SMatthias Kaehlcke /* Issue the MII 'write' command. Wait for the command to complete. */
637594d57d0SMatthias Kaehlcke writel((uint32_t)value, &mac->miidata);
638594d57d0SMatthias Kaehlcke writel(MIICMD_OPCODE_WRITE | ((uint32_t)addr << 5) | (uint32_t)reg,
639594d57d0SMatthias Kaehlcke &mac->miicmd);
640594d57d0SMatthias Kaehlcke while (readl(&mac->miists) & MIISTS_BUSY)
641594d57d0SMatthias Kaehlcke ; /* noop */
642594d57d0SMatthias Kaehlcke
643594d57d0SMatthias Kaehlcke /* Restore the saved SelfCTL value and return. */
644594d57d0SMatthias Kaehlcke writel(self_ctl, &mac->selfctl);
645594d57d0SMatthias Kaehlcke
646594d57d0SMatthias Kaehlcke ret = 0;
647594d57d0SMatthias Kaehlcke /* Fall through */
648594d57d0SMatthias Kaehlcke
649594d57d0SMatthias Kaehlcke debug("-ep93xx_miiphy_write");
650594d57d0SMatthias Kaehlcke return ret;
651594d57d0SMatthias Kaehlcke }
652594d57d0SMatthias Kaehlcke #endif /* defined(CONFIG_MII) */
653