xref: /openbmc/u-boot/drivers/net/designware.c (revision 983c72f4)
1 /*
2  * (C) Copyright 2010
3  * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 /*
25  * Designware ethernet IP driver for u-boot
26  */
27 
28 #include <common.h>
29 #include <miiphy.h>
30 #include <malloc.h>
31 #include <linux/compiler.h>
32 #include <linux/err.h>
33 #include <asm/io.h>
34 #include "designware.h"
35 
36 static int configure_phy(struct eth_device *dev);
37 
38 static void tx_descs_init(struct eth_device *dev)
39 {
40 	struct dw_eth_dev *priv = dev->priv;
41 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
42 	struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
43 	char *txbuffs = &priv->txbuffs[0];
44 	struct dmamacdescr *desc_p;
45 	u32 idx;
46 
47 	for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
48 		desc_p = &desc_table_p[idx];
49 		desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
50 		desc_p->dmamac_next = &desc_table_p[idx + 1];
51 
52 #if defined(CONFIG_DW_ALTDESCRIPTOR)
53 		desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
54 				DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
55 				DESC_TXSTS_TXCHECKINSCTRL | \
56 				DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
57 
58 		desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
59 		desc_p->dmamac_cntl = 0;
60 		desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
61 #else
62 		desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
63 		desc_p->txrx_status = 0;
64 #endif
65 	}
66 
67 	/* Correcting the last pointer of the chain */
68 	desc_p->dmamac_next = &desc_table_p[0];
69 
70 	writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
71 }
72 
73 static void rx_descs_init(struct eth_device *dev)
74 {
75 	struct dw_eth_dev *priv = dev->priv;
76 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
77 	struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
78 	char *rxbuffs = &priv->rxbuffs[0];
79 	struct dmamacdescr *desc_p;
80 	u32 idx;
81 
82 	for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
83 		desc_p = &desc_table_p[idx];
84 		desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
85 		desc_p->dmamac_next = &desc_table_p[idx + 1];
86 
87 		desc_p->dmamac_cntl =
88 			(MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
89 				      DESC_RXCTRL_RXCHAIN;
90 
91 		desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
92 	}
93 
94 	/* Correcting the last pointer of the chain */
95 	desc_p->dmamac_next = &desc_table_p[0];
96 
97 	writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
98 }
99 
100 static void descs_init(struct eth_device *dev)
101 {
102 	tx_descs_init(dev);
103 	rx_descs_init(dev);
104 }
105 
106 static int mac_reset(struct eth_device *dev)
107 {
108 	struct dw_eth_dev *priv = dev->priv;
109 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
110 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
111 
112 	ulong start;
113 	int timeout = CONFIG_MACRESET_TIMEOUT;
114 
115 	writel(DMAMAC_SRST, &dma_p->busmode);
116 
117 	if (priv->interface != PHY_INTERFACE_MODE_RGMII)
118 		writel(MII_PORTSELECT, &mac_p->conf);
119 
120 	start = get_timer(0);
121 	while (get_timer(start) < timeout) {
122 		if (!(readl(&dma_p->busmode) & DMAMAC_SRST))
123 			return 0;
124 
125 		/* Try again after 10usec */
126 		udelay(10);
127 	};
128 
129 	return -1;
130 }
131 
132 static int dw_write_hwaddr(struct eth_device *dev)
133 {
134 	struct dw_eth_dev *priv = dev->priv;
135 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
136 	u32 macid_lo, macid_hi;
137 	u8 *mac_id = &dev->enetaddr[0];
138 
139 	macid_lo = mac_id[0] + (mac_id[1] << 8) + \
140 		   (mac_id[2] << 16) + (mac_id[3] << 24);
141 	macid_hi = mac_id[4] + (mac_id[5] << 8);
142 
143 	writel(macid_hi, &mac_p->macaddr0hi);
144 	writel(macid_lo, &mac_p->macaddr0lo);
145 
146 	return 0;
147 }
148 
149 static int dw_eth_init(struct eth_device *dev, bd_t *bis)
150 {
151 	struct dw_eth_dev *priv = dev->priv;
152 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
153 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
154 	u32 conf;
155 
156 	if (priv->phy_configured != 1)
157 		configure_phy(dev);
158 
159 	/* Print link status only once */
160 	if (!priv->link_printed) {
161 		printf("ENET Speed is %d Mbps - %s duplex connection\n",
162 		       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
163 		priv->link_printed = 1;
164 	}
165 
166 	/* Reset ethernet hardware */
167 	if (mac_reset(dev) < 0)
168 		return -1;
169 
170 	/* Resore the HW MAC address as it has been lost during MAC reset */
171 	dw_write_hwaddr(dev);
172 
173 	writel(FIXEDBURST | PRIORXTX_41 | BURST_16,
174 			&dma_p->busmode);
175 
176 	writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD |
177 		TXSECONDFRAME, &dma_p->opmode);
178 
179 	conf = FRAMEBURSTENABLE | DISABLERXOWN;
180 
181 	if (priv->speed != 1000)
182 		conf |= MII_PORTSELECT;
183 
184 	if ((priv->interface != PHY_INTERFACE_MODE_MII) &&
185 		(priv->interface != PHY_INTERFACE_MODE_GMII)) {
186 
187 		if (priv->speed == 100)
188 			conf |= FES_100;
189 	}
190 
191 	if (priv->duplex == FULL)
192 		conf |= FULLDPLXMODE;
193 
194 	writel(conf, &mac_p->conf);
195 
196 	descs_init(dev);
197 
198 	/*
199 	 * Start/Enable xfer at dma as well as mac level
200 	 */
201 	writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode);
202 	writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode);
203 
204 	writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
205 
206 	return 0;
207 }
208 
209 static int dw_eth_send(struct eth_device *dev, void *packet, int length)
210 {
211 	struct dw_eth_dev *priv = dev->priv;
212 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
213 	u32 desc_num = priv->tx_currdescnum;
214 	struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
215 
216 	/* Check if the descriptor is owned by CPU */
217 	if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
218 		printf("CPU not owner of tx frame\n");
219 		return -1;
220 	}
221 
222 	memcpy((void *)desc_p->dmamac_addr, packet, length);
223 
224 #if defined(CONFIG_DW_ALTDESCRIPTOR)
225 	desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
226 	desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
227 			       DESC_TXCTRL_SIZE1MASK;
228 
229 	desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
230 	desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
231 #else
232 	desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
233 			       DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
234 			       DESC_TXCTRL_TXFIRST;
235 
236 	desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
237 #endif
238 
239 	/* Test the wrap-around condition. */
240 	if (++desc_num >= CONFIG_TX_DESCR_NUM)
241 		desc_num = 0;
242 
243 	priv->tx_currdescnum = desc_num;
244 
245 	/* Start the transmission */
246 	writel(POLL_DATA, &dma_p->txpolldemand);
247 
248 	return 0;
249 }
250 
251 static int dw_eth_recv(struct eth_device *dev)
252 {
253 	struct dw_eth_dev *priv = dev->priv;
254 	u32 desc_num = priv->rx_currdescnum;
255 	struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
256 
257 	u32 status = desc_p->txrx_status;
258 	int length = 0;
259 
260 	/* Check  if the owner is the CPU */
261 	if (!(status & DESC_RXSTS_OWNBYDMA)) {
262 
263 		length = (status & DESC_RXSTS_FRMLENMSK) >> \
264 			 DESC_RXSTS_FRMLENSHFT;
265 
266 		NetReceive(desc_p->dmamac_addr, length);
267 
268 		/*
269 		 * Make the current descriptor valid again and go to
270 		 * the next one
271 		 */
272 		desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
273 
274 		/* Test the wrap-around condition. */
275 		if (++desc_num >= CONFIG_RX_DESCR_NUM)
276 			desc_num = 0;
277 	}
278 
279 	priv->rx_currdescnum = desc_num;
280 
281 	return length;
282 }
283 
284 static void dw_eth_halt(struct eth_device *dev)
285 {
286 	struct dw_eth_dev *priv = dev->priv;
287 
288 	mac_reset(dev);
289 	priv->tx_currdescnum = priv->rx_currdescnum = 0;
290 }
291 
292 static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val)
293 {
294 	struct dw_eth_dev *priv = dev->priv;
295 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
296 	ulong start;
297 	u32 miiaddr;
298 	int timeout = CONFIG_MDIO_TIMEOUT;
299 
300 	miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
301 		  ((reg << MIIREGSHIFT) & MII_REGMSK);
302 
303 	writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
304 
305 	start = get_timer(0);
306 	while (get_timer(start) < timeout) {
307 		if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
308 			*val = readl(&mac_p->miidata);
309 			return 0;
310 		}
311 
312 		/* Try again after 10usec */
313 		udelay(10);
314 	};
315 
316 	return -1;
317 }
318 
319 static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val)
320 {
321 	struct dw_eth_dev *priv = dev->priv;
322 	struct eth_mac_regs *mac_p = priv->mac_regs_p;
323 	ulong start;
324 	u32 miiaddr;
325 	int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
326 	u16 value;
327 
328 	writel(val, &mac_p->miidata);
329 	miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
330 		  ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
331 
332 	writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
333 
334 	start = get_timer(0);
335 	while (get_timer(start) < timeout) {
336 		if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
337 			ret = 0;
338 			break;
339 		}
340 
341 		/* Try again after 10usec */
342 		udelay(10);
343 	};
344 
345 	/* Needed as a fix for ST-Phy */
346 	eth_mdio_read(dev, addr, reg, &value);
347 
348 	return ret;
349 }
350 
351 #if defined(CONFIG_DW_SEARCH_PHY)
352 static int find_phy(struct eth_device *dev)
353 {
354 	int phy_addr = 0;
355 	u16 ctrl, oldctrl;
356 
357 	do {
358 		eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
359 		oldctrl = ctrl & BMCR_ANENABLE;
360 
361 		ctrl ^= BMCR_ANENABLE;
362 		eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl);
363 		eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
364 		ctrl &= BMCR_ANENABLE;
365 
366 		if (ctrl == oldctrl) {
367 			phy_addr++;
368 		} else {
369 			ctrl ^= BMCR_ANENABLE;
370 			eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl);
371 
372 			return phy_addr;
373 		}
374 	} while (phy_addr < 32);
375 
376 	return -1;
377 }
378 #endif
379 
380 static int dw_reset_phy(struct eth_device *dev)
381 {
382 	struct dw_eth_dev *priv = dev->priv;
383 	u16 ctrl;
384 	ulong start;
385 	int timeout = CONFIG_PHYRESET_TIMEOUT;
386 	u32 phy_addr = priv->address;
387 
388 	eth_mdio_write(dev, phy_addr, MII_BMCR, BMCR_RESET);
389 
390 	start = get_timer(0);
391 	while (get_timer(start) < timeout) {
392 		eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
393 		if (!(ctrl & BMCR_RESET))
394 			break;
395 
396 		/* Try again after 10usec */
397 		udelay(10);
398 	};
399 
400 	if (get_timer(start) >= CONFIG_PHYRESET_TIMEOUT)
401 		return -1;
402 
403 #ifdef CONFIG_PHY_RESET_DELAY
404 	udelay(CONFIG_PHY_RESET_DELAY);
405 #endif
406 	return 0;
407 }
408 
409 /*
410  * Add weak default function for board specific PHY configuration
411  */
412 int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr,
413 		int (*mii_write)(struct eth_device *, u8, u8, u16),
414 		int dw_reset_phy(struct eth_device *))
415 {
416 	return 0;
417 }
418 
419 static int configure_phy(struct eth_device *dev)
420 {
421 	struct dw_eth_dev *priv = dev->priv;
422 	int phy_addr;
423 	u16 bmcr;
424 #if defined(CONFIG_DW_AUTONEG)
425 	u16 bmsr;
426 	u32 timeout;
427 	ulong start;
428 #endif
429 
430 #if defined(CONFIG_DW_SEARCH_PHY)
431 	phy_addr = find_phy(dev);
432 	if (phy_addr >= 0)
433 		priv->address = phy_addr;
434 	else
435 		return -1;
436 #else
437 	phy_addr = priv->address;
438 #endif
439 
440 	/*
441 	 * Some boards need board specific PHY initialization. This is
442 	 * after the main driver init code but before the auto negotiation
443 	 * is run.
444 	 */
445 	if (designware_board_phy_init(dev, phy_addr,
446 				      eth_mdio_write, dw_reset_phy) < 0)
447 		return -1;
448 
449 	if (dw_reset_phy(dev) < 0)
450 		return -1;
451 
452 #if defined(CONFIG_DW_AUTONEG)
453 	/* Set Auto-Neg Advertisement capabilities to 10/100 half/full */
454 	eth_mdio_write(dev, phy_addr, MII_ADVERTISE, 0x1E1);
455 
456 	bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
457 #else
458 	bmcr = BMCR_SPEED100 | BMCR_FULLDPLX;
459 
460 #if defined(CONFIG_DW_SPEED10M)
461 	bmcr &= ~BMCR_SPEED100;
462 #endif
463 #if defined(CONFIG_DW_DUPLEXHALF)
464 	bmcr &= ~BMCR_FULLDPLX;
465 #endif
466 #endif
467 	if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0)
468 		return -1;
469 
470 	/* Read the phy status register and populate priv structure */
471 #if defined(CONFIG_DW_AUTONEG)
472 	timeout = CONFIG_AUTONEG_TIMEOUT;
473 	start = get_timer(0);
474 	puts("Waiting for PHY auto negotiation to complete");
475 	while (get_timer(start) < timeout) {
476 		eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
477 		if (bmsr & BMSR_ANEGCOMPLETE) {
478 			priv->phy_configured = 1;
479 			break;
480 		}
481 
482 		/* Print dot all 1s to show progress */
483 		if ((get_timer(start) % 1000) == 0)
484 			putc('.');
485 
486 		/* Try again after 1msec */
487 		udelay(1000);
488 	};
489 
490 	if (!(bmsr & BMSR_ANEGCOMPLETE))
491 		puts(" TIMEOUT!\n");
492 	else
493 		puts(" done\n");
494 #else
495 	priv->phy_configured = 1;
496 #endif
497 
498 	priv->speed = miiphy_speed(dev->name, phy_addr);
499 	priv->duplex = miiphy_duplex(dev->name, phy_addr);
500 
501 	return 0;
502 }
503 
504 #if defined(CONFIG_MII)
505 static int dw_mii_read(const char *devname, u8 addr, u8 reg, u16 *val)
506 {
507 	struct eth_device *dev;
508 
509 	dev = eth_get_dev_by_name(devname);
510 	if (dev)
511 		eth_mdio_read(dev, addr, reg, val);
512 
513 	return 0;
514 }
515 
516 static int dw_mii_write(const char *devname, u8 addr, u8 reg, u16 val)
517 {
518 	struct eth_device *dev;
519 
520 	dev = eth_get_dev_by_name(devname);
521 	if (dev)
522 		eth_mdio_write(dev, addr, reg, val);
523 
524 	return 0;
525 }
526 #endif
527 
528 int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface)
529 {
530 	struct eth_device *dev;
531 	struct dw_eth_dev *priv;
532 
533 	dev = (struct eth_device *) malloc(sizeof(struct eth_device));
534 	if (!dev)
535 		return -ENOMEM;
536 
537 	/*
538 	 * Since the priv structure contains the descriptors which need a strict
539 	 * buswidth alignment, memalign is used to allocate memory
540 	 */
541 	priv = (struct dw_eth_dev *) memalign(16, sizeof(struct dw_eth_dev));
542 	if (!priv) {
543 		free(dev);
544 		return -ENOMEM;
545 	}
546 
547 	memset(dev, 0, sizeof(struct eth_device));
548 	memset(priv, 0, sizeof(struct dw_eth_dev));
549 
550 	sprintf(dev->name, "mii%d", id);
551 	dev->iobase = (int)base_addr;
552 	dev->priv = priv;
553 
554 	eth_getenv_enetaddr_by_index("eth", id, &dev->enetaddr[0]);
555 
556 	priv->dev = dev;
557 	priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
558 	priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
559 			DW_DMA_BASE_OFFSET);
560 	priv->address = phy_addr;
561 	priv->phy_configured = 0;
562 	priv->interface = interface;
563 
564 	dev->init = dw_eth_init;
565 	dev->send = dw_eth_send;
566 	dev->recv = dw_eth_recv;
567 	dev->halt = dw_eth_halt;
568 	dev->write_hwaddr = dw_write_hwaddr;
569 
570 	eth_register(dev);
571 
572 #if defined(CONFIG_MII)
573 	miiphy_register(dev->name, dw_mii_read, dw_mii_write);
574 #endif
575 	return 1;
576 }
577