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 void tx_descs_init(struct eth_device
*dev
)
37 struct dw_eth_dev
*priv
= dev
->priv
;
38 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
39 struct dmamacdescr
*desc_table_p
= &priv
->tx_mac_descrtable
[0];
40 char *txbuffs
= &priv
->txbuffs
[0];
41 struct dmamacdescr
*desc_p
;
44 for (idx
= 0; idx
< CONFIG_TX_DESCR_NUM
; idx
++) {
45 desc_p
= &desc_table_p
[idx
];
46 desc_p
->dmamac_addr
= &txbuffs
[idx
* CONFIG_ETH_BUFSIZE
];
47 desc_p
->dmamac_next
= &desc_table_p
[idx
+ 1];
49 #if defined(CONFIG_DW_ALTDESCRIPTOR)
50 desc_p
->txrx_status
&= ~(DESC_TXSTS_TXINT
| DESC_TXSTS_TXLAST
|
51 DESC_TXSTS_TXFIRST
| DESC_TXSTS_TXCRCDIS
| \
52 DESC_TXSTS_TXCHECKINSCTRL
| \
53 DESC_TXSTS_TXRINGEND
| DESC_TXSTS_TXPADDIS
);
55 desc_p
->txrx_status
|= DESC_TXSTS_TXCHAIN
;
56 desc_p
->dmamac_cntl
= 0;
57 desc_p
->txrx_status
&= ~(DESC_TXSTS_MSK
| DESC_TXSTS_OWNBYDMA
);
59 desc_p
->dmamac_cntl
= DESC_TXCTRL_TXCHAIN
;
60 desc_p
->txrx_status
= 0;
64 /* Correcting the last pointer of the chain */
65 desc_p
->dmamac_next
= &desc_table_p
[0];
67 writel((ulong
)&desc_table_p
[0], &dma_p
->txdesclistaddr
);
70 static void rx_descs_init(struct eth_device
*dev
)
72 struct dw_eth_dev
*priv
= dev
->priv
;
73 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
74 struct dmamacdescr
*desc_table_p
= &priv
->rx_mac_descrtable
[0];
75 char *rxbuffs
= &priv
->rxbuffs
[0];
76 struct dmamacdescr
*desc_p
;
79 for (idx
= 0; idx
< CONFIG_RX_DESCR_NUM
; idx
++) {
80 desc_p
= &desc_table_p
[idx
];
81 desc_p
->dmamac_addr
= &rxbuffs
[idx
* CONFIG_ETH_BUFSIZE
];
82 desc_p
->dmamac_next
= &desc_table_p
[idx
+ 1];
85 (MAC_MAX_FRAME_SZ
& DESC_RXCTRL_SIZE1MASK
) | \
88 desc_p
->txrx_status
= DESC_RXSTS_OWNBYDMA
;
91 /* Correcting the last pointer of the chain */
92 desc_p
->dmamac_next
= &desc_table_p
[0];
94 writel((ulong
)&desc_table_p
[0], &dma_p
->rxdesclistaddr
);
97 static void descs_init(struct eth_device
*dev
)
103 static int mac_reset(struct eth_device
*dev
)
105 struct dw_eth_dev
*priv
= dev
->priv
;
106 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
107 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
109 int timeout
= CONFIG_MACRESET_TIMEOUT
;
111 writel(DMAMAC_SRST
, &dma_p
->busmode
);
112 writel(MII_PORTSELECT
, &mac_p
->conf
);
115 if (!(readl(&dma_p
->busmode
) & DMAMAC_SRST
))
123 static int dw_write_hwaddr(struct eth_device
*dev
)
125 struct dw_eth_dev
*priv
= dev
->priv
;
126 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
127 u32 macid_lo
, macid_hi
;
128 u8
*mac_id
= &dev
->enetaddr
[0];
130 macid_lo
= mac_id
[0] + (mac_id
[1] << 8) + \
131 (mac_id
[2] << 16) + (mac_id
[3] << 24);
132 macid_hi
= mac_id
[4] + (mac_id
[5] << 8);
134 writel(macid_hi
, &mac_p
->macaddr0hi
);
135 writel(macid_lo
, &mac_p
->macaddr0lo
);
140 static int dw_eth_init(struct eth_device
*dev
, bd_t
*bis
)
142 struct dw_eth_dev
*priv
= dev
->priv
;
143 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
144 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
147 /* Reset ethernet hardware */
148 if (mac_reset(dev
) < 0)
151 writel(FIXEDBURST
| PRIORXTX_41
| BURST_16
,
154 writel(FLUSHTXFIFO
| readl(&dma_p
->opmode
), &dma_p
->opmode
);
155 writel(STOREFORWARD
| TXSECONDFRAME
, &dma_p
->opmode
);
157 conf
= FRAMEBURSTENABLE
| DISABLERXOWN
;
159 if (priv
->speed
!= SPEED_1000M
)
160 conf
|= MII_PORTSELECT
;
162 if (priv
->duplex
== FULL_DUPLEX
)
163 conf
|= FULLDPLXMODE
;
165 writel(conf
, &mac_p
->conf
);
170 * Start/Enable xfer at dma as well as mac level
172 writel(readl(&dma_p
->opmode
) | RXSTART
, &dma_p
->opmode
);
173 writel(readl(&dma_p
->opmode
) | TXSTART
, &dma_p
->opmode
);
175 writel(readl(&mac_p
->conf
) | RXENABLE
, &mac_p
->conf
);
176 writel(readl(&mac_p
->conf
) | TXENABLE
, &mac_p
->conf
);
181 static int dw_eth_send(struct eth_device
*dev
, volatile void *packet
,
184 struct dw_eth_dev
*priv
= dev
->priv
;
185 struct eth_dma_regs
*dma_p
= priv
->dma_regs_p
;
186 u32 desc_num
= priv
->tx_currdescnum
;
187 struct dmamacdescr
*desc_p
= &priv
->tx_mac_descrtable
[desc_num
];
189 /* Check if the descriptor is owned by CPU */
190 if (desc_p
->txrx_status
& DESC_TXSTS_OWNBYDMA
) {
191 printf("CPU not owner of tx frame\n");
195 memcpy((void *)desc_p
->dmamac_addr
, (void *)packet
, length
);
197 #if defined(CONFIG_DW_ALTDESCRIPTOR)
198 desc_p
->txrx_status
|= DESC_TXSTS_TXFIRST
| DESC_TXSTS_TXLAST
;
199 desc_p
->dmamac_cntl
|= (length
<< DESC_TXCTRL_SIZE1SHFT
) & \
200 DESC_TXCTRL_SIZE1MASK
;
202 desc_p
->txrx_status
&= ~(DESC_TXSTS_MSK
);
203 desc_p
->txrx_status
|= DESC_TXSTS_OWNBYDMA
;
205 desc_p
->dmamac_cntl
|= ((length
<< DESC_TXCTRL_SIZE1SHFT
) & \
206 DESC_TXCTRL_SIZE1MASK
) | DESC_TXCTRL_TXLAST
| \
209 desc_p
->txrx_status
= DESC_TXSTS_OWNBYDMA
;
212 /* Test the wrap-around condition. */
213 if (++desc_num
>= CONFIG_TX_DESCR_NUM
)
216 priv
->tx_currdescnum
= desc_num
;
218 /* Start the transmission */
219 writel(POLL_DATA
, &dma_p
->txpolldemand
);
224 static int dw_eth_recv(struct eth_device
*dev
)
226 struct dw_eth_dev
*priv
= dev
->priv
;
227 u32 desc_num
= priv
->rx_currdescnum
;
228 struct dmamacdescr
*desc_p
= &priv
->rx_mac_descrtable
[desc_num
];
230 u32 status
= desc_p
->txrx_status
;
233 /* Check if the owner is the CPU */
234 if (!(status
& DESC_RXSTS_OWNBYDMA
)) {
236 length
= (status
& DESC_RXSTS_FRMLENMSK
) >> \
237 DESC_RXSTS_FRMLENSHFT
;
239 NetReceive(desc_p
->dmamac_addr
, length
);
242 * Make the current descriptor valid again and go to
245 desc_p
->txrx_status
|= DESC_RXSTS_OWNBYDMA
;
247 /* Test the wrap-around condition. */
248 if (++desc_num
>= CONFIG_RX_DESCR_NUM
)
252 priv
->rx_currdescnum
= desc_num
;
257 static void dw_eth_halt(struct eth_device
*dev
)
259 struct dw_eth_dev
*priv
= dev
->priv
;
262 priv
->tx_currdescnum
= priv
->rx_currdescnum
= 0;
265 static int eth_mdio_read(struct eth_device
*dev
, u8 addr
, u8 reg
, u16
*val
)
267 struct dw_eth_dev
*priv
= dev
->priv
;
268 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
270 int timeout
= CONFIG_MDIO_TIMEOUT
;
272 miiaddr
= ((addr
<< MIIADDRSHIFT
) & MII_ADDRMSK
) | \
273 ((reg
<< MIIREGSHIFT
) & MII_REGMSK
);
275 writel(miiaddr
| MII_CLKRANGE_150_250M
| MII_BUSY
, &mac_p
->miiaddr
);
278 if (!(readl(&mac_p
->miiaddr
) & MII_BUSY
)) {
279 *val
= readl(&mac_p
->miidata
);
288 static int eth_mdio_write(struct eth_device
*dev
, u8 addr
, u8 reg
, u16 val
)
290 struct dw_eth_dev
*priv
= dev
->priv
;
291 struct eth_mac_regs
*mac_p
= priv
->mac_regs_p
;
293 int ret
= -1, timeout
= CONFIG_MDIO_TIMEOUT
;
296 writel(val
, &mac_p
->miidata
);
297 miiaddr
= ((addr
<< MIIADDRSHIFT
) & MII_ADDRMSK
) | \
298 ((reg
<< MIIREGSHIFT
) & MII_REGMSK
) | MII_WRITE
;
300 writel(miiaddr
| MII_CLKRANGE_150_250M
| MII_BUSY
, &mac_p
->miiaddr
);
303 if (!(readl(&mac_p
->miiaddr
) & MII_BUSY
))
308 /* Needed as a fix for ST-Phy */
309 eth_mdio_read(dev
, addr
, reg
, &value
);
314 #if defined(CONFIG_DW_SEARCH_PHY)
315 static int find_phy(struct eth_device
*dev
)
321 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
322 oldctrl
= ctrl
& BMCR_ANENABLE
;
324 ctrl
^= BMCR_ANENABLE
;
325 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, ctrl
);
326 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
327 ctrl
&= BMCR_ANENABLE
;
329 if (ctrl
== oldctrl
) {
332 ctrl
^= BMCR_ANENABLE
;
333 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, ctrl
);
337 } while (phy_addr
< 32);
343 static int dw_reset_phy(struct eth_device
*dev
)
345 struct dw_eth_dev
*priv
= dev
->priv
;
347 int timeout
= CONFIG_PHYRESET_TIMEOUT
;
348 u32 phy_addr
= priv
->address
;
350 eth_mdio_write(dev
, phy_addr
, MII_BMCR
, BMCR_RESET
);
352 eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
);
353 if (!(ctrl
& BMCR_RESET
))
361 #ifdef CONFIG_PHY_RESET_DELAY
362 udelay(CONFIG_PHY_RESET_DELAY
);
367 static int configure_phy(struct eth_device
*dev
)
369 struct dw_eth_dev
*priv
= dev
->priv
;
372 #if defined(CONFIG_DW_AUTONEG)
380 #if defined(CONFIG_DW_SEARCH_PHY)
381 phy_addr
= find_phy(dev
);
383 priv
->address
= phy_addr
;
387 phy_addr
= priv
->address
;
389 if (dw_reset_phy(dev
) < 0)
392 #if defined(CONFIG_DW_AUTONEG)
393 bmcr
= BMCR_ANENABLE
| BMCR_ANRESTART
| BMCR_SPEED100
| \
394 BMCR_FULLDPLX
| BMCR_SPEED1000
;
396 bmcr
= BMCR_SPEED100
| BMCR_FULLDPLX
;
398 #if defined(CONFIG_DW_SPEED10M)
399 bmcr
&= ~BMCR_SPEED100
;
401 #if defined(CONFIG_DW_DUPLEXHALF)
402 bmcr
&= ~BMCR_FULLDPLX
;
405 if (eth_mdio_write(dev
, phy_addr
, MII_BMCR
, bmcr
) < 0)
408 /* Read the phy status register and populate priv structure */
409 #if defined(CONFIG_DW_AUTONEG)
410 timeout
= CONFIG_AUTONEG_TIMEOUT
;
412 eth_mdio_read(dev
, phy_addr
, MII_BMSR
, &bmsr
);
413 if (bmsr
& BMSR_ANEGCOMPLETE
)
418 eth_mdio_read(dev
, phy_addr
, MII_LPA
, &anlpar
);
419 eth_mdio_read(dev
, phy_addr
, MII_STAT1000
, &btsr
);
421 if (btsr
& (PHY_1000BTSR_1000FD
| PHY_1000BTSR_1000HD
)) {
422 priv
->speed
= SPEED_1000M
;
423 if (btsr
& PHY_1000BTSR_1000FD
)
424 priv
->duplex
= FULL_DUPLEX
;
426 priv
->duplex
= HALF_DUPLEX
;
428 if (anlpar
& LPA_100
)
429 priv
->speed
= SPEED_100M
;
431 priv
->speed
= SPEED_10M
;
433 if (anlpar
& (LPA_10FULL
| LPA_100FULL
))
434 priv
->duplex
= FULL_DUPLEX
;
436 priv
->duplex
= HALF_DUPLEX
;
439 if (eth_mdio_read(dev
, phy_addr
, MII_BMCR
, &ctrl
) < 0)
442 if (ctrl
& BMCR_FULLDPLX
)
443 priv
->duplex
= FULL_DUPLEX
;
445 priv
->duplex
= HALF_DUPLEX
;
447 if (ctrl
& BMCR_SPEED1000
)
448 priv
->speed
= SPEED_1000M
;
449 else if (ctrl
& BMCR_SPEED100
)
450 priv
->speed
= SPEED_100M
;
452 priv
->speed
= SPEED_10M
;
457 #if defined(CONFIG_MII)
458 static int dw_mii_read(const char *devname
, u8 addr
, u8 reg
, u16
*val
)
460 struct eth_device
*dev
;
462 dev
= eth_get_dev_by_name(devname
);
464 eth_mdio_read(dev
, addr
, reg
, val
);
469 static int dw_mii_write(const char *devname
, u8 addr
, u8 reg
, u16 val
)
471 struct eth_device
*dev
;
473 dev
= eth_get_dev_by_name(devname
);
475 eth_mdio_write(dev
, addr
, reg
, val
);
481 int designware_initialize(u32 id
, ulong base_addr
, u32 phy_addr
)
483 struct eth_device
*dev
;
484 struct dw_eth_dev
*priv
;
486 dev
= (struct eth_device
*) malloc(sizeof(struct eth_device
));
491 * Since the priv structure contains the descriptors which need a strict
492 * buswidth alignment, memalign is used to allocate memory
494 priv
= (struct dw_eth_dev
*) memalign(16, sizeof(struct dw_eth_dev
));
500 memset(dev
, 0, sizeof(struct eth_device
));
501 memset(priv
, 0, sizeof(struct dw_eth_dev
));
503 sprintf(dev
->name
, "mii%d", id
);
504 dev
->iobase
= (int)base_addr
;
507 eth_getenv_enetaddr_by_index("eth", id
, &dev
->enetaddr
[0]);
510 priv
->mac_regs_p
= (struct eth_mac_regs
*)base_addr
;
511 priv
->dma_regs_p
= (struct eth_dma_regs
*)(base_addr
+
513 priv
->address
= phy_addr
;
515 if (mac_reset(dev
) < 0)
518 if (configure_phy(dev
) < 0) {
519 printf("Phy could not be configured\n");
523 dev
->init
= dw_eth_init
;
524 dev
->send
= dw_eth_send
;
525 dev
->recv
= dw_eth_recv
;
526 dev
->halt
= dw_eth_halt
;
527 dev
->write_hwaddr
= dw_write_hwaddr
;
531 #if defined(CONFIG_MII)
532 miiphy_register(dev
->name
, dw_mii_read
, dw_mii_write
);