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/compiler.h>
32 #include <linux/err.h>
34 #include "designware.h"
36 static int configure_phy(struct eth_device
*dev
);
38 static void tx_descs_init(struct eth_device
*dev
)
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
;
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];
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
);
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
);
62 desc_p
->dmamac_cntl
= DESC_TXCTRL_TXCHAIN
;
63 desc_p
->txrx_status
= 0;
67 /* Correcting the last pointer of the chain */
68 desc_p
->dmamac_next
= &desc_table_p
[0];
70 writel((ulong
)&desc_table_p
[0], &dma_p
->txdesclistaddr
);
73 static void rx_descs_init(struct eth_device
*dev
)
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
;
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];
88 (MAC_MAX_FRAME_SZ
& DESC_RXCTRL_SIZE1MASK
) | \
91 desc_p
->txrx_status
= DESC_RXSTS_OWNBYDMA
;
94 /* Correcting the last pointer of the chain */
95 desc_p
->dmamac_next
= &desc_table_p
[0];
97 writel((ulong
)&desc_table_p
[0], &dma_p
->rxdesclistaddr
);
100 static void descs_init(struct eth_device
*dev
)
106 static int mac_reset(struct eth_device
*dev
)
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
;
113 int timeout
= CONFIG_MACRESET_TIMEOUT
;
115 writel(DMAMAC_SRST
, &dma_p
->busmode
);
116 writel(MII_PORTSELECT
, &mac_p
->conf
);
118 start
= get_timer(0);
119 while (get_timer(start
) < timeout
) {
120 if (!(readl(&dma_p
->busmode
) & DMAMAC_SRST
))
123 /* Try again after 10usec */
130 static int dw_write_hwaddr(struct eth_device
*dev
)
132 struct dw_eth_dev
*priv
= dev
->priv
;
133 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
134 u32 macid_lo
, macid_hi
;
135 u8
*mac_id
= &dev
->enetaddr
[0];
137 macid_lo
= mac_id
[0] + (mac_id
[1] << 8) + \
138 (mac_id
[2] << 16) + (mac_id
[3] << 24);
139 macid_hi
= mac_id
[4] + (mac_id
[5] << 8);
141 writel(macid_hi
, &mac_p
->macaddr0hi
);
142 writel(macid_lo
, &mac_p
->macaddr0lo
);
147 static int dw_eth_init(struct eth_device
*dev
, bd_t
*bis
)
149 struct dw_eth_dev
*priv
= dev
->priv
;
150 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
151 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
154 if (priv
->phy_configured
!= 1)
157 /* Print link status only once */
158 if (!priv
->link_printed
) {
159 printf("ENET Speed is %d Mbps - %s duplex connection\n",
160 priv
->speed
, (priv
->duplex
== HALF
) ? "HALF" : "FULL");
161 priv
->link_printed
= 1;
164 /* Reset ethernet hardware */
165 if (mac_reset(dev
) < 0)
168 /* Resore the HW MAC address as it has been lost during MAC reset */
169 dw_write_hwaddr(dev
);
171 writel(FIXEDBURST
| PRIORXTX_41
| BURST_16
,
174 writel(readl(&dma_p
->opmode
) | FLUSHTXFIFO
| STOREFORWARD
|
175 TXSECONDFRAME
, &dma_p
->opmode
);
177 conf
= FRAMEBURSTENABLE
| DISABLERXOWN
;
179 if (priv
->speed
!= 1000)
180 conf
|= MII_PORTSELECT
;
182 if ((priv
->interface
!= PHY_INTERFACE_MODE_MII
) &&
183 (priv
->interface
!= PHY_INTERFACE_MODE_GMII
)) {
185 if (priv
->speed
== 100)
189 if (priv
->duplex
== FULL
)
190 conf
|= FULLDPLXMODE
;
192 writel(conf
, &mac_p
->conf
);
197 * Start/Enable xfer at dma as well as mac level
199 writel(readl(&dma_p
->opmode
) | RXSTART
, &dma_p
->opmode
);
200 writel(readl(&dma_p
->opmode
) | TXSTART
, &dma_p
->opmode
);
202 writel(readl(&mac_p
->conf
) | RXENABLE
| TXENABLE
, &mac_p
->conf
);
207 static int dw_eth_send(struct eth_device
*dev
, void *packet
, int length
)
209 struct dw_eth_dev
*priv
= dev
->priv
;
210 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
211 u32 desc_num
= priv
->tx_currdescnum
;
212 struct dmamacdescr
*desc_p
= &priv
->tx_mac_descrtable
[desc_num
];
214 /* Check if the descriptor is owned by CPU */
215 if (desc_p
->txrx_status
& DESC_TXSTS_OWNBYDMA
) {
216 printf("CPU not owner of tx frame\n");
220 memcpy((void *)desc_p
->dmamac_addr
, packet
, length
);
222 #if defined(CONFIG_DW_ALTDESCRIPTOR)
223 desc_p
->txrx_status
|= DESC_TXSTS_TXFIRST
| DESC_TXSTS_TXLAST
;
224 desc_p
->dmamac_cntl
|= (length
<< DESC_TXCTRL_SIZE1SHFT
) & \
225 DESC_TXCTRL_SIZE1MASK
;
227 desc_p
->txrx_status
&= ~(DESC_TXSTS_MSK
);
228 desc_p
->txrx_status
|= DESC_TXSTS_OWNBYDMA
;
230 desc_p
->dmamac_cntl
|= ((length
<< DESC_TXCTRL_SIZE1SHFT
) & \
231 DESC_TXCTRL_SIZE1MASK
) | DESC_TXCTRL_TXLAST
| \
234 desc_p
->txrx_status
= DESC_TXSTS_OWNBYDMA
;
237 /* Test the wrap-around condition. */
238 if (++desc_num
>= CONFIG_TX_DESCR_NUM
)
241 priv
->tx_currdescnum
= desc_num
;
243 /* Start the transmission */
244 writel(POLL_DATA
, &dma_p
->txpolldemand
);
249 static int dw_eth_recv(struct eth_device
*dev
)
251 struct dw_eth_dev
*priv
= dev
->priv
;
252 u32 desc_num
= priv
->rx_currdescnum
;
253 struct dmamacdescr
*desc_p
= &priv
->rx_mac_descrtable
[desc_num
];
255 u32 status
= desc_p
->txrx_status
;
258 /* Check if the owner is the CPU */
259 if (!(status
& DESC_RXSTS_OWNBYDMA
)) {
261 length
= (status
& DESC_RXSTS_FRMLENMSK
) >> \
262 DESC_RXSTS_FRMLENSHFT
;
264 NetReceive(desc_p
->dmamac_addr
, length
);
267 * Make the current descriptor valid again and go to
270 desc_p
->txrx_status
|= DESC_RXSTS_OWNBYDMA
;
272 /* Test the wrap-around condition. */
273 if (++desc_num
>= CONFIG_RX_DESCR_NUM
)
277 priv
->rx_currdescnum
= desc_num
;
282 static void dw_eth_halt(struct eth_device
*dev
)
284 struct dw_eth_dev
*priv
= dev
->priv
;
287 priv
->tx_currdescnum
= priv
->rx_currdescnum
= 0;
290 static int eth_mdio_read(struct eth_device
*dev
, u8 addr
, u8 reg
, u16
*val
)
292 struct dw_eth_dev
*priv
= dev
->priv
;
293 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
296 int timeout
= CONFIG_MDIO_TIMEOUT
;
298 miiaddr
= ((addr
<< MIIADDRSHIFT
) & MII_ADDRMSK
) | \
299 ((reg
<< MIIREGSHIFT
) & MII_REGMSK
);
301 writel(miiaddr
| MII_CLKRANGE_150_250M
| MII_BUSY
, &mac_p
->miiaddr
);
303 start
= get_timer(0);
304 while (get_timer(start
) < timeout
) {
305 if (!(readl(&mac_p
->miiaddr
) & MII_BUSY
)) {
306 *val
= readl(&mac_p
->miidata
);
310 /* Try again after 10usec */
317 static int eth_mdio_write(struct eth_device
*dev
, u8 addr
, u8 reg
, u16 val
)
319 struct dw_eth_dev
*priv
= dev
->priv
;
320 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
323 int ret
= -1, timeout
= CONFIG_MDIO_TIMEOUT
;
326 writel(val
, &mac_p
->miidata
);
327 miiaddr
= ((addr
<< MIIADDRSHIFT
) & MII_ADDRMSK
) | \
328 ((reg
<< MIIREGSHIFT
) & MII_REGMSK
) | MII_WRITE
;
330 writel(miiaddr
| MII_CLKRANGE_150_250M
| MII_BUSY
, &mac_p
->miiaddr
);
332 start
= get_timer(0);
333 while (get_timer(start
) < timeout
) {
334 if (!(readl(&mac_p
->miiaddr
) & MII_BUSY
)) {
339 /* Try again after 10usec */
343 /* Needed as a fix for ST-Phy */
344 eth_mdio_read(dev
, addr
, reg
, &value
);
349 #if defined(CONFIG_DW_SEARCH_PHY)
350 static int find_phy(struct eth_device
*dev
)
356 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
357 oldctrl
= ctrl
& BMCR_ANENABLE
;
359 ctrl
^= BMCR_ANENABLE
;
360 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, ctrl
);
361 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
362 ctrl
&= BMCR_ANENABLE
;
364 if (ctrl
== oldctrl
) {
367 ctrl
^= BMCR_ANENABLE
;
368 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, ctrl
);
372 } while (phy_addr
< 32);
378 static int dw_reset_phy(struct eth_device
*dev
)
380 struct dw_eth_dev
*priv
= dev
->priv
;
383 int timeout
= CONFIG_PHYRESET_TIMEOUT
;
384 u32 phy_addr
= priv
->address
;
386 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, BMCR_RESET
);
388 start
= get_timer(0);
389 while (get_timer(start
) < timeout
) {
390 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
391 if (!(ctrl
& BMCR_RESET
))
394 /* Try again after 10usec */
398 if (get_timer(start
) >= CONFIG_PHYRESET_TIMEOUT
)
401 #ifdef CONFIG_PHY_RESET_DELAY
402 udelay(CONFIG_PHY_RESET_DELAY
);
408 * Add weak default function for board specific PHY configuration
410 int __weak
designware_board_phy_init(struct eth_device
*dev
, int phy_addr
,
411 int (*mii_write
)(struct eth_device
*, u8
, u8
, u16
),
412 int dw_reset_phy(struct eth_device
*))
417 static int configure_phy(struct eth_device
*dev
)
419 struct dw_eth_dev
*priv
= dev
->priv
;
422 #if defined(CONFIG_DW_AUTONEG)
428 #if defined(CONFIG_DW_SEARCH_PHY)
429 phy_addr
= find_phy(dev
);
431 priv
->address
= phy_addr
;
435 phy_addr
= priv
->address
;
439 * Some boards need board specific PHY initialization. This is
440 * after the main driver init code but before the auto negotiation
443 if (designware_board_phy_init(dev
, phy_addr
,
444 eth_mdio_write
, dw_reset_phy
) < 0)
447 if (dw_reset_phy(dev
) < 0)
450 #if defined(CONFIG_DW_AUTONEG)
451 /* Set Auto-Neg Advertisement capabilities to 10/100 half/full */
452 eth_mdio_write(dev
, phy_addr
, MII_ADVERTISE
, 0x1E1);
454 bmcr
= BMCR_ANENABLE
| BMCR_ANRESTART
;
456 bmcr
= BMCR_SPEED100
| BMCR_FULLDPLX
;
458 #if defined(CONFIG_DW_SPEED10M)
459 bmcr
&= ~BMCR_SPEED100
;
461 #if defined(CONFIG_DW_DUPLEXHALF)
462 bmcr
&= ~BMCR_FULLDPLX
;
465 if (eth_mdio_write(dev
, phy_addr
, MII_BMCR
, bmcr
) < 0)
468 /* Read the phy status register and populate priv structure */
469 #if defined(CONFIG_DW_AUTONEG)
470 timeout
= CONFIG_AUTONEG_TIMEOUT
;
471 start
= get_timer(0);
472 puts("Waiting for PHY auto negotiation to complete");
473 while (get_timer(start
) < timeout
) {
474 eth_mdio_read(dev
, phy_addr
, MII_BMSR
, &bmsr
);
475 if (bmsr
& BMSR_ANEGCOMPLETE
) {
476 priv
->phy_configured
= 1;
480 /* Print dot all 1s to show progress */
481 if ((get_timer(start
) % 1000) == 0)
484 /* Try again after 1msec */
488 if (!(bmsr
& BMSR_ANEGCOMPLETE
))
493 priv
->phy_configured
= 1;
496 priv
->speed
= miiphy_speed(dev
->name
, phy_addr
);
497 priv
->duplex
= miiphy_duplex(dev
->name
, phy_addr
);
502 #if defined(CONFIG_MII)
503 static int dw_mii_read(const char *devname
, u8 addr
, u8 reg
, u16
*val
)
505 struct eth_device
*dev
;
507 dev
= eth_get_dev_by_name(devname
);
509 eth_mdio_read(dev
, addr
, reg
, val
);
514 static int dw_mii_write(const char *devname
, u8 addr
, u8 reg
, u16 val
)
516 struct eth_device
*dev
;
518 dev
= eth_get_dev_by_name(devname
);
520 eth_mdio_write(dev
, addr
, reg
, val
);
526 int designware_initialize(u32 id
, ulong base_addr
, u32 phy_addr
, u32 interface
)
528 struct eth_device
*dev
;
529 struct dw_eth_dev
*priv
;
531 dev
= (struct eth_device
*) malloc(sizeof(struct eth_device
));
536 * Since the priv structure contains the descriptors which need a strict
537 * buswidth alignment, memalign is used to allocate memory
539 priv
= (struct dw_eth_dev
*) memalign(16, sizeof(struct dw_eth_dev
));
545 memset(dev
, 0, sizeof(struct eth_device
));
546 memset(priv
, 0, sizeof(struct dw_eth_dev
));
548 sprintf(dev
->name
, "mii%d", id
);
549 dev
->iobase
= (int)base_addr
;
552 eth_getenv_enetaddr_by_index("eth", id
, &dev
->enetaddr
[0]);
555 priv
->mac_regs_p
= (struct eth_mac_regs
*)base_addr
;
556 priv
->dma_regs_p
= (struct eth_dma_regs
*)(base_addr
+
558 priv
->address
= phy_addr
;
559 priv
->phy_configured
= 0;
560 priv
->interface
= interface
;
562 dev
->init
= dw_eth_init
;
563 dev
->send
= dw_eth_send
;
564 dev
->recv
= dw_eth_recv
;
565 dev
->halt
= dw_eth_halt
;
566 dev
->write_hwaddr
= dw_write_hwaddr
;
570 #if defined(CONFIG_MII)
571 miiphy_register(dev
->name
, dw_mii_read
, dw_mii_write
);