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 <asm/dma-mapping.h>
31 #include <linux/mii.h>
33 #include "ftgmac100.h"
36 #define CFG_XBUF_SIZE 1536
38 /* RBSR - hw default init value is also 0x640 */
39 #define RBSR_DEFAULT_VALUE 0x640
41 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
42 #define PKTBUFSTX 4 /* must be power of 2 */
44 struct ftgmac100_data
{
46 struct ftgmac100_txdes
*txdes
;
48 struct ftgmac100_rxdes
*rxdes
;
55 * struct mii_bus functions
57 static int ftgmac100_mdiobus_read(struct eth_device
*dev
, int phy_addr
,
60 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
64 phycr
= readl(&ftgmac100
->phycr
);
66 /* preserve MDC cycle threshold */
67 phycr
&= FTGMAC100_PHYCR_MDC_CYCTHR_MASK
;
69 phycr
|= FTGMAC100_PHYCR_PHYAD(phy_addr
)
70 | FTGMAC100_PHYCR_REGAD(regnum
)
71 | FTGMAC100_PHYCR_MIIRD
;
73 writel(phycr
, &ftgmac100
->phycr
);
75 for (i
= 0; i
< 10; i
++) {
76 phycr
= readl(&ftgmac100
->phycr
);
78 if ((phycr
& FTGMAC100_PHYCR_MIIRD
) == 0) {
81 data
= readl(&ftgmac100
->phydata
);
82 return FTGMAC100_PHYDATA_MIIRDATA(data
);
88 debug("mdio read timed out\n");
92 static int ftgmac100_mdiobus_write(struct eth_device
*dev
, int phy_addr
,
93 int regnum
, u16 value
)
95 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
100 phycr
= readl(&ftgmac100
->phycr
);
102 /* preserve MDC cycle threshold */
103 phycr
&= FTGMAC100_PHYCR_MDC_CYCTHR_MASK
;
105 phycr
|= FTGMAC100_PHYCR_PHYAD(phy_addr
)
106 | FTGMAC100_PHYCR_REGAD(regnum
)
107 | FTGMAC100_PHYCR_MIIWR
;
109 data
= FTGMAC100_PHYDATA_MIIWDATA(value
);
111 writel(data
, &ftgmac100
->phydata
);
112 writel(phycr
, &ftgmac100
->phycr
);
114 for (i
= 0; i
< 10; i
++) {
115 phycr
= readl(&ftgmac100
->phycr
);
117 if ((phycr
& FTGMAC100_PHYCR_MIIWR
) == 0) {
118 debug("(phycr & FTGMAC100_PHYCR_MIIWR) == 0: " \
119 "phy_addr: %x\n", phy_addr
);
126 debug("mdio write timed out\n");
130 int ftgmac100_phy_read(struct eth_device
*dev
, int addr
, int reg
, u16
*value
)
132 *value
= ftgmac100_mdiobus_read(dev
, addr
, reg
);
140 int ftgmac100_phy_write(struct eth_device
*dev
, int addr
, int reg
, u16 value
)
142 if (ftgmac100_mdiobus_write(dev
, addr
, reg
, value
) == -1)
148 static int ftgmac100_phy_reset(struct eth_device
*dev
)
150 struct ftgmac100_data
*priv
= dev
->priv
;
154 adv
= ADVERTISE_CSMA
| ADVERTISE_ALL
;
156 ftgmac100_phy_write(dev
, priv
->phy_addr
, MII_ADVERTISE
, adv
);
158 printf("%s: Starting autonegotiation...\n", dev
->name
);
160 ftgmac100_phy_write(dev
, priv
->phy_addr
,
161 MII_BMCR
, (BMCR_ANENABLE
| BMCR_ANRESTART
));
163 for (i
= 0; i
< 100000 / 100; i
++) {
164 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &status
);
166 if (status
& BMSR_ANEGCOMPLETE
)
171 if (status
& BMSR_ANEGCOMPLETE
) {
172 printf("%s: Autonegotiation complete\n", dev
->name
);
174 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
182 static int ftgmac100_phy_init(struct eth_device
*dev
)
184 struct ftgmac100_data
*priv
= dev
->priv
;
187 u16 phy_id
, status
, adv
, lpa
, stat_ge
;
188 int media
, speed
, duplex
;
191 /* Check if the PHY is up to snuff... */
192 for (phy_addr
= 0; phy_addr
< CONFIG_PHY_MAX_ADDR
; phy_addr
++) {
194 ftgmac100_phy_read(dev
, phy_addr
, MII_PHYSID1
, &phy_id
);
197 * When it is unable to found PHY,
198 * the interface usually return 0xffff or 0x0000
200 if (phy_id
!= 0xffff && phy_id
!= 0x0) {
201 printf("%s: found PHY at 0x%02x\n",
202 dev
->name
, phy_addr
);
203 priv
->phy_addr
= phy_addr
;
208 if (phy_id
== 0xffff || phy_id
== 0x0) {
209 printf("%s: no PHY present\n", dev
->name
);
213 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &status
);
215 if (!(status
& BMSR_LSTATUS
)) {
216 /* Try to re-negotiate if we don't have link already. */
217 ftgmac100_phy_reset(dev
);
219 for (i
= 0; i
< 100000 / 100; i
++) {
220 ftgmac100_phy_read(dev
, priv
->phy_addr
,
222 if (status
& BMSR_LSTATUS
)
228 if (!(status
& BMSR_LSTATUS
)) {
229 printf("%s: link down\n", dev
->name
);
233 #ifdef CONFIG_FTGMAC100_EGIGA
234 /* 1000 Base-T Status Register */
235 ftgmac100_phy_read(dev
, priv
->phy_addr
,
236 MII_STAT1000
, &stat_ge
);
238 speed
= (stat_ge
& (LPA_1000FULL
| LPA_1000HALF
)
241 duplex
= ((stat_ge
& LPA_1000FULL
)
244 if (speed
) { /* Speed is 1000 */
245 printf("%s: link up, 1000bps %s-duplex\n",
246 dev
->name
, duplex
? "full" : "half");
251 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_ADVERTISE
, &adv
);
252 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_LPA
, &lpa
);
254 media
= mii_nway_result(lpa
& adv
);
255 speed
= (media
& (ADVERTISE_100FULL
| ADVERTISE_100HALF
) ? 1 : 0);
256 duplex
= (media
& ADVERTISE_FULL
) ? 1 : 0;
258 printf("%s: link up, %sMbps %s-duplex\n",
259 dev
->name
, speed
? "100" : "10", duplex
? "full" : "half");
264 static int ftgmac100_update_link_speed(struct eth_device
*dev
)
266 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
267 struct ftgmac100_data
*priv
= dev
->priv
;
269 unsigned short stat_fe
;
270 unsigned short stat_ge
;
273 #ifdef CONFIG_FTGMAC100_EGIGA
274 /* 1000 Base-T Status Register */
275 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_STAT1000
, &stat_ge
);
278 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &stat_fe
);
280 if (!(stat_fe
& BMSR_LSTATUS
)) /* link status up? */
283 /* read MAC control register and clear related bits */
284 maccr
= readl(&ftgmac100
->maccr
) &
285 ~(FTGMAC100_MACCR_GIGA_MODE
|
286 FTGMAC100_MACCR_FAST_MODE
|
287 FTGMAC100_MACCR_FULLDUP
);
289 #ifdef CONFIG_FTGMAC100_EGIGA
290 if (stat_ge
& LPA_1000FULL
) {
291 /* set gmac for 1000BaseTX and Full Duplex */
292 maccr
|= FTGMAC100_MACCR_GIGA_MODE
| FTGMAC100_MACCR_FULLDUP
;
295 if (stat_ge
& LPA_1000HALF
) {
296 /* set gmac for 1000BaseTX and Half Duplex */
297 maccr
|= FTGMAC100_MACCR_GIGA_MODE
;
301 if (stat_fe
& BMSR_100FULL
) {
302 /* set MII for 100BaseTX and Full Duplex */
303 maccr
|= FTGMAC100_MACCR_FAST_MODE
| FTGMAC100_MACCR_FULLDUP
;
306 if (stat_fe
& BMSR_10FULL
) {
307 /* set MII for 10BaseT and Full Duplex */
308 maccr
|= FTGMAC100_MACCR_FULLDUP
;
311 if (stat_fe
& BMSR_100HALF
) {
312 /* set MII for 100BaseTX and Half Duplex */
313 maccr
|= FTGMAC100_MACCR_FAST_MODE
;
316 if (stat_fe
& BMSR_10HALF
) {
317 /* set MII for 10BaseT and Half Duplex */
318 /* we have already clear these bits, do nothing */
322 /* update MII config into maccr */
323 writel(maccr
, &ftgmac100
->maccr
);
331 static void ftgmac100_reset(struct eth_device
*dev
)
333 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
335 debug("%s()\n", __func__
);
337 writel(FTGMAC100_MACCR_SW_RST
, &ftgmac100
->maccr
);
339 while (readl(&ftgmac100
->maccr
) & FTGMAC100_MACCR_SW_RST
)
346 static void ftgmac100_set_mac(struct eth_device
*dev
,
347 const unsigned char *mac
)
349 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
350 unsigned int maddr
= mac
[0] << 8 | mac
[1];
351 unsigned int laddr
= mac
[2] << 24 | mac
[3] << 16 | mac
[4] << 8 | mac
[5];
353 debug("%s(%x %x)\n", __func__
, maddr
, laddr
);
355 writel(maddr
, &ftgmac100
->mac_madr
);
356 writel(laddr
, &ftgmac100
->mac_ladr
);
359 static void ftgmac100_set_mac_from_env(struct eth_device
*dev
)
361 eth_getenv_enetaddr("ethaddr", dev
->enetaddr
);
363 ftgmac100_set_mac(dev
, dev
->enetaddr
);
367 * disable transmitter, receiver
369 static void ftgmac100_halt(struct eth_device
*dev
)
371 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
373 debug("%s()\n", __func__
);
375 writel(0, &ftgmac100
->maccr
);
378 static int ftgmac100_init(struct eth_device
*dev
, bd_t
*bd
)
380 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
381 struct ftgmac100_data
*priv
= dev
->priv
;
382 struct ftgmac100_txdes
*txdes
;
383 struct ftgmac100_rxdes
*rxdes
;
388 debug("%s()\n", __func__
);
391 txdes
= dma_alloc_coherent(
392 sizeof(*txdes
) * PKTBUFSTX
, &priv
->txdes_dma
);
394 panic("ftgmac100: out of memory\n");
395 memset(txdes
, 0, sizeof(*txdes
) * PKTBUFSTX
);
401 rxdes
= dma_alloc_coherent(
402 sizeof(*rxdes
) * PKTBUFSRX
, &priv
->rxdes_dma
);
404 panic("ftgmac100: out of memory\n");
405 memset(rxdes
, 0, sizeof(*rxdes
) * PKTBUFSRX
);
410 /* set the ethernet address */
411 ftgmac100_set_mac_from_env(dev
);
413 /* disable all interrupts */
414 writel(0, &ftgmac100
->ier
);
416 /* initialize descriptors */
420 txdes
[PKTBUFSTX
- 1].txdes0
= FTGMAC100_TXDES0_EDOTR
;
421 rxdes
[PKTBUFSRX
- 1].rxdes0
= FTGMAC100_RXDES0_EDORR
;
423 for (i
= 0; i
< PKTBUFSTX
; i
++) {
425 if (!txdes
[i
].txdes2
) {
426 buf
= memalign(ARCH_DMA_MINALIGN
, CFG_XBUF_SIZE
);
428 panic("ftgmac100: out of memory\n");
429 txdes
[i
].txdes3
= virt_to_phys(buf
);
430 txdes
[i
].txdes2
= (uint
)buf
;
435 for (i
= 0; i
< PKTBUFSRX
; i
++) {
437 if (!rxdes
[i
].rxdes2
) {
438 buf
= NetRxPackets
[i
];
439 rxdes
[i
].rxdes3
= virt_to_phys(buf
);
440 rxdes
[i
].rxdes2
= (uint
)buf
;
442 rxdes
[i
].rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
446 writel(priv
->txdes_dma
, &ftgmac100
->txr_badr
);
449 writel(priv
->rxdes_dma
, &ftgmac100
->rxr_badr
);
451 /* poll receive descriptor automatically */
452 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100
->aptc
);
454 /* config receive buffer size register */
455 writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE
), &ftgmac100
->rbsr
);
457 /* enable transmitter, receiver */
458 maccr
= FTGMAC100_MACCR_TXMAC_EN
|
459 FTGMAC100_MACCR_RXMAC_EN
|
460 FTGMAC100_MACCR_TXDMA_EN
|
461 FTGMAC100_MACCR_RXDMA_EN
|
462 FTGMAC100_MACCR_CRC_APD
|
463 FTGMAC100_MACCR_FULLDUP
|
464 FTGMAC100_MACCR_RX_RUNT
|
465 FTGMAC100_MACCR_RX_BROADPKT
;
467 writel(maccr
, &ftgmac100
->maccr
);
469 if (!ftgmac100_phy_init(dev
)) {
470 if (!ftgmac100_update_link_speed(dev
))
478 * Get a data block via Ethernet
480 static int ftgmac100_recv(struct eth_device
*dev
)
482 struct ftgmac100_data
*priv
= dev
->priv
;
483 struct ftgmac100_rxdes
*curr_des
;
484 unsigned short rxlen
;
486 curr_des
= &priv
->rxdes
[priv
->rx_index
];
488 if (!(curr_des
->rxdes0
& FTGMAC100_RXDES0_RXPKT_RDY
))
491 if (curr_des
->rxdes0
& (FTGMAC100_RXDES0_RX_ERR
|
492 FTGMAC100_RXDES0_CRC_ERR
|
493 FTGMAC100_RXDES0_FTL
|
494 FTGMAC100_RXDES0_RUNT
|
495 FTGMAC100_RXDES0_RX_ODD_NB
)) {
499 rxlen
= FTGMAC100_RXDES0_VDBC(curr_des
->rxdes0
);
501 debug("%s(): RX buffer %d, %x received\n",
502 __func__
, priv
->rx_index
, rxlen
);
504 /* invalidate d-cache */
505 dma_map_single((void *)curr_des
->rxdes2
, rxlen
, DMA_FROM_DEVICE
);
507 /* pass the packet up to the protocol layers. */
508 NetReceive((void *)curr_des
->rxdes2
, rxlen
);
510 /* release buffer to DMA */
511 curr_des
->rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
513 priv
->rx_index
= (priv
->rx_index
+ 1) % PKTBUFSRX
;
519 * Send a data block via Ethernet
521 static int ftgmac100_send(struct eth_device
*dev
, void *packet
, int length
)
523 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
524 struct ftgmac100_data
*priv
= dev
->priv
;
525 struct ftgmac100_txdes
*curr_des
= &priv
->txdes
[priv
->tx_index
];
527 if (curr_des
->txdes0
& FTGMAC100_TXDES0_TXDMA_OWN
) {
528 debug("%s(): no TX descriptor available\n", __func__
);
532 debug("%s(%x, %x)\n", __func__
, (int)packet
, length
);
534 length
= (length
< ETH_ZLEN
) ? ETH_ZLEN
: length
;
536 memcpy((void *)curr_des
->txdes2
, (void *)packet
, length
);
537 dma_map_single((void *)curr_des
->txdes2
, length
, DMA_TO_DEVICE
);
539 /* only one descriptor on TXBUF */
540 curr_des
->txdes0
&= FTGMAC100_TXDES0_EDOTR
;
541 curr_des
->txdes0
|= FTGMAC100_TXDES0_FTS
|
542 FTGMAC100_TXDES0_LTS
|
543 FTGMAC100_TXDES0_TXBUF_SIZE(length
) |
544 FTGMAC100_TXDES0_TXDMA_OWN
;
547 writel(1, &ftgmac100
->txpd
);
549 debug("%s(): packet sent\n", __func__
);
551 priv
->tx_index
= (priv
->tx_index
+ 1) % PKTBUFSTX
;
556 int ftgmac100_initialize(bd_t
*bd
)
558 struct eth_device
*dev
;
559 struct ftgmac100_data
*priv
;
561 dev
= malloc(sizeof *dev
);
563 printf("%s(): failed to allocate dev\n", __func__
);
567 /* Transmit and receive descriptors should align to 16 bytes */
568 priv
= memalign(16, sizeof(struct ftgmac100_data
));
570 printf("%s(): failed to allocate priv\n", __func__
);
574 memset(dev
, 0, sizeof(*dev
));
575 memset(priv
, 0, sizeof(*priv
));
577 sprintf(dev
->name
, "FTGMAC100");
578 dev
->iobase
= CONFIG_FTGMAC100_BASE
;
579 dev
->init
= ftgmac100_init
;
580 dev
->halt
= ftgmac100_halt
;
581 dev
->send
= ftgmac100_send
;
582 dev
->recv
= ftgmac100_recv
;
587 ftgmac100_reset(dev
);