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 * SPDX-License-Identifier: GPL-2.0+
18 #include <asm/dma-mapping.h>
19 #include <linux/mii.h>
21 #include "ftgmac100.h"
24 #define CFG_XBUF_SIZE 1536
26 /* RBSR - hw default init value is also 0x640 */
27 #define RBSR_DEFAULT_VALUE 0x640
29 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
30 #define PKTBUFSTX 4 /* must be power of 2 */
32 struct ftgmac100_data
{
34 struct ftgmac100_txdes
*txdes
;
36 struct ftgmac100_rxdes
*rxdes
;
43 * struct mii_bus functions
45 static int ftgmac100_mdiobus_read(struct eth_device
*dev
, int phy_addr
,
48 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
52 phycr
= readl(&ftgmac100
->phycr
);
54 /* preserve MDC cycle threshold */
55 phycr
&= FTGMAC100_PHYCR_MDC_CYCTHR_MASK
;
57 phycr
|= FTGMAC100_PHYCR_PHYAD(phy_addr
)
58 | FTGMAC100_PHYCR_REGAD(regnum
)
59 | FTGMAC100_PHYCR_MIIRD
;
61 writel(phycr
, &ftgmac100
->phycr
);
63 for (i
= 0; i
< 10; i
++) {
64 phycr
= readl(&ftgmac100
->phycr
);
66 if ((phycr
& FTGMAC100_PHYCR_MIIRD
) == 0) {
69 data
= readl(&ftgmac100
->phydata
);
70 return FTGMAC100_PHYDATA_MIIRDATA(data
);
76 debug("mdio read timed out\n");
80 static int ftgmac100_mdiobus_write(struct eth_device
*dev
, int phy_addr
,
81 int regnum
, u16 value
)
83 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
88 phycr
= readl(&ftgmac100
->phycr
);
90 /* preserve MDC cycle threshold */
91 phycr
&= FTGMAC100_PHYCR_MDC_CYCTHR_MASK
;
93 phycr
|= FTGMAC100_PHYCR_PHYAD(phy_addr
)
94 | FTGMAC100_PHYCR_REGAD(regnum
)
95 | FTGMAC100_PHYCR_MIIWR
;
97 data
= FTGMAC100_PHYDATA_MIIWDATA(value
);
99 writel(data
, &ftgmac100
->phydata
);
100 writel(phycr
, &ftgmac100
->phycr
);
102 for (i
= 0; i
< 10; i
++) {
103 phycr
= readl(&ftgmac100
->phycr
);
105 if ((phycr
& FTGMAC100_PHYCR_MIIWR
) == 0) {
106 debug("(phycr & FTGMAC100_PHYCR_MIIWR) == 0: " \
107 "phy_addr: %x\n", phy_addr
);
114 debug("mdio write timed out\n");
118 int ftgmac100_phy_read(struct eth_device
*dev
, int addr
, int reg
, u16
*value
)
120 *value
= ftgmac100_mdiobus_read(dev
, addr
, reg
);
128 int ftgmac100_phy_write(struct eth_device
*dev
, int addr
, int reg
, u16 value
)
130 if (ftgmac100_mdiobus_write(dev
, addr
, reg
, value
) == -1)
136 static int ftgmac100_phy_reset(struct eth_device
*dev
)
138 struct ftgmac100_data
*priv
= dev
->priv
;
142 adv
= ADVERTISE_CSMA
| ADVERTISE_ALL
;
144 ftgmac100_phy_write(dev
, priv
->phy_addr
, MII_ADVERTISE
, adv
);
146 printf("%s: Starting autonegotiation...\n", dev
->name
);
148 ftgmac100_phy_write(dev
, priv
->phy_addr
,
149 MII_BMCR
, (BMCR_ANENABLE
| BMCR_ANRESTART
));
151 for (i
= 0; i
< 100000 / 100; i
++) {
152 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &status
);
154 if (status
& BMSR_ANEGCOMPLETE
)
159 if (status
& BMSR_ANEGCOMPLETE
) {
160 printf("%s: Autonegotiation complete\n", dev
->name
);
162 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
170 static int ftgmac100_phy_init(struct eth_device
*dev
)
172 struct ftgmac100_data
*priv
= dev
->priv
;
175 u16 phy_id
, status
, adv
, lpa
, stat_ge
;
176 int media
, speed
, duplex
;
179 /* Check if the PHY is up to snuff... */
180 for (phy_addr
= 0; phy_addr
< CONFIG_PHY_MAX_ADDR
; phy_addr
++) {
182 ftgmac100_phy_read(dev
, phy_addr
, MII_PHYSID1
, &phy_id
);
185 * When it is unable to found PHY,
186 * the interface usually return 0xffff or 0x0000
188 if (phy_id
!= 0xffff && phy_id
!= 0x0) {
189 printf("%s: found PHY at 0x%02x\n",
190 dev
->name
, phy_addr
);
191 priv
->phy_addr
= phy_addr
;
196 if (phy_id
== 0xffff || phy_id
== 0x0) {
197 printf("%s: no PHY present\n", dev
->name
);
201 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &status
);
203 if (!(status
& BMSR_LSTATUS
)) {
204 /* Try to re-negotiate if we don't have link already. */
205 ftgmac100_phy_reset(dev
);
207 for (i
= 0; i
< 100000 / 100; i
++) {
208 ftgmac100_phy_read(dev
, priv
->phy_addr
,
210 if (status
& BMSR_LSTATUS
)
216 if (!(status
& BMSR_LSTATUS
)) {
217 printf("%s: link down\n", dev
->name
);
221 #ifdef CONFIG_FTGMAC100_EGIGA
222 /* 1000 Base-T Status Register */
223 ftgmac100_phy_read(dev
, priv
->phy_addr
,
224 MII_STAT1000
, &stat_ge
);
226 speed
= (stat_ge
& (LPA_1000FULL
| LPA_1000HALF
)
229 duplex
= ((stat_ge
& LPA_1000FULL
)
232 if (speed
) { /* Speed is 1000 */
233 printf("%s: link up, 1000bps %s-duplex\n",
234 dev
->name
, duplex
? "full" : "half");
239 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_ADVERTISE
, &adv
);
240 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_LPA
, &lpa
);
242 media
= mii_nway_result(lpa
& adv
);
243 speed
= (media
& (ADVERTISE_100FULL
| ADVERTISE_100HALF
) ? 1 : 0);
244 duplex
= (media
& ADVERTISE_FULL
) ? 1 : 0;
246 printf("%s: link up, %sMbps %s-duplex\n",
247 dev
->name
, speed
? "100" : "10", duplex
? "full" : "half");
252 static int ftgmac100_update_link_speed(struct eth_device
*dev
)
254 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
255 struct ftgmac100_data
*priv
= dev
->priv
;
257 unsigned short stat_fe
;
258 unsigned short stat_ge
;
261 #ifdef CONFIG_FTGMAC100_EGIGA
262 /* 1000 Base-T Status Register */
263 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_STAT1000
, &stat_ge
);
266 ftgmac100_phy_read(dev
, priv
->phy_addr
, MII_BMSR
, &stat_fe
);
268 if (!(stat_fe
& BMSR_LSTATUS
)) /* link status up? */
271 /* read MAC control register and clear related bits */
272 maccr
= readl(&ftgmac100
->maccr
) &
273 ~(FTGMAC100_MACCR_GIGA_MODE
|
274 FTGMAC100_MACCR_FAST_MODE
|
275 FTGMAC100_MACCR_FULLDUP
);
277 #ifdef CONFIG_FTGMAC100_EGIGA
278 if (stat_ge
& LPA_1000FULL
) {
279 /* set gmac for 1000BaseTX and Full Duplex */
280 maccr
|= FTGMAC100_MACCR_GIGA_MODE
| FTGMAC100_MACCR_FULLDUP
;
283 if (stat_ge
& LPA_1000HALF
) {
284 /* set gmac for 1000BaseTX and Half Duplex */
285 maccr
|= FTGMAC100_MACCR_GIGA_MODE
;
289 if (stat_fe
& BMSR_100FULL
) {
290 /* set MII for 100BaseTX and Full Duplex */
291 maccr
|= FTGMAC100_MACCR_FAST_MODE
| FTGMAC100_MACCR_FULLDUP
;
294 if (stat_fe
& BMSR_10FULL
) {
295 /* set MII for 10BaseT and Full Duplex */
296 maccr
|= FTGMAC100_MACCR_FULLDUP
;
299 if (stat_fe
& BMSR_100HALF
) {
300 /* set MII for 100BaseTX and Half Duplex */
301 maccr
|= FTGMAC100_MACCR_FAST_MODE
;
304 if (stat_fe
& BMSR_10HALF
) {
305 /* set MII for 10BaseT and Half Duplex */
306 /* we have already clear these bits, do nothing */
310 /* update MII config into maccr */
311 writel(maccr
, &ftgmac100
->maccr
);
319 static void ftgmac100_reset(struct eth_device
*dev
)
321 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
323 debug("%s()\n", __func__
);
325 writel(FTGMAC100_MACCR_SW_RST
, &ftgmac100
->maccr
);
327 while (readl(&ftgmac100
->maccr
) & FTGMAC100_MACCR_SW_RST
)
334 static void ftgmac100_set_mac(struct eth_device
*dev
,
335 const unsigned char *mac
)
337 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
338 unsigned int maddr
= mac
[0] << 8 | mac
[1];
339 unsigned int laddr
= mac
[2] << 24 | mac
[3] << 16 | mac
[4] << 8 | mac
[5];
341 debug("%s(%x %x)\n", __func__
, maddr
, laddr
);
343 writel(maddr
, &ftgmac100
->mac_madr
);
344 writel(laddr
, &ftgmac100
->mac_ladr
);
347 static void ftgmac100_set_mac_from_env(struct eth_device
*dev
)
349 eth_getenv_enetaddr("ethaddr", dev
->enetaddr
);
351 ftgmac100_set_mac(dev
, dev
->enetaddr
);
355 * disable transmitter, receiver
357 static void ftgmac100_halt(struct eth_device
*dev
)
359 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
361 debug("%s()\n", __func__
);
363 writel(0, &ftgmac100
->maccr
);
366 static int ftgmac100_init(struct eth_device
*dev
, bd_t
*bd
)
368 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
369 struct ftgmac100_data
*priv
= dev
->priv
;
370 struct ftgmac100_txdes
*txdes
;
371 struct ftgmac100_rxdes
*rxdes
;
376 debug("%s()\n", __func__
);
379 txdes
= dma_alloc_coherent(
380 sizeof(*txdes
) * PKTBUFSTX
, &priv
->txdes_dma
);
382 panic("ftgmac100: out of memory\n");
383 memset(txdes
, 0, sizeof(*txdes
) * PKTBUFSTX
);
389 rxdes
= dma_alloc_coherent(
390 sizeof(*rxdes
) * PKTBUFSRX
, &priv
->rxdes_dma
);
392 panic("ftgmac100: out of memory\n");
393 memset(rxdes
, 0, sizeof(*rxdes
) * PKTBUFSRX
);
398 /* set the ethernet address */
399 ftgmac100_set_mac_from_env(dev
);
401 /* disable all interrupts */
402 writel(0, &ftgmac100
->ier
);
404 /* initialize descriptors */
408 txdes
[PKTBUFSTX
- 1].txdes0
= FTGMAC100_TXDES0_EDOTR
;
409 rxdes
[PKTBUFSRX
- 1].rxdes0
= FTGMAC100_RXDES0_EDORR
;
411 for (i
= 0; i
< PKTBUFSTX
; i
++) {
413 if (!txdes
[i
].txdes2
) {
414 buf
= memalign(ARCH_DMA_MINALIGN
, CFG_XBUF_SIZE
);
416 panic("ftgmac100: out of memory\n");
417 txdes
[i
].txdes3
= virt_to_phys(buf
);
418 txdes
[i
].txdes2
= (uint
)buf
;
423 for (i
= 0; i
< PKTBUFSRX
; i
++) {
425 if (!rxdes
[i
].rxdes2
) {
426 buf
= net_rx_packets
[i
];
427 rxdes
[i
].rxdes3
= virt_to_phys(buf
);
428 rxdes
[i
].rxdes2
= (uint
)buf
;
430 rxdes
[i
].rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
434 writel(priv
->txdes_dma
, &ftgmac100
->txr_badr
);
437 writel(priv
->rxdes_dma
, &ftgmac100
->rxr_badr
);
439 /* poll receive descriptor automatically */
440 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100
->aptc
);
442 /* config receive buffer size register */
443 writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE
), &ftgmac100
->rbsr
);
445 /* enable transmitter, receiver */
446 maccr
= FTGMAC100_MACCR_TXMAC_EN
|
447 FTGMAC100_MACCR_RXMAC_EN
|
448 FTGMAC100_MACCR_TXDMA_EN
|
449 FTGMAC100_MACCR_RXDMA_EN
|
450 FTGMAC100_MACCR_CRC_APD
|
451 FTGMAC100_MACCR_FULLDUP
|
452 FTGMAC100_MACCR_RX_RUNT
|
453 FTGMAC100_MACCR_RX_BROADPKT
;
455 writel(maccr
, &ftgmac100
->maccr
);
457 if (!ftgmac100_phy_init(dev
)) {
458 if (!ftgmac100_update_link_speed(dev
))
466 * Get a data block via Ethernet
468 static int ftgmac100_recv(struct eth_device
*dev
)
470 struct ftgmac100_data
*priv
= dev
->priv
;
471 struct ftgmac100_rxdes
*curr_des
;
472 unsigned short rxlen
;
474 curr_des
= &priv
->rxdes
[priv
->rx_index
];
476 if (!(curr_des
->rxdes0
& FTGMAC100_RXDES0_RXPKT_RDY
))
479 if (curr_des
->rxdes0
& (FTGMAC100_RXDES0_RX_ERR
|
480 FTGMAC100_RXDES0_CRC_ERR
|
481 FTGMAC100_RXDES0_FTL
|
482 FTGMAC100_RXDES0_RUNT
|
483 FTGMAC100_RXDES0_RX_ODD_NB
)) {
487 rxlen
= FTGMAC100_RXDES0_VDBC(curr_des
->rxdes0
);
489 debug("%s(): RX buffer %d, %x received\n",
490 __func__
, priv
->rx_index
, rxlen
);
492 /* invalidate d-cache */
493 dma_map_single((void *)curr_des
->rxdes2
, rxlen
, DMA_FROM_DEVICE
);
495 /* pass the packet up to the protocol layers. */
496 net_process_received_packet((void *)curr_des
->rxdes2
, rxlen
);
498 /* release buffer to DMA */
499 curr_des
->rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
501 priv
->rx_index
= (priv
->rx_index
+ 1) % PKTBUFSRX
;
507 * Send a data block via Ethernet
509 static int ftgmac100_send(struct eth_device
*dev
, void *packet
, int length
)
511 struct ftgmac100
*ftgmac100
= (struct ftgmac100
*)dev
->iobase
;
512 struct ftgmac100_data
*priv
= dev
->priv
;
513 struct ftgmac100_txdes
*curr_des
= &priv
->txdes
[priv
->tx_index
];
515 if (curr_des
->txdes0
& FTGMAC100_TXDES0_TXDMA_OWN
) {
516 debug("%s(): no TX descriptor available\n", __func__
);
520 debug("%s(%x, %x)\n", __func__
, (int)packet
, length
);
522 length
= (length
< ETH_ZLEN
) ? ETH_ZLEN
: length
;
524 memcpy((void *)curr_des
->txdes2
, (void *)packet
, length
);
525 dma_map_single((void *)curr_des
->txdes2
, length
, DMA_TO_DEVICE
);
527 /* only one descriptor on TXBUF */
528 curr_des
->txdes0
&= FTGMAC100_TXDES0_EDOTR
;
529 curr_des
->txdes0
|= FTGMAC100_TXDES0_FTS
|
530 FTGMAC100_TXDES0_LTS
|
531 FTGMAC100_TXDES0_TXBUF_SIZE(length
) |
532 FTGMAC100_TXDES0_TXDMA_OWN
;
535 writel(1, &ftgmac100
->txpd
);
537 debug("%s(): packet sent\n", __func__
);
539 priv
->tx_index
= (priv
->tx_index
+ 1) % PKTBUFSTX
;
544 int ftgmac100_initialize(bd_t
*bd
)
546 struct eth_device
*dev
;
547 struct ftgmac100_data
*priv
;
549 dev
= malloc(sizeof *dev
);
551 printf("%s(): failed to allocate dev\n", __func__
);
555 /* Transmit and receive descriptors should align to 16 bytes */
556 priv
= memalign(16, sizeof(struct ftgmac100_data
));
558 printf("%s(): failed to allocate priv\n", __func__
);
562 memset(dev
, 0, sizeof(*dev
));
563 memset(priv
, 0, sizeof(*priv
));
565 strcpy(dev
->name
, "FTGMAC100");
566 dev
->iobase
= CONFIG_FTGMAC100_BASE
;
567 dev
->init
= ftgmac100_init
;
568 dev
->halt
= ftgmac100_halt
;
569 dev
->send
= ftgmac100_send
;
570 dev
->recv
= ftgmac100_recv
;
575 ftgmac100_reset(dev
);