xref: /openbmc/u-boot/drivers/net/designware.c (revision c0982871)
1 /*
2  * (C) Copyright 2010
3  * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 /*
9  * Designware ethernet IP driver for U-Boot
10  */
11 
12 #include <common.h>
13 #include <dm.h>
14 #include <errno.h>
15 #include <miiphy.h>
16 #include <malloc.h>
17 #include <pci.h>
18 #include <linux/compiler.h>
19 #include <linux/err.h>
20 #include <asm/io.h>
21 #include "designware.h"
22 
23 DECLARE_GLOBAL_DATA_PTR;
24 
25 #if !defined(CONFIG_PHYLIB)
26 # error "DesignWare Ether MAC requires PHYLIB - missing CONFIG_PHYLIB"
27 #endif
28 
29 static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
30 {
31 	struct eth_mac_regs *mac_p = bus->priv;
32 	ulong start;
33 	u16 miiaddr;
34 	int timeout = CONFIG_MDIO_TIMEOUT;
35 
36 	miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
37 		  ((reg << MIIREGSHIFT) & MII_REGMSK);
38 
39 	writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
40 
41 	start = get_timer(0);
42 	while (get_timer(start) < timeout) {
43 		if (!(readl(&mac_p->miiaddr) & MII_BUSY))
44 			return readl(&mac_p->miidata);
45 		udelay(10);
46 	};
47 
48 	return -ETIMEDOUT;
49 }
50 
51 static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
52 			u16 val)
53 {
54 	struct eth_mac_regs *mac_p = bus->priv;
55 	ulong start;
56 	u16 miiaddr;
57 	int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
58 
59 	writel(val, &mac_p->miidata);
60 	miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
61 		  ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
62 
63 	writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
64 
65 	start = get_timer(0);
66 	while (get_timer(start) < timeout) {
67 		if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
68 			ret = 0;
69 			break;
70 		}
71 		udelay(10);
72 	};
73 
74 	return ret;
75 }
76 
77 static int dw_mdio_init(const char *name, struct eth_mac_regs *mac_regs_p)
78 {
79 	struct mii_dev *bus = mdio_alloc();
80 
81 	if (!bus) {
82 		printf("Failed to allocate MDIO bus\n");
83 		return -ENOMEM;
84 	}
85 
86 	bus->read = dw_mdio_read;
87 	bus->write = dw_mdio_write;
88 	snprintf(bus->name, sizeof(bus->name), name);
89 
90 	bus->priv = (void *)mac_regs_p;
91 
92 	return mdio_register(bus);
93 }
94 
95 static void tx_descs_init(struct dw_eth_dev *priv)
96 {
97 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
98 	struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
99 	char *txbuffs = &priv->txbuffs[0];
100 	struct dmamacdescr *desc_p;
101 	u32 idx;
102 
103 	for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
104 		desc_p = &desc_table_p[idx];
105 		desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
106 		desc_p->dmamac_next = &desc_table_p[idx + 1];
107 
108 #if defined(CONFIG_DW_ALTDESCRIPTOR)
109 		desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
110 				DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
111 				DESC_TXSTS_TXCHECKINSCTRL | \
112 				DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
113 
114 		desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
115 		desc_p->dmamac_cntl = 0;
116 		desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
117 #else
118 		desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
119 		desc_p->txrx_status = 0;
120 #endif
121 	}
122 
123 	/* Correcting the last pointer of the chain */
124 	desc_p->dmamac_next = &desc_table_p[0];
125 
126 	/* Flush all Tx buffer descriptors at once */
127 	flush_dcache_range((unsigned int)priv->tx_mac_descrtable,
128 			   (unsigned int)priv->tx_mac_descrtable +
129 			   sizeof(priv->tx_mac_descrtable));
130 
131 	writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
132 	priv->tx_currdescnum = 0;
133 }
134 
135 static void rx_descs_init(struct dw_eth_dev *priv)
136 {
137 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
138 	struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
139 	char *rxbuffs = &priv->rxbuffs[0];
140 	struct dmamacdescr *desc_p;
141 	u32 idx;
142 
143 	/* Before passing buffers to GMAC we need to make sure zeros
144 	 * written there right after "priv" structure allocation were
145 	 * flushed into RAM.
146 	 * Otherwise there's a chance to get some of them flushed in RAM when
147 	 * GMAC is already pushing data to RAM via DMA. This way incoming from
148 	 * GMAC data will be corrupted. */
149 	flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs +
150 			   RX_TOTAL_BUFSIZE);
151 
152 	for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
153 		desc_p = &desc_table_p[idx];
154 		desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
155 		desc_p->dmamac_next = &desc_table_p[idx + 1];
156 
157 		desc_p->dmamac_cntl =
158 			(MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
159 				      DESC_RXCTRL_RXCHAIN;
160 
161 		desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
162 	}
163 
164 	/* Correcting the last pointer of the chain */
165 	desc_p->dmamac_next = &desc_table_p[0];
166 
167 	/* Flush all Rx buffer descriptors at once */
168 	flush_dcache_range((unsigned int)priv->rx_mac_descrtable,
169 			   (unsigned int)priv->rx_mac_descrtable +
170 			   sizeof(priv->rx_mac_descrtable));
171 
172 	writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
173 	priv->rx_currdescnum = 0;
174 }
175 
176 static int _dw_write_hwaddr(struct dw_eth_dev *priv, u8 *mac_id)
177 {
178 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
179 	u32 macid_lo, macid_hi;
180 
181 	macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
182 		   (mac_id[3] << 24);
183 	macid_hi = mac_id[4] + (mac_id[5] << 8);
184 
185 	writel(macid_hi, &mac_p->macaddr0hi);
186 	writel(macid_lo, &mac_p->macaddr0lo);
187 
188 	return 0;
189 }
190 
191 static void dw_adjust_link(struct eth_mac_regs *mac_p,
192 			   struct phy_device *phydev)
193 {
194 	u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN;
195 
196 	if (!phydev->link) {
197 		printf("%s: No link.\n", phydev->dev->name);
198 		return;
199 	}
200 
201 	if (phydev->speed != 1000)
202 		conf |= MII_PORTSELECT;
203 
204 	if (phydev->speed == 100)
205 		conf |= FES_100;
206 
207 	if (phydev->duplex)
208 		conf |= FULLDPLXMODE;
209 
210 	writel(conf, &mac_p->conf);
211 
212 	printf("Speed: %d, %s duplex%s\n", phydev->speed,
213 	       (phydev->duplex) ? "full" : "half",
214 	       (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
215 }
216 
217 static void _dw_eth_halt(struct dw_eth_dev *priv)
218 {
219 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
220 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
221 
222 	writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf);
223 	writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode);
224 
225 	phy_shutdown(priv->phydev);
226 }
227 
228 static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr)
229 {
230 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
231 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
232 	unsigned int start;
233 	int ret;
234 
235 	writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
236 
237 	start = get_timer(0);
238 	while (readl(&dma_p->busmode) & DMAMAC_SRST) {
239 		if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
240 			printf("DMA reset timeout\n");
241 			return -ETIMEDOUT;
242 		}
243 
244 		mdelay(100);
245 	};
246 
247 	/*
248 	 * Soft reset above clears HW address registers.
249 	 * So we have to set it here once again.
250 	 */
251 	_dw_write_hwaddr(priv, enetaddr);
252 
253 	rx_descs_init(priv);
254 	tx_descs_init(priv);
255 
256 	writel(FIXEDBURST | PRIORXTX_41 | DMA_PBL, &dma_p->busmode);
257 
258 #ifndef CONFIG_DW_MAC_FORCE_THRESHOLD_MODE
259 	writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD,
260 	       &dma_p->opmode);
261 #else
262 	writel(readl(&dma_p->opmode) | FLUSHTXFIFO,
263 	       &dma_p->opmode);
264 #endif
265 
266 	writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode);
267 
268 #ifdef CONFIG_DW_AXI_BURST_LEN
269 	writel((CONFIG_DW_AXI_BURST_LEN & 0x1FF >> 1), &dma_p->axibus);
270 #endif
271 
272 	/* Start up the PHY */
273 	ret = phy_startup(priv->phydev);
274 	if (ret) {
275 		printf("Could not initialize PHY %s\n",
276 		       priv->phydev->dev->name);
277 		return ret;
278 	}
279 
280 	dw_adjust_link(mac_p, priv->phydev);
281 
282 	if (!priv->phydev->link)
283 		return -EIO;
284 
285 	writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
286 
287 	return 0;
288 }
289 
290 static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
291 {
292 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
293 	u32 desc_num = priv->tx_currdescnum;
294 	struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
295 	uint32_t desc_start = (uint32_t)desc_p;
296 	uint32_t desc_end = desc_start +
297 		roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
298 	uint32_t data_start = (uint32_t)desc_p->dmamac_addr;
299 	uint32_t data_end = data_start +
300 		roundup(length, ARCH_DMA_MINALIGN);
301 	/*
302 	 * Strictly we only need to invalidate the "txrx_status" field
303 	 * for the following check, but on some platforms we cannot
304 	 * invalidate only 4 bytes, so we flush the entire descriptor,
305 	 * which is 16 bytes in total. This is safe because the
306 	 * individual descriptors in the array are each aligned to
307 	 * ARCH_DMA_MINALIGN and padded appropriately.
308 	 */
309 	invalidate_dcache_range(desc_start, desc_end);
310 
311 	/* Check if the descriptor is owned by CPU */
312 	if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
313 		printf("CPU not owner of tx frame\n");
314 		return -EPERM;
315 	}
316 
317 	memcpy(desc_p->dmamac_addr, packet, length);
318 
319 	/* Flush data to be sent */
320 	flush_dcache_range(data_start, data_end);
321 
322 #if defined(CONFIG_DW_ALTDESCRIPTOR)
323 	desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
324 	desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
325 			       DESC_TXCTRL_SIZE1MASK;
326 
327 	desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
328 	desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
329 #else
330 	desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
331 			       DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
332 			       DESC_TXCTRL_TXFIRST;
333 
334 	desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
335 #endif
336 
337 	/* Flush modified buffer descriptor */
338 	flush_dcache_range(desc_start, desc_end);
339 
340 	/* Test the wrap-around condition. */
341 	if (++desc_num >= CONFIG_TX_DESCR_NUM)
342 		desc_num = 0;
343 
344 	priv->tx_currdescnum = desc_num;
345 
346 	/* Start the transmission */
347 	writel(POLL_DATA, &dma_p->txpolldemand);
348 
349 	return 0;
350 }
351 
352 static int _dw_eth_recv(struct dw_eth_dev *priv, uchar **packetp)
353 {
354 	u32 status, desc_num = priv->rx_currdescnum;
355 	struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
356 	int length = -EAGAIN;
357 	uint32_t desc_start = (uint32_t)desc_p;
358 	uint32_t desc_end = desc_start +
359 		roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
360 	uint32_t data_start = (uint32_t)desc_p->dmamac_addr;
361 	uint32_t data_end;
362 
363 	/* Invalidate entire buffer descriptor */
364 	invalidate_dcache_range(desc_start, desc_end);
365 
366 	status = desc_p->txrx_status;
367 
368 	/* Check  if the owner is the CPU */
369 	if (!(status & DESC_RXSTS_OWNBYDMA)) {
370 
371 		length = (status & DESC_RXSTS_FRMLENMSK) >> \
372 			 DESC_RXSTS_FRMLENSHFT;
373 
374 		/* Invalidate received data */
375 		data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
376 		invalidate_dcache_range(data_start, data_end);
377 		*packetp = desc_p->dmamac_addr;
378 	}
379 
380 	return length;
381 }
382 
383 static int _dw_free_pkt(struct dw_eth_dev *priv)
384 {
385 	u32 desc_num = priv->rx_currdescnum;
386 	struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
387 	uint32_t desc_start = (uint32_t)desc_p;
388 	uint32_t desc_end = desc_start +
389 		roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
390 
391 	/*
392 	 * Make the current descriptor valid again and go to
393 	 * the next one
394 	 */
395 	desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
396 
397 	/* Flush only status field - others weren't changed */
398 	flush_dcache_range(desc_start, desc_end);
399 
400 	/* Test the wrap-around condition. */
401 	if (++desc_num >= CONFIG_RX_DESCR_NUM)
402 		desc_num = 0;
403 	priv->rx_currdescnum = desc_num;
404 
405 	return 0;
406 }
407 
408 static int dw_phy_init(struct dw_eth_dev *priv, void *dev)
409 {
410 	struct phy_device *phydev;
411 	int mask = 0xffffffff;
412 
413 #ifdef CONFIG_PHY_ADDR
414 	mask = 1 << CONFIG_PHY_ADDR;
415 #endif
416 
417 	phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
418 	if (!phydev)
419 		return -ENODEV;
420 
421 	phy_connect_dev(phydev, dev);
422 
423 	phydev->supported &= PHY_GBIT_FEATURES;
424 	phydev->advertising = phydev->supported;
425 
426 	priv->phydev = phydev;
427 	phy_config(phydev);
428 
429 	return 0;
430 }
431 
432 #ifndef CONFIG_DM_ETH
433 static int dw_eth_init(struct eth_device *dev, bd_t *bis)
434 {
435 	return _dw_eth_init(dev->priv, dev->enetaddr);
436 }
437 
438 static int dw_eth_send(struct eth_device *dev, void *packet, int length)
439 {
440 	return _dw_eth_send(dev->priv, packet, length);
441 }
442 
443 static int dw_eth_recv(struct eth_device *dev)
444 {
445 	uchar *packet;
446 	int length;
447 
448 	length = _dw_eth_recv(dev->priv, &packet);
449 	if (length == -EAGAIN)
450 		return 0;
451 	net_process_received_packet(packet, length);
452 
453 	_dw_free_pkt(dev->priv);
454 
455 	return 0;
456 }
457 
458 static void dw_eth_halt(struct eth_device *dev)
459 {
460 	return _dw_eth_halt(dev->priv);
461 }
462 
463 static int dw_write_hwaddr(struct eth_device *dev)
464 {
465 	return _dw_write_hwaddr(dev->priv, dev->enetaddr);
466 }
467 
468 int designware_initialize(ulong base_addr, u32 interface)
469 {
470 	struct eth_device *dev;
471 	struct dw_eth_dev *priv;
472 
473 	dev = (struct eth_device *) malloc(sizeof(struct eth_device));
474 	if (!dev)
475 		return -ENOMEM;
476 
477 	/*
478 	 * Since the priv structure contains the descriptors which need a strict
479 	 * buswidth alignment, memalign is used to allocate memory
480 	 */
481 	priv = (struct dw_eth_dev *) memalign(ARCH_DMA_MINALIGN,
482 					      sizeof(struct dw_eth_dev));
483 	if (!priv) {
484 		free(dev);
485 		return -ENOMEM;
486 	}
487 
488 	memset(dev, 0, sizeof(struct eth_device));
489 	memset(priv, 0, sizeof(struct dw_eth_dev));
490 
491 	sprintf(dev->name, "dwmac.%lx", base_addr);
492 	dev->iobase = (int)base_addr;
493 	dev->priv = priv;
494 
495 	priv->dev = dev;
496 	priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
497 	priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
498 			DW_DMA_BASE_OFFSET);
499 
500 	dev->init = dw_eth_init;
501 	dev->send = dw_eth_send;
502 	dev->recv = dw_eth_recv;
503 	dev->halt = dw_eth_halt;
504 	dev->write_hwaddr = dw_write_hwaddr;
505 
506 	eth_register(dev);
507 
508 	priv->interface = interface;
509 
510 	dw_mdio_init(dev->name, priv->mac_regs_p);
511 	priv->bus = miiphy_get_dev_by_name(dev->name);
512 
513 	return dw_phy_init(priv, dev);
514 }
515 #endif
516 
517 #ifdef CONFIG_DM_ETH
518 static int designware_eth_start(struct udevice *dev)
519 {
520 	struct eth_pdata *pdata = dev_get_platdata(dev);
521 
522 	return _dw_eth_init(dev->priv, pdata->enetaddr);
523 }
524 
525 static int designware_eth_send(struct udevice *dev, void *packet, int length)
526 {
527 	struct dw_eth_dev *priv = dev_get_priv(dev);
528 
529 	return _dw_eth_send(priv, packet, length);
530 }
531 
532 static int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp)
533 {
534 	struct dw_eth_dev *priv = dev_get_priv(dev);
535 
536 	return _dw_eth_recv(priv, packetp);
537 }
538 
539 static int designware_eth_free_pkt(struct udevice *dev, uchar *packet,
540 				   int length)
541 {
542 	struct dw_eth_dev *priv = dev_get_priv(dev);
543 
544 	return _dw_free_pkt(priv);
545 }
546 
547 static void designware_eth_stop(struct udevice *dev)
548 {
549 	struct dw_eth_dev *priv = dev_get_priv(dev);
550 
551 	return _dw_eth_halt(priv);
552 }
553 
554 static int designware_eth_write_hwaddr(struct udevice *dev)
555 {
556 	struct eth_pdata *pdata = dev_get_platdata(dev);
557 	struct dw_eth_dev *priv = dev_get_priv(dev);
558 
559 	return _dw_write_hwaddr(priv, pdata->enetaddr);
560 }
561 
562 static int designware_eth_bind(struct udevice *dev)
563 {
564 #ifdef CONFIG_DM_PCI
565 	static int num_cards;
566 	char name[20];
567 
568 	/* Create a unique device name for PCI type devices */
569 	if (device_is_on_pci_bus(dev)) {
570 		sprintf(name, "eth_designware#%u", num_cards++);
571 		device_set_name(dev, name);
572 	}
573 #endif
574 
575 	return 0;
576 }
577 
578 static int designware_eth_probe(struct udevice *dev)
579 {
580 	struct eth_pdata *pdata = dev_get_platdata(dev);
581 	struct dw_eth_dev *priv = dev_get_priv(dev);
582 	u32 iobase = pdata->iobase;
583 	int ret;
584 
585 #ifdef CONFIG_DM_PCI
586 	/*
587 	 * If we are on PCI bus, either directly attached to a PCI root port,
588 	 * or via a PCI bridge, fill in platdata before we probe the hardware.
589 	 */
590 	if (device_is_on_pci_bus(dev)) {
591 		pci_dev_t bdf = pci_get_bdf(dev);
592 
593 		dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
594 		iobase &= PCI_BASE_ADDRESS_MEM_MASK;
595 		iobase = pci_mem_to_phys(bdf, iobase);
596 
597 		pdata->iobase = iobase;
598 		pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
599 	}
600 #endif
601 
602 	debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
603 	priv->mac_regs_p = (struct eth_mac_regs *)iobase;
604 	priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
605 	priv->interface = pdata->phy_interface;
606 
607 	dw_mdio_init(dev->name, priv->mac_regs_p);
608 	priv->bus = miiphy_get_dev_by_name(dev->name);
609 
610 	ret = dw_phy_init(priv, dev);
611 	debug("%s, ret=%d\n", __func__, ret);
612 
613 	return ret;
614 }
615 
616 static int designware_eth_remove(struct udevice *dev)
617 {
618 	struct dw_eth_dev *priv = dev_get_priv(dev);
619 
620 	free(priv->phydev);
621 	mdio_unregister(priv->bus);
622 	mdio_free(priv->bus);
623 
624 	return 0;
625 }
626 
627 static const struct eth_ops designware_eth_ops = {
628 	.start			= designware_eth_start,
629 	.send			= designware_eth_send,
630 	.recv			= designware_eth_recv,
631 	.free_pkt		= designware_eth_free_pkt,
632 	.stop			= designware_eth_stop,
633 	.write_hwaddr		= designware_eth_write_hwaddr,
634 };
635 
636 static int designware_eth_ofdata_to_platdata(struct udevice *dev)
637 {
638 	struct eth_pdata *pdata = dev_get_platdata(dev);
639 	const char *phy_mode;
640 
641 	pdata->iobase = dev_get_addr(dev);
642 	pdata->phy_interface = -1;
643 	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
644 	if (phy_mode)
645 		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
646 	if (pdata->phy_interface == -1) {
647 		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
648 		return -EINVAL;
649 	}
650 
651 	return 0;
652 }
653 
654 static const struct udevice_id designware_eth_ids[] = {
655 	{ .compatible = "allwinner,sun7i-a20-gmac" },
656 	{ .compatible = "altr,socfpga-stmmac" },
657 	{ }
658 };
659 
660 U_BOOT_DRIVER(eth_designware) = {
661 	.name	= "eth_designware",
662 	.id	= UCLASS_ETH,
663 	.of_match = designware_eth_ids,
664 	.ofdata_to_platdata = designware_eth_ofdata_to_platdata,
665 	.bind	= designware_eth_bind,
666 	.probe	= designware_eth_probe,
667 	.remove	= designware_eth_remove,
668 	.ops	= &designware_eth_ops,
669 	.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
670 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
671 	.flags = DM_FLAG_ALLOC_PRIV_DMA,
672 };
673 
674 static struct pci_device_id supported[] = {
675 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
676 	{ }
677 };
678 
679 U_BOOT_PCI_DEVICE(eth_designware, supported);
680 #endif
681