The SiFive MACB ethernet has a custom TX_CLK_SEL register to select different TX clock for 1000mbps vs 10/100mbps.
This patch adds SiFive MACB compatible string and extends the MACB ethernet driver to change TX clock using TX_CLK_SEL register for SiFive MACB. Signed-off-by: Anup Patel <anup.pa...@wdc.com> --- drivers/net/macb.c | 53 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c072f99d8f..6a29ee3064 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -83,6 +83,9 @@ struct macb_dma_desc { struct macb_device { void *regs; + void *regs_sifive_gemgxl; + + bool skip_dma_config; unsigned int dma_burst_length; unsigned int rx_tail; @@ -122,7 +125,9 @@ struct macb_device { }; struct macb_config { + bool skip_dma_config; unsigned int dma_burst_length; + bool has_sifive_gemgxl; }; #ifndef CONFIG_DM_ETH @@ -486,18 +491,11 @@ static int macb_phy_find(struct macb_device *macb, const char *name) int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed) { #ifdef CONFIG_CLK + struct macb_device *macb = dev_get_priv(dev); struct clk tx_clk; ulong rate; int ret; - /* - * "tx_clk" is an optional clock source for MACB. - * Ignore if it does not exist in DT. - */ - ret = clk_get_by_name(dev, "tx_clk", &tx_clk); - if (ret) - return 0; - switch (speed) { case _10BASET: rate = 2500000; /* 2.5 MHz */ @@ -513,6 +511,26 @@ int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed) return 0; } + if (macb->regs_sifive_gemgxl) { + /* + * SiFive GEMGXL TX clock operation mode: + * + * 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic + * and output clock on GMII output signal GTX_CLK + * 1 = MII mode. Use MII input signal TX_CLK in TX logic + */ + writel(rate != 125000000, macb->regs_sifive_gemgxl); + return 0; + } + + /* + * "tx_clk" is an optional clock source for MACB. + * Ignore if it does not exist in DT. + */ + ret = clk_get_by_name(dev, "tx_clk", &tx_clk); + if (ret) + return 0; + if (tx_clk.dev) { ret = clk_set_rate(&tx_clk, rate); if (ret) @@ -701,6 +719,9 @@ static void gmac_configure_dma(struct macb_device *macb) u32 buffer_size; u32 dmacfg; + if (macb->skip_dma_config) + return; + buffer_size = 128 / RX_BUFFER_MULTIPLE; dmacfg = gem_readl(macb, DMACFG) & ~GEM_BF(RXBS, -1L); dmacfg |= GEM_BF(RXBS, buffer_size); @@ -1178,6 +1199,7 @@ static int macb_eth_probe(struct udevice *dev) struct macb_device *macb = dev_get_priv(dev); const char *phy_mode; __maybe_unused int ret; + fdt_addr_t addr; phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", NULL); @@ -1194,6 +1216,7 @@ static int macb_eth_probe(struct udevice *dev) if (!macb_config) macb_config = &default_gem_config; + macb->skip_dma_config = macb_config->skip_dma_config; macb->dma_burst_length = macb_config->dma_burst_length; #ifdef CONFIG_CLK ret = macb_enable_clk(dev); @@ -1201,6 +1224,13 @@ static int macb_eth_probe(struct udevice *dev) return ret; #endif + if (macb_config->has_sifive_gemgxl) { + addr = dev_read_addr_index(dev, 1); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + macb->regs_sifive_gemgxl = (void __iomem *)addr; + } + _macb_eth_initialize(macb); #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) @@ -1259,6 +1289,12 @@ static const struct macb_config sama5d4_config = { .dma_burst_length = 4, }; +static const struct macb_config sifive_config = { + .skip_dma_config = true, + .dma_burst_length = 0, + .has_sifive_gemgxl = true, +}; + static const struct udevice_id macb_eth_ids[] = { { .compatible = "cdns,macb" }, { .compatible = "cdns,at91sam9260-macb" }, @@ -1266,6 +1302,7 @@ static const struct udevice_id macb_eth_ids[] = { { .compatible = "atmel,sama5d3-gem" }, { .compatible = "atmel,sama5d4-gem", .data = (ulong)&sama5d4_config }, { .compatible = "cdns,zynq-gem" }, + { .compatible = "sifive,fu540-macb", .data = (ulong)&sifive_config }, { } }; -- 2.17.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot