1 // SPDX-License-Identifier: GPL-2.0+
3 * Faraday FTGMAC100 Ethernet
5 * (C) Copyright 2009 Faraday Technology
6 * Po-Yu Chuang <ratbert@faraday-tech.com>
8 * (C) Copyright 2010 Andes Technology
9 * Macpaul Lin <macpaul@andestech.com>
11 * Copyright (C) 2018, IBM Corporation.
21 #include <dm/device_compat.h>
23 #include <linux/iopoll.h>
25 #include "ftgmac100.h"
27 /* Min frame ethernet frame size without FCS */
30 /* Receive Buffer Size Register - HW default is 0x640 */
31 #define FTGMAC100_RBSR_DEFAULT 0x640
33 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
34 #define PKTBUFSTX 4 /* must be power of 2 */
36 /* Timeout for transmit */
37 #define FTGMAC100_TX_TIMEOUT_MS 1000
39 /* Timeout for a mdio read/write operation */
40 #define FTGMAC100_MDIO_TIMEOUT_USEC 10000
43 * MDC clock cycle threshold
45 * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
47 #define MDC_CYCTHR 0x34
50 * ftgmac100 model variants
52 enum ftgmac100_model
{
53 FTGMAC100_MODEL_FARADAY
,
54 FTGMAC100_MODEL_ASPEED
,
58 * struct ftgmac100_data - private data for the FTGMAC100 driver
60 * @iobase: The base address of the hardware registers
61 * @txdes: The array of transmit descriptors
62 * @rxdes: The array of receive descriptors
63 * @tx_index: Transmit descriptor index in @txdes
64 * @rx_index: Receive descriptor index in @rxdes
65 * @phy_addr: The PHY interface address to use
66 * @phydev: The PHY device backing the MAC
68 * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
69 * @max_speed: Maximum speed of Ethernet connection supported by MAC
70 * @clks: The bulk of clocks assigned to the device in the DT
71 * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
72 * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
74 struct ftgmac100_data
{
75 struct ftgmac100
*iobase
;
77 struct ftgmac100_txdes txdes
[PKTBUFSTX
] __aligned(ARCH_DMA_MINALIGN
);
78 struct ftgmac100_rxdes rxdes
[PKTBUFSRX
] __aligned(ARCH_DMA_MINALIGN
);
83 struct phy_device
*phydev
;
90 /* End of RX/TX ring buffer bits. Depend on model */
91 u32 rxdes0_edorr_mask
;
92 u32 txdes0_edotr_mask
;
96 * struct mii_bus functions
98 static int ftgmac100_mdio_read(struct mii_dev
*bus
, int phy_addr
, int dev_addr
,
101 struct ftgmac100_data
*priv
= bus
->priv
;
102 struct ftgmac100
*ftgmac100
= priv
->iobase
;
107 phycr
= FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR
) |
108 FTGMAC100_PHYCR_PHYAD(phy_addr
) |
109 FTGMAC100_PHYCR_REGAD(reg_addr
) |
110 FTGMAC100_PHYCR_MIIRD
;
111 writel(phycr
, &ftgmac100
->phycr
);
113 ret
= readl_poll_timeout(&ftgmac100
->phycr
, phycr
,
114 !(phycr
& FTGMAC100_PHYCR_MIIRD
),
115 FTGMAC100_MDIO_TIMEOUT_USEC
);
117 pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
118 priv
->phydev
->dev
->name
, phy_addr
, reg_addr
);
122 data
= readl(&ftgmac100
->phydata
);
124 return FTGMAC100_PHYDATA_MIIRDATA(data
);
127 static int ftgmac100_mdio_write(struct mii_dev
*bus
, int phy_addr
, int dev_addr
,
128 int reg_addr
, u16 value
)
130 struct ftgmac100_data
*priv
= bus
->priv
;
131 struct ftgmac100
*ftgmac100
= priv
->iobase
;
136 phycr
= FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR
) |
137 FTGMAC100_PHYCR_PHYAD(phy_addr
) |
138 FTGMAC100_PHYCR_REGAD(reg_addr
) |
139 FTGMAC100_PHYCR_MIIWR
;
140 data
= FTGMAC100_PHYDATA_MIIWDATA(value
);
142 writel(data
, &ftgmac100
->phydata
);
143 writel(phycr
, &ftgmac100
->phycr
);
145 ret
= readl_poll_timeout(&ftgmac100
->phycr
, phycr
,
146 !(phycr
& FTGMAC100_PHYCR_MIIWR
),
147 FTGMAC100_MDIO_TIMEOUT_USEC
);
149 pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
150 priv
->phydev
->dev
->name
, phy_addr
, reg_addr
);
156 static int ftgmac100_mdio_init(struct udevice
*dev
)
158 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
166 bus
->read
= ftgmac100_mdio_read
;
167 bus
->write
= ftgmac100_mdio_write
;
170 ret
= mdio_register_seq(bus
, dev
->seq
);
181 static int ftgmac100_phy_adjust_link(struct ftgmac100_data
*priv
)
183 struct ftgmac100
*ftgmac100
= priv
->iobase
;
184 struct phy_device
*phydev
= priv
->phydev
;
188 dev_err(phydev
->dev
, "No link\n");
192 /* read MAC control register and clear related bits */
193 maccr
= readl(&ftgmac100
->maccr
) &
194 ~(FTGMAC100_MACCR_GIGA_MODE
|
195 FTGMAC100_MACCR_FAST_MODE
|
196 FTGMAC100_MACCR_FULLDUP
);
198 if (phy_interface_is_rgmii(phydev
) && phydev
->speed
== 1000)
199 maccr
|= FTGMAC100_MACCR_GIGA_MODE
;
201 if (phydev
->speed
== 100)
202 maccr
|= FTGMAC100_MACCR_FAST_MODE
;
205 maccr
|= FTGMAC100_MACCR_FULLDUP
;
207 /* update MII config into maccr */
208 writel(maccr
, &ftgmac100
->maccr
);
213 static int ftgmac100_phy_init(struct udevice
*dev
)
215 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
216 struct phy_device
*phydev
;
219 phydev
= phy_connect(priv
->bus
, priv
->phy_addr
, dev
, priv
->phy_mode
);
223 phydev
->supported
&= PHY_GBIT_FEATURES
;
224 if (priv
->max_speed
) {
225 ret
= phy_set_supported(phydev
, priv
->max_speed
);
229 phydev
->advertising
= phydev
->supported
;
230 priv
->phydev
= phydev
;
239 static void ftgmac100_reset(struct ftgmac100_data
*priv
)
241 struct ftgmac100
*ftgmac100
= priv
->iobase
;
243 debug("%s()\n", __func__
);
245 setbits_le32(&ftgmac100
->maccr
, FTGMAC100_MACCR_SW_RST
);
247 while (readl(&ftgmac100
->maccr
) & FTGMAC100_MACCR_SW_RST
)
254 static int ftgmac100_set_mac(struct ftgmac100_data
*priv
,
255 const unsigned char *mac
)
257 struct ftgmac100
*ftgmac100
= priv
->iobase
;
258 unsigned int maddr
= mac
[0] << 8 | mac
[1];
259 unsigned int laddr
= mac
[2] << 24 | mac
[3] << 16 | mac
[4] << 8 | mac
[5];
261 debug("%s(%x %x)\n", __func__
, maddr
, laddr
);
263 writel(maddr
, &ftgmac100
->mac_madr
);
264 writel(laddr
, &ftgmac100
->mac_ladr
);
270 * disable transmitter, receiver
272 static void ftgmac100_stop(struct udevice
*dev
)
274 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
275 struct ftgmac100
*ftgmac100
= priv
->iobase
;
277 debug("%s()\n", __func__
);
279 writel(0, &ftgmac100
->maccr
);
281 phy_shutdown(priv
->phydev
);
284 static int ftgmac100_start(struct udevice
*dev
)
286 struct eth_pdata
*plat
= dev_get_platdata(dev
);
287 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
288 struct ftgmac100
*ftgmac100
= priv
->iobase
;
289 struct phy_device
*phydev
= priv
->phydev
;
295 debug("%s()\n", __func__
);
297 ftgmac100_reset(priv
);
299 /* set the ethernet address */
300 ftgmac100_set_mac(priv
, plat
->enetaddr
);
302 /* disable all interrupts */
303 writel(0, &ftgmac100
->ier
);
305 /* initialize descriptors */
309 for (i
= 0; i
< PKTBUFSTX
; i
++) {
310 priv
->txdes
[i
].txdes3
= 0;
311 priv
->txdes
[i
].txdes0
= 0;
313 priv
->txdes
[PKTBUFSTX
- 1].txdes0
= priv
->txdes0_edotr_mask
;
315 start
= ((ulong
)&priv
->txdes
[0]) & ~(ARCH_DMA_MINALIGN
- 1);
316 end
= start
+ roundup(sizeof(priv
->txdes
), ARCH_DMA_MINALIGN
);
317 flush_dcache_range(start
, end
);
319 for (i
= 0; i
< PKTBUFSRX
; i
++) {
320 priv
->rxdes
[i
].rxdes3
= (unsigned int)net_rx_packets
[i
];
321 priv
->rxdes
[i
].rxdes0
= 0;
323 priv
->rxdes
[PKTBUFSRX
- 1].rxdes0
= priv
->rxdes0_edorr_mask
;
325 start
= ((ulong
)&priv
->rxdes
[0]) & ~(ARCH_DMA_MINALIGN
- 1);
326 end
= start
+ roundup(sizeof(priv
->rxdes
), ARCH_DMA_MINALIGN
);
327 flush_dcache_range(start
, end
);
330 writel((u32
)priv
->txdes
, &ftgmac100
->txr_badr
);
333 writel((u32
)priv
->rxdes
, &ftgmac100
->rxr_badr
);
335 /* poll receive descriptor automatically */
336 writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100
->aptc
);
338 /* config receive buffer size register */
339 writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT
), &ftgmac100
->rbsr
);
341 /* enable transmitter, receiver */
342 maccr
= FTGMAC100_MACCR_TXMAC_EN
|
343 FTGMAC100_MACCR_RXMAC_EN
|
344 FTGMAC100_MACCR_TXDMA_EN
|
345 FTGMAC100_MACCR_RXDMA_EN
|
346 FTGMAC100_MACCR_CRC_APD
|
347 FTGMAC100_MACCR_FULLDUP
|
348 FTGMAC100_MACCR_RX_RUNT
|
349 FTGMAC100_MACCR_RX_BROADPKT
;
351 writel(maccr
, &ftgmac100
->maccr
);
353 ret
= phy_startup(phydev
);
355 dev_err(phydev
->dev
, "Could not start PHY\n");
359 ret
= ftgmac100_phy_adjust_link(priv
);
361 dev_err(phydev
->dev
, "Could not adjust link\n");
365 printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev
->dev
->name
,
366 phydev
->speed
, phydev
->duplex
? "full" : "half", plat
->enetaddr
);
371 static int ftgmac100_free_pkt(struct udevice
*dev
, uchar
*packet
, int length
)
373 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
374 struct ftgmac100_rxdes
*curr_des
= &priv
->rxdes
[priv
->rx_index
];
375 ulong des_start
= ((ulong
)curr_des
) & ~(ARCH_DMA_MINALIGN
- 1);
376 ulong des_end
= des_start
+
377 roundup(sizeof(*curr_des
), ARCH_DMA_MINALIGN
);
379 /* Release buffer to DMA and flush descriptor */
380 curr_des
->rxdes0
&= ~FTGMAC100_RXDES0_RXPKT_RDY
;
381 flush_dcache_range(des_start
, des_end
);
383 /* Move to next descriptor */
384 priv
->rx_index
= (priv
->rx_index
+ 1) % PKTBUFSRX
;
390 * Get a data block via Ethernet
392 static int ftgmac100_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
394 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
395 struct ftgmac100_rxdes
*curr_des
= &priv
->rxdes
[priv
->rx_index
];
396 unsigned short rxlen
;
397 ulong des_start
= ((ulong
)curr_des
) & ~(ARCH_DMA_MINALIGN
- 1);
398 ulong des_end
= des_start
+
399 roundup(sizeof(*curr_des
), ARCH_DMA_MINALIGN
);
400 ulong data_start
= curr_des
->rxdes3
;
403 invalidate_dcache_range(des_start
, des_end
);
405 if (!(curr_des
->rxdes0
& FTGMAC100_RXDES0_RXPKT_RDY
))
408 if (curr_des
->rxdes0
& (FTGMAC100_RXDES0_RX_ERR
|
409 FTGMAC100_RXDES0_CRC_ERR
|
410 FTGMAC100_RXDES0_FTL
|
411 FTGMAC100_RXDES0_RUNT
|
412 FTGMAC100_RXDES0_RX_ODD_NB
)) {
416 rxlen
= FTGMAC100_RXDES0_VDBC(curr_des
->rxdes0
);
418 debug("%s(): RX buffer %d, %x received\n",
419 __func__
, priv
->rx_index
, rxlen
);
421 /* Invalidate received data */
422 data_end
= data_start
+ roundup(rxlen
, ARCH_DMA_MINALIGN
);
423 invalidate_dcache_range(data_start
, data_end
);
424 *packetp
= (uchar
*)data_start
;
429 static u32
ftgmac100_read_txdesc(const void *desc
)
431 const struct ftgmac100_txdes
*txdes
= desc
;
432 ulong des_start
= ((ulong
)txdes
) & ~(ARCH_DMA_MINALIGN
- 1);
433 ulong des_end
= des_start
+ roundup(sizeof(*txdes
), ARCH_DMA_MINALIGN
);
435 invalidate_dcache_range(des_start
, des_end
);
437 return txdes
->txdes0
;
440 BUILD_WAIT_FOR_BIT(ftgmac100_txdone
, u32
, ftgmac100_read_txdesc
)
443 * Send a data block via Ethernet
445 static int ftgmac100_send(struct udevice
*dev
, void *packet
, int length
)
447 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
448 struct ftgmac100
*ftgmac100
= priv
->iobase
;
449 struct ftgmac100_txdes
*curr_des
= &priv
->txdes
[priv
->tx_index
];
450 ulong des_start
= ((ulong
)curr_des
) & ~(ARCH_DMA_MINALIGN
- 1);
451 ulong des_end
= des_start
+
452 roundup(sizeof(*curr_des
), ARCH_DMA_MINALIGN
);
457 invalidate_dcache_range(des_start
, des_end
);
459 if (curr_des
->txdes0
& FTGMAC100_TXDES0_TXDMA_OWN
) {
460 dev_err(dev
, "no TX descriptor available\n");
464 debug("%s(%x, %x)\n", __func__
, (int)packet
, length
);
466 length
= (length
< ETH_ZLEN
) ? ETH_ZLEN
: length
;
468 curr_des
->txdes3
= (unsigned int)packet
;
470 /* Flush data to be sent */
471 data_start
= curr_des
->txdes3
;
472 data_end
= data_start
+ roundup(length
, ARCH_DMA_MINALIGN
);
473 flush_dcache_range(data_start
, data_end
);
475 /* Only one segment on TXBUF */
476 curr_des
->txdes0
&= priv
->txdes0_edotr_mask
;
477 curr_des
->txdes0
|= FTGMAC100_TXDES0_FTS
|
478 FTGMAC100_TXDES0_LTS
|
479 FTGMAC100_TXDES0_TXBUF_SIZE(length
) |
480 FTGMAC100_TXDES0_TXDMA_OWN
;
482 /* Flush modified buffer descriptor */
483 flush_dcache_range(des_start
, des_end
);
486 writel(1, &ftgmac100
->txpd
);
488 rc
= wait_for_bit_ftgmac100_txdone(curr_des
,
489 FTGMAC100_TXDES0_TXDMA_OWN
, false,
490 FTGMAC100_TX_TIMEOUT_MS
, true);
494 debug("%s(): packet sent\n", __func__
);
496 /* Move to next descriptor */
497 priv
->tx_index
= (priv
->tx_index
+ 1) % PKTBUFSTX
;
502 static int ftgmac100_write_hwaddr(struct udevice
*dev
)
504 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
505 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
507 return ftgmac100_set_mac(priv
, pdata
->enetaddr
);
510 static int ftgmac100_ofdata_to_platdata(struct udevice
*dev
)
512 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
513 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
514 const char *phy_mode
;
516 pdata
->iobase
= devfdt_get_addr(dev
);
517 pdata
->phy_interface
= -1;
518 phy_mode
= dev_read_string(dev
, "phy-mode");
520 pdata
->phy_interface
= phy_get_interface_by_name(phy_mode
);
521 if (pdata
->phy_interface
== -1) {
522 dev_err(dev
, "Invalid PHY interface '%s'\n", phy_mode
);
526 pdata
->max_speed
= dev_read_u32_default(dev
, "max-speed", 0);
528 if (dev_get_driver_data(dev
) == FTGMAC100_MODEL_ASPEED
) {
529 priv
->rxdes0_edorr_mask
= BIT(30);
530 priv
->txdes0_edotr_mask
= BIT(30);
532 priv
->rxdes0_edorr_mask
= BIT(15);
533 priv
->txdes0_edotr_mask
= BIT(15);
536 return clk_get_bulk(dev
, &priv
->clks
);
539 static int ftgmac100_probe(struct udevice
*dev
)
541 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
542 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
545 priv
->iobase
= (struct ftgmac100
*)pdata
->iobase
;
546 priv
->phy_mode
= pdata
->phy_interface
;
547 priv
->max_speed
= pdata
->max_speed
;
550 ret
= clk_enable_bulk(&priv
->clks
);
554 ret
= ftgmac100_mdio_init(dev
);
556 dev_err(dev
, "Failed to initialize mdiobus: %d\n", ret
);
560 ret
= ftgmac100_phy_init(dev
);
562 dev_err(dev
, "Failed to initialize PHY: %d\n", ret
);
568 clk_release_bulk(&priv
->clks
);
573 static int ftgmac100_remove(struct udevice
*dev
)
575 struct ftgmac100_data
*priv
= dev_get_priv(dev
);
578 mdio_unregister(priv
->bus
);
579 mdio_free(priv
->bus
);
580 clk_release_bulk(&priv
->clks
);
585 static const struct eth_ops ftgmac100_ops
= {
586 .start
= ftgmac100_start
,
587 .send
= ftgmac100_send
,
588 .recv
= ftgmac100_recv
,
589 .stop
= ftgmac100_stop
,
590 .free_pkt
= ftgmac100_free_pkt
,
591 .write_hwaddr
= ftgmac100_write_hwaddr
,
594 static const struct udevice_id ftgmac100_ids
[] = {
595 { .compatible
= "faraday,ftgmac100", .data
= FTGMAC100_MODEL_FARADAY
},
596 { .compatible
= "aspeed,ast2500-mac", .data
= FTGMAC100_MODEL_ASPEED
},
600 U_BOOT_DRIVER(ftgmac100
) = {
603 .of_match
= ftgmac100_ids
,
604 .ofdata_to_platdata
= ftgmac100_ofdata_to_platdata
,
605 .probe
= ftgmac100_probe
,
606 .remove
= ftgmac100_remove
,
607 .ops
= &ftgmac100_ops
,
608 .priv_auto_alloc_size
= sizeof(struct ftgmac100_data
),
609 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),
610 .flags
= DM_FLAG_ALLOC_PRIV_DMA
,