2 * Faraday FTGMAC100 Ethernet
4 * (C) Copyright 2009 Faraday Technology
5 * Po-Yu Chuang <ratbert@faraday-tech.com>
7 * (C) Copyright 2010 Andes Technology
8 * Macpaul Lin <macpaul@andestech.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <linux/mii.h>
32 #include "ftgmac100.h"
36 /* RBSR - hw default init value is also 0x640 */
37 #define RBSR_DEFAULT_VALUE 0x640
39 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
40 #define PKTBUFSTX 4 /* must be power of 2 */
42 struct ftgmac100_data
{
43 struct ftgmac100_txdes txdes
[PKTBUFSTX
];
44 struct ftgmac100_rxdes rxdes
[PKTBUFSRX
];
51 * struct mii_bus functions
53 static int ftgmac100_mdiobus_read(struct eth_device
*dev
, int phy_addr
,
56 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
60 phycr
= readl(&ftgmac100
->phycr
);
62 /* preserve MDC cycle threshold */
63 phycr
&= FTGMAC100_PHYCR_MDC_CYCTHR_MASK
;
65 phycr
|= FTGMAC100_PHYCR_PHYAD(phy_addr
)
66 | FTGMAC100_PHYCR_REGAD(regnum
)
67 | FTGMAC100_PHYCR_MIIRD
;
69 writel(phycr
, &ftgmac100
->phycr
);
71 for (i
= 0; i
< 10; i
++) {
72 phycr
= readl(&ftgmac100
->phycr
);
74 if ((phycr
& FTGMAC100_PHYCR_MIIRD
) == 0) {
77 data
= readl(&ftgmac100
->phydata
);
78 return FTGMAC100_PHYDATA_MIIRDATA(data
);
84 debug("mdio read timed out\n");
88 static int ftgmac100_mdiobus_write(struct eth_device
*dev
, int phy_addr
,
89 int regnum
, u16 value
)
91 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
96 phycr
= readl(&ftgmac100
->phycr
);
98 /* preserve MDC cycle threshold */
99 phycr
&= FTGMAC100_PHYCR_MDC_CYCTHR_MASK
;
101 phycr
|= FTGMAC100_PHYCR_PHYAD(phy_addr
)
102 | FTGMAC100_PHYCR_REGAD(regnum
)
103 | FTGMAC100_PHYCR_MIIWR
;
105 data
= FTGMAC100_PHYDATA_MIIWDATA(value
);
107 writel(data
, &ftgmac100
->phydata
);
108 writel(phycr
, &ftgmac100
->phycr
);
110 for (i
= 0; i
< 10; i
++) {
111 phycr
= readl(&ftgmac100
->phycr
);
113 if ((phycr
& FTGMAC100_PHYCR_MIIWR
) == 0) {
114 debug("(phycr & FTGMAC100_PHYCR_MIIWR) == 0: " \
115 "phy_addr: %x\n", phy_addr
);
122 debug("mdio write timed out\n");
126 int ftgmac100_phy_read(struct eth_device
*dev
, int addr
, int reg
, u16
*value
)
128 *value
= ftgmac100_mdiobus_read(dev
, addr
, reg
);
136 int ftgmac100_phy_write(struct eth_device
*dev
, int addr
, int reg
, u16 value
)
138 if (ftgmac100_mdiobus_write(dev
, addr
, reg
, value
) == -1)
144 static int ftgmac100_phy_reset(struct eth_device
*dev
)
146 struct ftgmac100_data
*priv
= dev
->priv
;
150 adv
= ADVERTISE_CSMA
| ADVERTISE_ALL
;
152 ftgmac100_phy_write(dev
, priv
->phy_addr
, MII_ADVERTISE
, adv
);
154 printf("%s: Starting autonegotiation...\n", dev
->name
);
156 ftgmac100_phy_write(dev
, priv
->phy_addr
,
157 MII_BMCR
, (BMCR_ANENABLE
| BMCR_ANRESTART
));
159 for (i
= 0; i
< 100000 / 100; i
++) {
160 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &status
);
162 if (status
& BMSR_ANEGCOMPLETE
)
167 if (status
& BMSR_ANEGCOMPLETE
) {
168 printf("%s: Autonegotiation complete\n", dev
->name
);
170 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
178 static int ftgmac100_phy_init(struct eth_device
*dev
)
180 struct ftgmac100_data
*priv
= dev
->priv
;
183 u16 phy_id
, status
, adv
, lpa
, stat_ge
;
184 int media
, speed
, duplex
;
187 /* Check if the PHY is up to snuff... */
188 for (phy_addr
= 0; phy_addr
< CONFIG_PHY_MAX_ADDR
; phy_addr
++) {
190 ftgmac100_phy_read(dev
, phy_addr
, MII_PHYSID1
, &phy_id
);
193 * When it is unable to found PHY,
194 * the interface usually return 0xffff or 0x0000
196 if (phy_id
!= 0xffff && phy_id
!= 0x0) {
197 printf("%s: found PHY at 0x%02x\n",
198 dev
->name
, phy_addr
);
199 priv
->phy_addr
= phy_addr
;
204 if (phy_id
== 0xffff || phy_id
== 0x0) {
205 printf("%s: no PHY present\n", dev
->name
);
209 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &status
);
211 if (!(status
& BMSR_LSTATUS
)) {
212 /* Try to re-negotiate if we don't have link already. */
213 ftgmac100_phy_reset(dev
);
215 for (i
= 0; i
< 100000 / 100; i
++) {
216 ftgmac100_phy_read(dev
, priv
->phy_addr
,
218 if (status
& BMSR_LSTATUS
)
224 if (!(status
& BMSR_LSTATUS
)) {
225 printf("%s: link down\n", dev
->name
);
229 #ifdef CONFIG_FTGMAC100_EGIGA
230 /* 1000 Base-T Status Register */
231 ftgmac100_phy_read(dev
, priv
->phy_addr
,
232 MII_STAT1000
, &stat_ge
);
234 speed
= (stat_ge
& (LPA_1000FULL
| LPA_1000HALF
)
237 duplex
= ((stat_ge
& LPA_1000FULL
)
240 if (speed
) { /* Speed is 1000 */
241 printf("%s: link up, 1000bps %s-duplex\n",
242 dev
->name
, duplex
? "full" : "half");
247 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_ADVERTISE
, &adv
);
248 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_LPA
, &lpa
);
250 media
= mii_nway_result(lpa
& adv
);
251 speed
= (media
& (ADVERTISE_100FULL
| ADVERTISE_100HALF
) ? 1 : 0);
252 duplex
= (media
& ADVERTISE_FULL
) ? 1 : 0;
254 printf("%s: link up, %sMbps %s-duplex\n",
255 dev
->name
, speed
? "100" : "10", duplex
? "full" : "half");
260 static int ftgmac100_update_link_speed(struct eth_device
*dev
)
262 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
263 struct ftgmac100_data
*priv
= dev
->priv
;
265 unsigned short stat_fe
;
266 unsigned short stat_ge
;
269 #ifdef CONFIG_FTGMAC100_EGIGA
270 /* 1000 Base-T Status Register */
271 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_STAT1000
, &stat_ge
);
274 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &stat_fe
);
276 if (!(stat_fe
& BMSR_LSTATUS
)) /* link status up? */
279 /* read MAC control register and clear related bits */
280 maccr
= readl(&ftgmac100
->maccr
) &
281 ~(FTGMAC100_MACCR_GIGA_MODE
|
282 FTGMAC100_MACCR_FAST_MODE
|
283 FTGMAC100_MACCR_FULLDUP
);
285 #ifdef CONFIG_FTGMAC100_EGIGA
286 if (stat_ge
& LPA_1000FULL
) {
287 /* set gmac for 1000BaseTX and Full Duplex */
288 maccr
|= FTGMAC100_MACCR_GIGA_MODE
| FTGMAC100_MACCR_FULLDUP
;
291 if (stat_ge
& LPA_1000HALF
) {
292 /* set gmac for 1000BaseTX and Half Duplex */
293 maccr
|= FTGMAC100_MACCR_GIGA_MODE
;
297 if (stat_fe
& BMSR_100FULL
) {
298 /* set MII for 100BaseTX and Full Duplex */
299 maccr
|= FTGMAC100_MACCR_FAST_MODE
| FTGMAC100_MACCR_FULLDUP
;
302 if (stat_fe
& BMSR_10FULL
) {
303 /* set MII for 10BaseT and Full Duplex */
304 maccr
|= FTGMAC100_MACCR_FULLDUP
;
307 if (stat_fe
& BMSR_100HALF
) {
308 /* set MII for 100BaseTX and Half Duplex */
309 maccr
|= FTGMAC100_MACCR_FAST_MODE
;
312 if (stat_fe
& BMSR_10HALF
) {
313 /* set MII for 10BaseT and Half Duplex */
314 /* we have already clear these bits, do nothing */
318 /* update MII config into maccr */
319 writel(maccr
, &ftgmac100
->maccr
);
327 static void ftgmac100_reset(struct eth_device
*dev
)
329 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
331 debug("%s()\n", __func__
);
333 writel(FTGMAC100_MACCR_SW_RST
, &ftgmac100
->maccr
);
335 while (readl(&ftgmac100
->maccr
) & FTGMAC100_MACCR_SW_RST
)
342 static void ftgmac100_set_mac(struct eth_device
*dev
,
343 const unsigned char *mac
)
345 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
346 unsigned int maddr
= mac
[0] << 8 | mac
[1];
347 unsigned int laddr
= mac
[2] << 24 | mac
[3] << 16 | mac
[4] << 8 | mac
[5];
349 debug("%s(%x %x)\n", __func__
, maddr
, laddr
);
351 writel(maddr
, &ftgmac100
->mac_madr
);
352 writel(laddr
, &ftgmac100
->mac_ladr
);
355 static void ftgmac100_set_mac_from_env(struct eth_device
*dev
)
357 eth_getenv_enetaddr("ethaddr", dev
->enetaddr
);
359 ftgmac100_set_mac(dev
, dev
->enetaddr
);
363 * disable transmitter, receiver
365 static void ftgmac100_halt(struct eth_device
*dev
)
367 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
369 debug("%s()\n", __func__
);
371 writel(0, &ftgmac100
->maccr
);
374 static int ftgmac100_init(struct eth_device
*dev
, bd_t
*bd
)
376 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
377 struct ftgmac100_data
*priv
= dev
->priv
;
378 struct ftgmac100_txdes
*txdes
= priv
->txdes
;
379 struct ftgmac100_rxdes
*rxdes
= priv
->rxdes
;
383 debug("%s()\n", __func__
);
385 /* set the ethernet address */
386 ftgmac100_set_mac_from_env(dev
);
388 /* disable all interrupts */
389 writel(0, &ftgmac100
->ier
);
391 /* initialize descriptors */
395 txdes
[PKTBUFSTX
- 1].txdes0
= FTGMAC100_TXDES0_EDOTR
;
396 rxdes
[PKTBUFSRX
- 1].rxdes0
= FTGMAC100_RXDES0_EDORR
;
398 for (i
= 0; i
< PKTBUFSTX
; i
++) {
404 for (i
= 0; i
< PKTBUFSRX
; i
++) {
406 rxdes
[i
].rxdes3
= (unsigned int)NetRxPackets
[i
];
407 rxdes
[i
].rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
411 writel((unsigned int)txdes
, &ftgmac100
->txr_badr
);
414 writel((unsigned int)rxdes
, &ftgmac100
->rxr_badr
);
416 /* poll receive descriptor automatically */
417 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100
->aptc
);
419 /* config receive buffer size register */
420 writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE
), &ftgmac100
->rbsr
);
422 /* enable transmitter, receiver */
423 maccr
= FTGMAC100_MACCR_TXMAC_EN
|
424 FTGMAC100_MACCR_RXMAC_EN
|
425 FTGMAC100_MACCR_TXDMA_EN
|
426 FTGMAC100_MACCR_RXDMA_EN
|
427 FTGMAC100_MACCR_CRC_APD
|
428 FTGMAC100_MACCR_FULLDUP
|
429 FTGMAC100_MACCR_RX_RUNT
|
430 FTGMAC100_MACCR_RX_BROADPKT
;
432 writel(maccr
, &ftgmac100
->maccr
);
434 if (!ftgmac100_phy_init(dev
)) {
435 if (!ftgmac100_update_link_speed(dev
))
443 * Get a data block via Ethernet
445 static int ftgmac100_recv(struct eth_device
*dev
)
447 struct ftgmac100_data
*priv
= dev
->priv
;
448 struct ftgmac100_rxdes
*curr_des
;
449 unsigned short rxlen
;
451 curr_des
= &priv
->rxdes
[priv
->rx_index
];
453 if (!(curr_des
->rxdes0
& FTGMAC100_RXDES0_RXPKT_RDY
))
456 if (curr_des
->rxdes0
& (FTGMAC100_RXDES0_RX_ERR
|
457 FTGMAC100_RXDES0_CRC_ERR
|
458 FTGMAC100_RXDES0_FTL
|
459 FTGMAC100_RXDES0_RUNT
|
460 FTGMAC100_RXDES0_RX_ODD_NB
)) {
464 rxlen
= FTGMAC100_RXDES0_VDBC(curr_des
->rxdes0
);
466 debug("%s(): RX buffer %d, %x received\n",
467 __func__
, priv
->rx_index
, rxlen
);
469 /* pass the packet up to the protocol layers. */
470 NetReceive((void *)curr_des
->rxdes3
, rxlen
);
472 /* release buffer to DMA */
473 curr_des
->rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
475 priv
->rx_index
= (priv
->rx_index
+ 1) % PKTBUFSRX
;
481 * Send a data block via Ethernet
483 static int ftgmac100_send(struct eth_device
*dev
, void *packet
, int length
)
485 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
486 struct ftgmac100_data
*priv
= dev
->priv
;
487 struct ftgmac100_txdes
*curr_des
= &priv
->txdes
[priv
->tx_index
];
490 if (curr_des
->txdes0
& FTGMAC100_TXDES0_TXDMA_OWN
) {
491 debug("%s(): no TX descriptor available\n", __func__
);
495 debug("%s(%x, %x)\n", __func__
, (int)packet
, length
);
497 length
= (length
< ETH_ZLEN
) ? ETH_ZLEN
: length
;
499 /* initiate a transmit sequence */
500 curr_des
->txdes3
= (unsigned int)packet
; /* TXBUF_BADR */
502 /* only one descriptor on TXBUF */
503 curr_des
->txdes0
&= FTGMAC100_TXDES0_EDOTR
;
504 curr_des
->txdes0
|= FTGMAC100_TXDES0_FTS
|
505 FTGMAC100_TXDES0_LTS
|
506 FTGMAC100_TXDES0_TXBUF_SIZE(length
) |
507 FTGMAC100_TXDES0_TXDMA_OWN
;
510 writel(1, &ftgmac100
->txpd
);
512 /* wait for transfer to succeed */
513 start
= get_timer(0);
514 while (curr_des
->txdes0
& FTGMAC100_TXDES0_TXDMA_OWN
) {
515 if (get_timer(0) >= 5) {
516 debug("%s(): timed out\n", __func__
);
521 debug("%s(): packet sent\n", __func__
);
523 priv
->tx_index
= (priv
->tx_index
+ 1) % PKTBUFSTX
;
528 int ftgmac100_initialize(bd_t
*bd
)
530 struct eth_device
*dev
;
531 struct ftgmac100_data
*priv
;
533 dev
= malloc(sizeof *dev
);
535 printf("%s(): failed to allocate dev\n", __func__
);
539 /* Transmit and receive descriptors should align to 16 bytes */
540 priv
= memalign(16, sizeof(struct ftgmac100_data
));
542 printf("%s(): failed to allocate priv\n", __func__
);
546 memset(dev
, 0, sizeof(*dev
));
547 memset(priv
, 0, sizeof(*priv
));
549 sprintf(dev
->name
, "FTGMAC100");
550 dev
->iobase
= CONFIG_FTGMAC100_BASE
;
551 dev
->init
= ftgmac100_init
;
552 dev
->halt
= ftgmac100_halt
;
553 dev
->send
= ftgmac100_send
;
554 dev
->recv
= ftgmac100_recv
;
559 ftgmac100_reset(dev
);