xref: /openbmc/u-boot/drivers/net/ftmac100.c (revision 3eceff64)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2750326e5SPo-Yu Chuang /*
3750326e5SPo-Yu Chuang  * Faraday FTMAC100 Ethernet
4750326e5SPo-Yu Chuang  *
5750326e5SPo-Yu Chuang  * (C) Copyright 2009 Faraday Technology
6750326e5SPo-Yu Chuang  * Po-Yu Chuang <ratbert@faraday-tech.com>
7750326e5SPo-Yu Chuang  */
8750326e5SPo-Yu Chuang 
9750326e5SPo-Yu Chuang #include <config.h>
10750326e5SPo-Yu Chuang #include <common.h>
11750326e5SPo-Yu Chuang #include <malloc.h>
12750326e5SPo-Yu Chuang #include <net.h>
13be71a179Srick #include <linux/io.h>
14750326e5SPo-Yu Chuang 
15750326e5SPo-Yu Chuang #include "ftmac100.h"
16be71a179Srick #ifdef CONFIG_DM_ETH
17be71a179Srick #include <dm.h>
18be71a179Srick DECLARE_GLOBAL_DATA_PTR;
19be71a179Srick #endif
20750326e5SPo-Yu Chuang #define ETH_ZLEN	60
21750326e5SPo-Yu Chuang 
22750326e5SPo-Yu Chuang struct ftmac100_data {
236f6e6e09SPo-Yu Chuang 	struct ftmac100_txdes txdes[1];
246f6e6e09SPo-Yu Chuang 	struct ftmac100_rxdes rxdes[PKTBUFSRX];
25750326e5SPo-Yu Chuang 	int rx_index;
26be71a179Srick 	const char *name;
27be71a179Srick 	phys_addr_t iobase;
28750326e5SPo-Yu Chuang };
29750326e5SPo-Yu Chuang 
30750326e5SPo-Yu Chuang /*
31750326e5SPo-Yu Chuang  * Reset MAC
32750326e5SPo-Yu Chuang  */
ftmac100_reset(struct ftmac100_data * priv)33be71a179Srick static void ftmac100_reset(struct ftmac100_data *priv)
34750326e5SPo-Yu Chuang {
35be71a179Srick 	struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
36750326e5SPo-Yu Chuang 
37750326e5SPo-Yu Chuang 	debug ("%s()\n", __func__);
38750326e5SPo-Yu Chuang 
39750326e5SPo-Yu Chuang 	writel (FTMAC100_MACCR_SW_RST, &ftmac100->maccr);
40750326e5SPo-Yu Chuang 
41750326e5SPo-Yu Chuang 	while (readl (&ftmac100->maccr) & FTMAC100_MACCR_SW_RST)
421341494cSrick 		mdelay(1);
431341494cSrick 	/*
441341494cSrick 	 * When soft reset complete, write mac address immediately maybe fail somehow
451341494cSrick 	 *  Wait for a while can avoid this problem
461341494cSrick 	 */
471341494cSrick 	mdelay(1);
48750326e5SPo-Yu Chuang }
49750326e5SPo-Yu Chuang 
50750326e5SPo-Yu Chuang /*
51750326e5SPo-Yu Chuang  * Set MAC address
52750326e5SPo-Yu Chuang  */
ftmac100_set_mac(struct ftmac100_data * priv,const unsigned char * mac)53be71a179Srick static void ftmac100_set_mac(struct ftmac100_data *priv ,
54be71a179Srick 	const unsigned char *mac)
55750326e5SPo-Yu Chuang {
56be71a179Srick 	struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
57750326e5SPo-Yu Chuang 	unsigned int maddr = mac[0] << 8 | mac[1];
58750326e5SPo-Yu Chuang 	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
59750326e5SPo-Yu Chuang 
60750326e5SPo-Yu Chuang 	debug ("%s(%x %x)\n", __func__, maddr, laddr);
61750326e5SPo-Yu Chuang 
62750326e5SPo-Yu Chuang 	writel (maddr, &ftmac100->mac_madr);
63750326e5SPo-Yu Chuang 	writel (laddr, &ftmac100->mac_ladr);
64750326e5SPo-Yu Chuang }
65750326e5SPo-Yu Chuang 
66750326e5SPo-Yu Chuang /*
67be71a179Srick  * Disable MAC
68750326e5SPo-Yu Chuang  */
_ftmac100_halt(struct ftmac100_data * priv)69be71a179Srick static void _ftmac100_halt(struct ftmac100_data *priv)
70750326e5SPo-Yu Chuang {
71be71a179Srick 	struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
72750326e5SPo-Yu Chuang 	debug ("%s()\n", __func__);
73750326e5SPo-Yu Chuang 	writel (0, &ftmac100->maccr);
74750326e5SPo-Yu Chuang }
75750326e5SPo-Yu Chuang 
76be71a179Srick /*
77be71a179Srick  * Initialize MAC
78be71a179Srick  */
_ftmac100_init(struct ftmac100_data * priv,unsigned char enetaddr[6])79be71a179Srick static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
80750326e5SPo-Yu Chuang {
81be71a179Srick 	struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
826f6e6e09SPo-Yu Chuang 	struct ftmac100_txdes *txdes = priv->txdes;
836f6e6e09SPo-Yu Chuang 	struct ftmac100_rxdes *rxdes = priv->rxdes;
84750326e5SPo-Yu Chuang 	unsigned int maccr;
85750326e5SPo-Yu Chuang 	int i;
86750326e5SPo-Yu Chuang 	debug ("%s()\n", __func__);
87750326e5SPo-Yu Chuang 
88be71a179Srick 	ftmac100_reset(priv);
89750326e5SPo-Yu Chuang 
90750326e5SPo-Yu Chuang 	/* set the ethernet address */
91be71a179Srick 	ftmac100_set_mac(priv, enetaddr);
92750326e5SPo-Yu Chuang 
93750326e5SPo-Yu Chuang 
94750326e5SPo-Yu Chuang 	/* disable all interrupts */
95750326e5SPo-Yu Chuang 
96750326e5SPo-Yu Chuang 	writel (0, &ftmac100->imr);
97750326e5SPo-Yu Chuang 
98750326e5SPo-Yu Chuang 	/* initialize descriptors */
99750326e5SPo-Yu Chuang 
100750326e5SPo-Yu Chuang 	priv->rx_index = 0;
101750326e5SPo-Yu Chuang 
102750326e5SPo-Yu Chuang 	txdes[0].txdes1			= FTMAC100_TXDES1_EDOTR;
103750326e5SPo-Yu Chuang 	rxdes[PKTBUFSRX - 1].rxdes1	= FTMAC100_RXDES1_EDORR;
104750326e5SPo-Yu Chuang 
105750326e5SPo-Yu Chuang 	for (i = 0; i < PKTBUFSRX; i++) {
106750326e5SPo-Yu Chuang 		/* RXBUF_BADR */
107*28b52a6fSRick Chen 		rxdes[i].rxdes2 = (unsigned int)(unsigned long)net_rx_packets[i];
108750326e5SPo-Yu Chuang 		rxdes[i].rxdes1 |= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN);
109750326e5SPo-Yu Chuang 		rxdes[i].rxdes0 = FTMAC100_RXDES0_RXDMA_OWN;
110750326e5SPo-Yu Chuang 	}
111750326e5SPo-Yu Chuang 
112750326e5SPo-Yu Chuang 	/* transmit ring */
113750326e5SPo-Yu Chuang 
114*28b52a6fSRick Chen 	writel ((unsigned long)txdes, &ftmac100->txr_badr);
115750326e5SPo-Yu Chuang 
116750326e5SPo-Yu Chuang 	/* receive ring */
117750326e5SPo-Yu Chuang 
118*28b52a6fSRick Chen 	writel ((unsigned long)rxdes, &ftmac100->rxr_badr);
119750326e5SPo-Yu Chuang 
120750326e5SPo-Yu Chuang 	/* poll receive descriptor automatically */
121750326e5SPo-Yu Chuang 
122750326e5SPo-Yu Chuang 	writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100->aptc);
123750326e5SPo-Yu Chuang 
124750326e5SPo-Yu Chuang 	/* enable transmitter, receiver */
125750326e5SPo-Yu Chuang 
126750326e5SPo-Yu Chuang 	maccr = FTMAC100_MACCR_XMT_EN |
127750326e5SPo-Yu Chuang 		FTMAC100_MACCR_RCV_EN |
128750326e5SPo-Yu Chuang 		FTMAC100_MACCR_XDMA_EN |
129750326e5SPo-Yu Chuang 		FTMAC100_MACCR_RDMA_EN |
130750326e5SPo-Yu Chuang 		FTMAC100_MACCR_CRC_APD |
131750326e5SPo-Yu Chuang 		FTMAC100_MACCR_ENRX_IN_HALFTX |
132750326e5SPo-Yu Chuang 		FTMAC100_MACCR_RX_RUNT |
133750326e5SPo-Yu Chuang 		FTMAC100_MACCR_RX_BROADPKT;
134750326e5SPo-Yu Chuang 
135750326e5SPo-Yu Chuang 	writel (maccr, &ftmac100->maccr);
136750326e5SPo-Yu Chuang 
137750326e5SPo-Yu Chuang 	return 0;
138750326e5SPo-Yu Chuang }
139750326e5SPo-Yu Chuang 
140750326e5SPo-Yu Chuang /*
141be71a179Srick  * Free receiving buffer
142750326e5SPo-Yu Chuang  */
_ftmac100_free_pkt(struct ftmac100_data * priv)143be71a179Srick static int _ftmac100_free_pkt(struct ftmac100_data *priv)
144750326e5SPo-Yu Chuang {
145be71a179Srick 	struct ftmac100_rxdes *curr_des;
146be71a179Srick 	curr_des = &priv->rxdes[priv->rx_index];
147be71a179Srick 	/* release buffer to DMA */
148be71a179Srick 	curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
149be71a179Srick 	priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
150be71a179Srick 	return 0;
151be71a179Srick }
152be71a179Srick 
153be71a179Srick /*
154be71a179Srick  * Receive a data block via Ethernet
155be71a179Srick  */
__ftmac100_recv(struct ftmac100_data * priv)156be71a179Srick static int __ftmac100_recv(struct ftmac100_data *priv)
157be71a179Srick {
1586f6e6e09SPo-Yu Chuang 	struct ftmac100_rxdes *curr_des;
159750326e5SPo-Yu Chuang 	unsigned short rxlen;
160750326e5SPo-Yu Chuang 
161750326e5SPo-Yu Chuang 	curr_des = &priv->rxdes[priv->rx_index];
162750326e5SPo-Yu Chuang 	if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN)
163be71a179Srick 		return 0;
164750326e5SPo-Yu Chuang 
165750326e5SPo-Yu Chuang 	if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR |
166750326e5SPo-Yu Chuang 				FTMAC100_RXDES0_CRC_ERR |
167750326e5SPo-Yu Chuang 				FTMAC100_RXDES0_FTL |
168750326e5SPo-Yu Chuang 				FTMAC100_RXDES0_RUNT |
169750326e5SPo-Yu Chuang 				FTMAC100_RXDES0_RX_ODD_NB)) {
170be71a179Srick 		return 0;
171750326e5SPo-Yu Chuang 	}
172750326e5SPo-Yu Chuang 
173750326e5SPo-Yu Chuang 	rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0);
174ce4e2370Srick 	invalidate_dcache_range(curr_des->rxdes2,curr_des->rxdes2+rxlen);
175750326e5SPo-Yu Chuang 	debug ("%s(): RX buffer %d, %x received\n",
176750326e5SPo-Yu Chuang 	       __func__, priv->rx_index, rxlen);
177750326e5SPo-Yu Chuang 
178be71a179Srick 	return rxlen;
179750326e5SPo-Yu Chuang }
180750326e5SPo-Yu Chuang 
181750326e5SPo-Yu Chuang /*
182750326e5SPo-Yu Chuang  * Send a data block via Ethernet
183750326e5SPo-Yu Chuang  */
_ftmac100_send(struct ftmac100_data * priv,void * packet,int length)184be71a179Srick static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
185750326e5SPo-Yu Chuang {
186be71a179Srick 	struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
1876f6e6e09SPo-Yu Chuang 	struct ftmac100_txdes *curr_des = priv->txdes;
1888d8fd5b6SPo-Yu Chuang 	ulong start;
189750326e5SPo-Yu Chuang 
190750326e5SPo-Yu Chuang 	if (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
191750326e5SPo-Yu Chuang 		debug ("%s(): no TX descriptor available\n", __func__);
192750326e5SPo-Yu Chuang 		return -1;
193750326e5SPo-Yu Chuang 	}
194750326e5SPo-Yu Chuang 
195*28b52a6fSRick Chen 	debug ("%s(%lx, %x)\n", __func__, (unsigned long)packet, length);
196750326e5SPo-Yu Chuang 
197750326e5SPo-Yu Chuang 	length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
198750326e5SPo-Yu Chuang 
199750326e5SPo-Yu Chuang 	/* initiate a transmit sequence */
200750326e5SPo-Yu Chuang 
201*28b52a6fSRick Chen 	flush_dcache_range((unsigned long)packet,(unsigned long)packet+length);
202*28b52a6fSRick Chen 	curr_des->txdes2 = (unsigned int)(unsigned long)packet;	/* TXBUF_BADR */
203750326e5SPo-Yu Chuang 
204750326e5SPo-Yu Chuang 	curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR;
205750326e5SPo-Yu Chuang 	curr_des->txdes1 |= FTMAC100_TXDES1_FTS |
206750326e5SPo-Yu Chuang 			    FTMAC100_TXDES1_LTS |
207750326e5SPo-Yu Chuang 			    FTMAC100_TXDES1_TXBUF_SIZE (length);
208750326e5SPo-Yu Chuang 
209750326e5SPo-Yu Chuang 	curr_des->txdes0 = FTMAC100_TXDES0_TXDMA_OWN;
210750326e5SPo-Yu Chuang 
211750326e5SPo-Yu Chuang 	/* start transmit */
212750326e5SPo-Yu Chuang 
213750326e5SPo-Yu Chuang 	writel (1, &ftmac100->txpd);
214750326e5SPo-Yu Chuang 
215750326e5SPo-Yu Chuang 	/* wait for transfer to succeed */
216750326e5SPo-Yu Chuang 
2178d8fd5b6SPo-Yu Chuang 	start = get_timer(0);
218750326e5SPo-Yu Chuang 	while (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
2198d8fd5b6SPo-Yu Chuang 		if (get_timer(start) >= 5) {
220750326e5SPo-Yu Chuang 			debug ("%s(): timed out\n", __func__);
221750326e5SPo-Yu Chuang 			return -1;
222750326e5SPo-Yu Chuang 		}
223750326e5SPo-Yu Chuang 	}
224750326e5SPo-Yu Chuang 
225750326e5SPo-Yu Chuang 	debug ("%s(): packet sent\n", __func__);
226750326e5SPo-Yu Chuang 
227750326e5SPo-Yu Chuang 	return 0;
228750326e5SPo-Yu Chuang }
229750326e5SPo-Yu Chuang 
230be71a179Srick #ifndef CONFIG_DM_ETH
231be71a179Srick /*
232be71a179Srick  * disable transmitter, receiver
233be71a179Srick  */
ftmac100_halt(struct eth_device * dev)234be71a179Srick static void ftmac100_halt(struct eth_device *dev)
235be71a179Srick {
236be71a179Srick 	struct ftmac100_data *priv = dev->priv;
237be71a179Srick 	return _ftmac100_halt(priv);
238be71a179Srick }
239be71a179Srick 
ftmac100_init(struct eth_device * dev,bd_t * bd)240be71a179Srick static int ftmac100_init(struct eth_device *dev, bd_t *bd)
241be71a179Srick {
242be71a179Srick 	struct ftmac100_data *priv = dev->priv;
243be71a179Srick 	return _ftmac100_init(priv , dev->enetaddr);
244be71a179Srick }
245be71a179Srick 
_ftmac100_recv(struct ftmac100_data * priv)246be71a179Srick static int _ftmac100_recv(struct ftmac100_data *priv)
247be71a179Srick {
248be71a179Srick 	struct ftmac100_rxdes *curr_des;
249be71a179Srick 	unsigned short len;
250be71a179Srick 	curr_des = &priv->rxdes[priv->rx_index];
251be71a179Srick 	len = __ftmac100_recv(priv);
252be71a179Srick 	if (len) {
253be71a179Srick 		/* pass the packet up to the protocol layers. */
254be71a179Srick 		net_process_received_packet((void *)curr_des->rxdes2, len);
255be71a179Srick 		_ftmac100_free_pkt(priv);
256be71a179Srick 	}
257be71a179Srick 	return len ? 1 : 0;
258be71a179Srick }
259be71a179Srick 
260be71a179Srick /*
261be71a179Srick  * Get a data block via Ethernet
262be71a179Srick  */
ftmac100_recv(struct eth_device * dev)263be71a179Srick static int ftmac100_recv(struct eth_device *dev)
264be71a179Srick {
265be71a179Srick 	struct ftmac100_data *priv = dev->priv;
266be71a179Srick 	return _ftmac100_recv(priv);
267be71a179Srick }
268be71a179Srick 
269be71a179Srick /*
270be71a179Srick  * Send a data block via Ethernet
271be71a179Srick  */
ftmac100_send(struct eth_device * dev,void * packet,int length)272be71a179Srick static int ftmac100_send(struct eth_device *dev, void *packet, int length)
273be71a179Srick {
274be71a179Srick 	struct ftmac100_data *priv = dev->priv;
275be71a179Srick 	return _ftmac100_send(priv , packet , length);
276be71a179Srick }
277be71a179Srick 
ftmac100_initialize(bd_t * bd)278750326e5SPo-Yu Chuang int ftmac100_initialize (bd_t *bd)
279750326e5SPo-Yu Chuang {
280750326e5SPo-Yu Chuang 	struct eth_device *dev;
281750326e5SPo-Yu Chuang 	struct ftmac100_data *priv;
282750326e5SPo-Yu Chuang 	dev = malloc (sizeof *dev);
283750326e5SPo-Yu Chuang 	if (!dev) {
284750326e5SPo-Yu Chuang 		printf ("%s(): failed to allocate dev\n", __func__);
285750326e5SPo-Yu Chuang 		goto out;
286750326e5SPo-Yu Chuang 	}
287750326e5SPo-Yu Chuang 	/* Transmit and receive descriptors should align to 16 bytes */
288750326e5SPo-Yu Chuang 	priv = memalign (16, sizeof (struct ftmac100_data));
289750326e5SPo-Yu Chuang 	if (!priv) {
290750326e5SPo-Yu Chuang 		printf ("%s(): failed to allocate priv\n", __func__);
291750326e5SPo-Yu Chuang 		goto free_dev;
292750326e5SPo-Yu Chuang 	}
293750326e5SPo-Yu Chuang 	memset (dev, 0, sizeof (*dev));
294750326e5SPo-Yu Chuang 	memset (priv, 0, sizeof (*priv));
295750326e5SPo-Yu Chuang 
296192bc694SBen Whitten 	strcpy(dev->name, "FTMAC100");
297750326e5SPo-Yu Chuang 	dev->iobase	= CONFIG_FTMAC100_BASE;
298750326e5SPo-Yu Chuang 	dev->init	= ftmac100_init;
299750326e5SPo-Yu Chuang 	dev->halt	= ftmac100_halt;
300750326e5SPo-Yu Chuang 	dev->send	= ftmac100_send;
301750326e5SPo-Yu Chuang 	dev->recv	= ftmac100_recv;
302750326e5SPo-Yu Chuang 	dev->priv	= priv;
303be71a179Srick 	priv->iobase	= dev->iobase;
304750326e5SPo-Yu Chuang 	eth_register (dev);
305750326e5SPo-Yu Chuang 
306750326e5SPo-Yu Chuang 	return 1;
307750326e5SPo-Yu Chuang 
308750326e5SPo-Yu Chuang free_dev:
309750326e5SPo-Yu Chuang 	free (dev);
310750326e5SPo-Yu Chuang out:
311750326e5SPo-Yu Chuang 	return 0;
312750326e5SPo-Yu Chuang }
313be71a179Srick #endif
314be71a179Srick 
315be71a179Srick #ifdef CONFIG_DM_ETH
ftmac100_start(struct udevice * dev)316be71a179Srick static int ftmac100_start(struct udevice *dev)
317be71a179Srick {
318be71a179Srick 	struct eth_pdata *plat = dev_get_platdata(dev);
319be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
320be71a179Srick 
321be71a179Srick 	return _ftmac100_init(priv, plat->enetaddr);
322be71a179Srick }
323be71a179Srick 
ftmac100_stop(struct udevice * dev)324be71a179Srick static void ftmac100_stop(struct udevice *dev)
325be71a179Srick {
326be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
327be71a179Srick 	_ftmac100_halt(priv);
328be71a179Srick }
329be71a179Srick 
ftmac100_send(struct udevice * dev,void * packet,int length)330be71a179Srick static int ftmac100_send(struct udevice *dev, void *packet, int length)
331be71a179Srick {
332be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
333be71a179Srick 	int ret;
334be71a179Srick 	ret = _ftmac100_send(priv , packet , length);
335be71a179Srick 	return ret ? 0 : -ETIMEDOUT;
336be71a179Srick }
337be71a179Srick 
ftmac100_recv(struct udevice * dev,int flags,uchar ** packetp)338be71a179Srick static int ftmac100_recv(struct udevice *dev, int flags, uchar **packetp)
339be71a179Srick {
340be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
341be71a179Srick 	struct ftmac100_rxdes *curr_des;
342be71a179Srick 	curr_des = &priv->rxdes[priv->rx_index];
343be71a179Srick 	int len;
344be71a179Srick 	len = __ftmac100_recv(priv);
345be71a179Srick 	if (len)
346*28b52a6fSRick Chen 		*packetp = (uchar *)(unsigned long)curr_des->rxdes2;
347be71a179Srick 
348be71a179Srick 	return len ? len : -EAGAIN;
349be71a179Srick }
350be71a179Srick 
ftmac100_free_pkt(struct udevice * dev,uchar * packet,int length)351be71a179Srick static int ftmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
352be71a179Srick {
353be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
354be71a179Srick 	_ftmac100_free_pkt(priv);
355be71a179Srick 	return 0;
356be71a179Srick }
357be71a179Srick 
ftmac100_read_rom_hwaddr(struct udevice * dev)358be71a179Srick int ftmac100_read_rom_hwaddr(struct udevice *dev)
359be71a179Srick {
360be71a179Srick 	struct eth_pdata *pdata = dev_get_platdata(dev);
36135affd7aSSimon Glass 	eth_env_get_enetaddr("ethaddr", pdata->enetaddr);
362be71a179Srick 	return 0;
363be71a179Srick }
364be71a179Srick 
dtbmacaddr(u32 ifno)365be71a179Srick static const char *dtbmacaddr(u32 ifno)
366be71a179Srick {
367be71a179Srick 	int node, len;
368be71a179Srick 	char enet[16];
369be71a179Srick 	const char *mac;
370be71a179Srick 	const char *path;
371be71a179Srick 	if (gd->fdt_blob == NULL) {
372be71a179Srick 		printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
373be71a179Srick 		return NULL;
374be71a179Srick 	}
375be71a179Srick 	node = fdt_path_offset(gd->fdt_blob, "/aliases");
376be71a179Srick 	if (node < 0)
377be71a179Srick 		return NULL;
378be71a179Srick 
379be71a179Srick 	sprintf(enet, "ethernet%d", ifno);
380be71a179Srick 	path = fdt_getprop(gd->fdt_blob, node, enet, NULL);
381be71a179Srick 	if (!path) {
382be71a179Srick 		printf("no alias for %s\n", enet);
383be71a179Srick 		return NULL;
384be71a179Srick 	}
385be71a179Srick 	node = fdt_path_offset(gd->fdt_blob, path);
386be71a179Srick 	mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len);
387be71a179Srick 	if (mac && is_valid_ethaddr((u8 *)mac))
388be71a179Srick 		return mac;
389be71a179Srick 
390be71a179Srick 	return NULL;
391be71a179Srick }
392be71a179Srick 
ftmac100_ofdata_to_platdata(struct udevice * dev)393be71a179Srick static int ftmac100_ofdata_to_platdata(struct udevice *dev)
394be71a179Srick {
395be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
396be71a179Srick 	struct eth_pdata *pdata = dev_get_platdata(dev);
397be71a179Srick 	const char *mac;
398a821c4afSSimon Glass 	pdata->iobase = devfdt_get_addr(dev);
399be71a179Srick 	priv->iobase = pdata->iobase;
400be71a179Srick 	mac = dtbmacaddr(0);
401be71a179Srick 	if (mac)
402be71a179Srick 		memcpy(pdata->enetaddr , mac , 6);
403be71a179Srick 
404be71a179Srick 	return 0;
405be71a179Srick }
406be71a179Srick 
ftmac100_probe(struct udevice * dev)407be71a179Srick static int ftmac100_probe(struct udevice *dev)
408be71a179Srick {
409be71a179Srick 	struct ftmac100_data *priv = dev_get_priv(dev);
410be71a179Srick 	priv->name = dev->name;
411be71a179Srick 	return 0;
412be71a179Srick }
413be71a179Srick 
ftmac100_bind(struct udevice * dev)414be71a179Srick static int ftmac100_bind(struct udevice *dev)
415be71a179Srick {
416be71a179Srick 	return device_set_name(dev, dev->name);
417be71a179Srick }
418be71a179Srick 
419be71a179Srick static const struct eth_ops ftmac100_ops = {
420be71a179Srick 	.start	= ftmac100_start,
421be71a179Srick 	.send	= ftmac100_send,
422be71a179Srick 	.recv	= ftmac100_recv,
423be71a179Srick 	.stop	= ftmac100_stop,
424be71a179Srick 	.free_pkt = ftmac100_free_pkt,
425be71a179Srick };
426be71a179Srick 
427be71a179Srick static const struct udevice_id ftmac100_ids[] = {
428be71a179Srick 	{ .compatible = "andestech,atmac100" },
429be71a179Srick 	{ }
430be71a179Srick };
431be71a179Srick 
432be71a179Srick U_BOOT_DRIVER(ftmac100) = {
433be71a179Srick 	.name	= "nds32_mac",
434be71a179Srick 	.id	= UCLASS_ETH,
435be71a179Srick 	.of_match = ftmac100_ids,
436be71a179Srick 	.bind	= ftmac100_bind,
437be71a179Srick 	.ofdata_to_platdata = ftmac100_ofdata_to_platdata,
438be71a179Srick 	.probe	= ftmac100_probe,
439be71a179Srick 	.ops	= &ftmac100_ops,
440be71a179Srick 	.priv_auto_alloc_size = sizeof(struct ftmac100_data),
441be71a179Srick 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
442be71a179Srick 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
443be71a179Srick };
444be71a179Srick #endif
445