3 * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
25 * Designware ethernet IP driver for u-boot
31 #include <linux/err.h>
33 #include "designware.h"
35 static int configure_phy(struct eth_device
*dev
);
37 static void tx_descs_init(struct eth_device
*dev
)
39 struct dw_eth_dev
*priv
= dev
->priv
;
40 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
41 struct dmamacdescr
*desc_table_p
= &priv
->tx_mac_descrtable
[0];
42 char *txbuffs
= &priv
->txbuffs
[0];
43 struct dmamacdescr
*desc_p
;
46 for (idx
= 0; idx
< CONFIG_TX_DESCR_NUM
; idx
++) {
47 desc_p
= &desc_table_p
[idx
];
48 desc_p
->dmamac_addr
= &txbuffs
[idx
* CONFIG_ETH_BUFSIZE
];
49 desc_p
->dmamac_next
= &desc_table_p
[idx
+ 1];
51 #if defined(CONFIG_DW_ALTDESCRIPTOR)
52 desc_p
->txrx_status
&= ~(DESC_TXSTS_TXINT
| DESC_TXSTS_TXLAST
|
53 DESC_TXSTS_TXFIRST
| DESC_TXSTS_TXCRCDIS
| \
54 DESC_TXSTS_TXCHECKINSCTRL
| \
55 DESC_TXSTS_TXRINGEND
| DESC_TXSTS_TXPADDIS
);
57 desc_p
->txrx_status
|= DESC_TXSTS_TXCHAIN
;
58 desc_p
->dmamac_cntl
= 0;
59 desc_p
->txrx_status
&= ~(DESC_TXSTS_MSK
| DESC_TXSTS_OWNBYDMA
);
61 desc_p
->dmamac_cntl
= DESC_TXCTRL_TXCHAIN
;
62 desc_p
->txrx_status
= 0;
66 /* Correcting the last pointer of the chain */
67 desc_p
->dmamac_next
= &desc_table_p
[0];
69 writel((ulong
)&desc_table_p
[0], &dma_p
->txdesclistaddr
);
72 static void rx_descs_init(struct eth_device
*dev
)
74 struct dw_eth_dev
*priv
= dev
->priv
;
75 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
76 struct dmamacdescr
*desc_table_p
= &priv
->rx_mac_descrtable
[0];
77 char *rxbuffs
= &priv
->rxbuffs
[0];
78 struct dmamacdescr
*desc_p
;
81 for (idx
= 0; idx
< CONFIG_RX_DESCR_NUM
; idx
++) {
82 desc_p
= &desc_table_p
[idx
];
83 desc_p
->dmamac_addr
= &rxbuffs
[idx
* CONFIG_ETH_BUFSIZE
];
84 desc_p
->dmamac_next
= &desc_table_p
[idx
+ 1];
87 (MAC_MAX_FRAME_SZ
& DESC_RXCTRL_SIZE1MASK
) | \
90 desc_p
->txrx_status
= DESC_RXSTS_OWNBYDMA
;
93 /* Correcting the last pointer of the chain */
94 desc_p
->dmamac_next
= &desc_table_p
[0];
96 writel((ulong
)&desc_table_p
[0], &dma_p
->rxdesclistaddr
);
99 static void descs_init(struct eth_device
*dev
)
105 static int mac_reset(struct eth_device
*dev
)
107 struct dw_eth_dev
*priv
= dev
->priv
;
108 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
109 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
112 int timeout
= CONFIG_MACRESET_TIMEOUT
;
114 writel(DMAMAC_SRST
, &dma_p
->busmode
);
115 writel(MII_PORTSELECT
, &mac_p
->conf
);
117 start
= get_timer(0);
118 while (get_timer(start
) < timeout
) {
119 if (!(readl(&dma_p
->busmode
) & DMAMAC_SRST
))
122 /* Try again after 10usec */
129 static int dw_write_hwaddr(struct eth_device
*dev
)
131 struct dw_eth_dev
*priv
= dev
->priv
;
132 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
133 u32 macid_lo
, macid_hi
;
134 u8
*mac_id
= &dev
->enetaddr
[0];
136 macid_lo
= mac_id
[0] + (mac_id
[1] << 8) + \
137 (mac_id
[2] << 16) + (mac_id
[3] << 24);
138 macid_hi
= mac_id
[4] + (mac_id
[5] << 8);
140 writel(macid_hi
, &mac_p
->macaddr0hi
);
141 writel(macid_lo
, &mac_p
->macaddr0lo
);
146 static int dw_eth_init(struct eth_device
*dev
, bd_t
*bis
)
148 struct dw_eth_dev
*priv
= dev
->priv
;
149 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
150 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
153 if (priv
->phy_configured
!= 1)
156 /* Reset ethernet hardware */
157 if (mac_reset(dev
) < 0)
160 /* Resore the HW MAC address as it has been lost during MAC reset */
161 dw_write_hwaddr(dev
);
163 writel(FIXEDBURST
| PRIORXTX_41
| BURST_16
,
166 writel(FLUSHTXFIFO
| readl(&dma_p
->opmode
), &dma_p
->opmode
);
167 writel(STOREFORWARD
| TXSECONDFRAME
, &dma_p
->opmode
);
169 conf
= FRAMEBURSTENABLE
| DISABLERXOWN
;
171 if (priv
->speed
!= SPEED_1000M
)
172 conf
|= MII_PORTSELECT
;
174 if (priv
->duplex
== FULL_DUPLEX
)
175 conf
|= FULLDPLXMODE
;
177 writel(conf
, &mac_p
->conf
);
182 * Start/Enable xfer at dma as well as mac level
184 writel(readl(&dma_p
->opmode
) | RXSTART
, &dma_p
->opmode
);
185 writel(readl(&dma_p
->opmode
) | TXSTART
, &dma_p
->opmode
);
187 writel(readl(&mac_p
->conf
) | RXENABLE
| TXENABLE
, &mac_p
->conf
);
192 static int dw_eth_send(struct eth_device
*dev
, volatile void *packet
,
195 struct dw_eth_dev
*priv
= dev
->priv
;
196 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
197 u32 desc_num
= priv
->tx_currdescnum
;
198 struct dmamacdescr
*desc_p
= &priv
->tx_mac_descrtable
[desc_num
];
200 /* Check if the descriptor is owned by CPU */
201 if (desc_p
->txrx_status
& DESC_TXSTS_OWNBYDMA
) {
202 printf("CPU not owner of tx frame\n");
206 memcpy((void *)desc_p
->dmamac_addr
, (void *)packet
, length
);
208 #if defined(CONFIG_DW_ALTDESCRIPTOR)
209 desc_p
->txrx_status
|= DESC_TXSTS_TXFIRST
| DESC_TXSTS_TXLAST
;
210 desc_p
->dmamac_cntl
|= (length
<< DESC_TXCTRL_SIZE1SHFT
) & \
211 DESC_TXCTRL_SIZE1MASK
;
213 desc_p
->txrx_status
&= ~(DESC_TXSTS_MSK
);
214 desc_p
->txrx_status
|= DESC_TXSTS_OWNBYDMA
;
216 desc_p
->dmamac_cntl
|= ((length
<< DESC_TXCTRL_SIZE1SHFT
) & \
217 DESC_TXCTRL_SIZE1MASK
) | DESC_TXCTRL_TXLAST
| \
220 desc_p
->txrx_status
= DESC_TXSTS_OWNBYDMA
;
223 /* Test the wrap-around condition. */
224 if (++desc_num
>= CONFIG_TX_DESCR_NUM
)
227 priv
->tx_currdescnum
= desc_num
;
229 /* Start the transmission */
230 writel(POLL_DATA
, &dma_p
->txpolldemand
);
235 static int dw_eth_recv(struct eth_device
*dev
)
237 struct dw_eth_dev
*priv
= dev
->priv
;
238 u32 desc_num
= priv
->rx_currdescnum
;
239 struct dmamacdescr
*desc_p
= &priv
->rx_mac_descrtable
[desc_num
];
241 u32 status
= desc_p
->txrx_status
;
244 /* Check if the owner is the CPU */
245 if (!(status
& DESC_RXSTS_OWNBYDMA
)) {
247 length
= (status
& DESC_RXSTS_FRMLENMSK
) >> \
248 DESC_RXSTS_FRMLENSHFT
;
250 NetReceive(desc_p
->dmamac_addr
, length
);
253 * Make the current descriptor valid again and go to
256 desc_p
->txrx_status
|= DESC_RXSTS_OWNBYDMA
;
258 /* Test the wrap-around condition. */
259 if (++desc_num
>= CONFIG_RX_DESCR_NUM
)
263 priv
->rx_currdescnum
= desc_num
;
268 static void dw_eth_halt(struct eth_device
*dev
)
270 struct dw_eth_dev
*priv
= dev
->priv
;
273 priv
->tx_currdescnum
= priv
->rx_currdescnum
= 0;
276 static int eth_mdio_read(struct eth_device
*dev
, u8 addr
, u8 reg
, u16
*val
)
278 struct dw_eth_dev
*priv
= dev
->priv
;
279 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
282 int timeout
= CONFIG_MDIO_TIMEOUT
;
284 miiaddr
= ((addr
<< MIIADDRSHIFT
) & MII_ADDRMSK
) | \
285 ((reg
<< MIIREGSHIFT
) & MII_REGMSK
);
287 writel(miiaddr
| MII_CLKRANGE_150_250M
| MII_BUSY
, &mac_p
->miiaddr
);
289 start
= get_timer(0);
290 while (get_timer(start
) < timeout
) {
291 if (!(readl(&mac_p
->miiaddr
) & MII_BUSY
)) {
292 *val
= readl(&mac_p
->miidata
);
296 /* Try again after 10usec */
303 static int eth_mdio_write(struct eth_device
*dev
, u8 addr
, u8 reg
, u16 val
)
305 struct dw_eth_dev
*priv
= dev
->priv
;
306 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
309 int ret
= -1, timeout
= CONFIG_MDIO_TIMEOUT
;
312 writel(val
, &mac_p
->miidata
);
313 miiaddr
= ((addr
<< MIIADDRSHIFT
) & MII_ADDRMSK
) | \
314 ((reg
<< MIIREGSHIFT
) & MII_REGMSK
) | MII_WRITE
;
316 writel(miiaddr
| MII_CLKRANGE_150_250M
| MII_BUSY
, &mac_p
->miiaddr
);
318 start
= get_timer(0);
319 while (get_timer(start
) < timeout
) {
320 if (!(readl(&mac_p
->miiaddr
) & MII_BUSY
)) {
325 /* Try again after 10usec */
329 /* Needed as a fix for ST-Phy */
330 eth_mdio_read(dev
, addr
, reg
, &value
);
335 #if defined(CONFIG_DW_SEARCH_PHY)
336 static int find_phy(struct eth_device
*dev
)
342 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
343 oldctrl
= ctrl
& BMCR_ANENABLE
;
345 ctrl
^= BMCR_ANENABLE
;
346 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, ctrl
);
347 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
348 ctrl
&= BMCR_ANENABLE
;
350 if (ctrl
== oldctrl
) {
353 ctrl
^= BMCR_ANENABLE
;
354 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, ctrl
);
358 } while (phy_addr
< 32);
364 static int dw_reset_phy(struct eth_device
*dev
)
366 struct dw_eth_dev
*priv
= dev
->priv
;
369 int timeout
= CONFIG_PHYRESET_TIMEOUT
;
370 u32 phy_addr
= priv
->address
;
372 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, BMCR_RESET
);
374 start
= get_timer(0);
375 while (get_timer(start
) < timeout
) {
376 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
377 if (!(ctrl
& BMCR_RESET
))
380 /* Try again after 10usec */
384 if (get_timer(start
) >= CONFIG_PHYRESET_TIMEOUT
)
387 #ifdef CONFIG_PHY_RESET_DELAY
388 udelay(CONFIG_PHY_RESET_DELAY
);
393 static int configure_phy(struct eth_device
*dev
)
395 struct dw_eth_dev
*priv
= dev
->priv
;
398 #if defined(CONFIG_DW_AUTONEG)
407 #if defined(CONFIG_DW_SEARCH_PHY)
408 phy_addr
= find_phy(dev
);
410 priv
->address
= phy_addr
;
414 phy_addr
= priv
->address
;
416 if (dw_reset_phy(dev
) < 0)
419 #if defined(CONFIG_DW_AUTONEG)
420 /* Set Auto-Neg Advertisement capabilities to 10/100 half/full */
421 eth_mdio_write(dev
, phy_addr
, MII_ADVERTISE
, 0x1E1);
423 bmcr
= BMCR_ANENABLE
| BMCR_ANRESTART
;
425 bmcr
= BMCR_SPEED100
| BMCR_FULLDPLX
;
427 #if defined(CONFIG_DW_SPEED10M)
428 bmcr
&= ~BMCR_SPEED100
;
430 #if defined(CONFIG_DW_DUPLEXHALF)
431 bmcr
&= ~BMCR_FULLDPLX
;
434 if (eth_mdio_write(dev
, phy_addr
, MII_BMCR
, bmcr
) < 0)
437 /* Read the phy status register and populate priv structure */
438 #if defined(CONFIG_DW_AUTONEG)
439 timeout
= CONFIG_AUTONEG_TIMEOUT
;
440 start
= get_timer(0);
442 while (get_timer(start
) < timeout
) {
443 eth_mdio_read(dev
, phy_addr
, MII_BMSR
, &bmsr
);
444 if (bmsr
& BMSR_ANEGCOMPLETE
)
447 /* Try again after 10usec */
451 eth_mdio_read(dev
, phy_addr
, MII_LPA
, &anlpar
);
452 eth_mdio_read(dev
, phy_addr
, MII_STAT1000
, &btsr
);
454 if (bmsr
& BMSR_ANEGCOMPLETE
) {
455 if (btsr
& PHY_1000BTSR_1000FD
) {
456 priv
->speed
= SPEED_1000M
;
457 bmcr
|= BMCR_SPEED1000
;
458 priv
->duplex
= FULL_DUPLEX
;
459 bmcr
|= BMCR_FULLDPLX
;
460 } else if (btsr
& PHY_1000BTSR_1000HD
) {
461 priv
->speed
= SPEED_1000M
;
462 bmcr
|= BMCR_SPEED1000
;
463 priv
->duplex
= HALF_DUPLEX
;
464 bmcr
&= ~BMCR_FULLDPLX
;
465 } else if (anlpar
& LPA_100FULL
) {
466 priv
->speed
= SPEED_100M
;
467 bmcr
|= BMCR_SPEED100
;
468 priv
->duplex
= FULL_DUPLEX
;
469 bmcr
|= BMCR_FULLDPLX
;
470 } else if (anlpar
& LPA_100HALF
) {
471 priv
->speed
= SPEED_100M
;
472 bmcr
|= BMCR_SPEED100
;
473 priv
->duplex
= HALF_DUPLEX
;
474 bmcr
&= ~BMCR_FULLDPLX
;
475 } else if (anlpar
& LPA_10FULL
) {
476 priv
->speed
= SPEED_10M
;
477 bmcr
&= ~BMCR_SPEED100
;
478 priv
->duplex
= FULL_DUPLEX
;
479 bmcr
|= BMCR_FULLDPLX
;
481 priv
->speed
= SPEED_10M
;
482 bmcr
&= ~BMCR_SPEED100
;
483 priv
->duplex
= HALF_DUPLEX
;
484 bmcr
&= ~BMCR_FULLDPLX
;
486 if (eth_mdio_write(dev
, phy_addr
, MII_BMCR
, bmcr
) < 0)
491 if (eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
) < 0)
494 if (ctrl
& BMCR_FULLDPLX
)
495 priv
->duplex
= FULL_DUPLEX
;
497 priv
->duplex
= HALF_DUPLEX
;
499 if (ctrl
& BMCR_SPEED1000
)
500 priv
->speed
= SPEED_1000M
;
501 else if (ctrl
& BMCR_SPEED100
)
502 priv
->speed
= SPEED_100M
;
504 priv
->speed
= SPEED_10M
;
506 priv
->phy_configured
= 1;
511 #if defined(CONFIG_MII)
512 static int dw_mii_read(const char *devname
, u8 addr
, u8 reg
, u16
*val
)
514 struct eth_device
*dev
;
516 dev
= eth_get_dev_by_name(devname
);
518 eth_mdio_read(dev
, addr
, reg
, val
);
523 static int dw_mii_write(const char *devname
, u8 addr
, u8 reg
, u16 val
)
525 struct eth_device
*dev
;
527 dev
= eth_get_dev_by_name(devname
);
529 eth_mdio_write(dev
, addr
, reg
, val
);
535 int designware_initialize(u32 id
, ulong base_addr
, u32 phy_addr
)
537 struct eth_device
*dev
;
538 struct dw_eth_dev
*priv
;
540 dev
= (struct eth_device
*) malloc(sizeof(struct eth_device
));
545 * Since the priv structure contains the descriptors which need a strict
546 * buswidth alignment, memalign is used to allocate memory
548 priv
= (struct dw_eth_dev
*) memalign(16, sizeof(struct dw_eth_dev
));
554 memset(dev
, 0, sizeof(struct eth_device
));
555 memset(priv
, 0, sizeof(struct dw_eth_dev
));
557 sprintf(dev
->name
, "mii%d", id
);
558 dev
->iobase
= (int)base_addr
;
561 eth_getenv_enetaddr_by_index("eth", id
, &dev
->enetaddr
[0]);
564 priv
->mac_regs_p
= (struct eth_mac_regs
*)base_addr
;
565 priv
->dma_regs_p
= (struct eth_dma_regs
*)(base_addr
+
567 priv
->address
= phy_addr
;
568 priv
->phy_configured
= 0;
570 if (mac_reset(dev
) < 0)
575 dev
->init
= dw_eth_init
;
576 dev
->send
= dw_eth_send
;
577 dev
->recv
= dw_eth_recv
;
578 dev
->halt
= dw_eth_halt
;
579 dev
->write_hwaddr
= dw_write_hwaddr
;
583 #if defined(CONFIG_MII)
584 miiphy_register(dev
->name
, dw_mii_read
, dw_mii_write
);