[U-Boot] [PATCH v2 2/6] net: macb: add support for faster clk rates

add support for clock rates higher than 2.4Mhz
Signed-off-by: Ramon Fried rfried.dev@gmail.com Reviewed-by: Anup Patel anup.patel@wdc.com Tested-by: Anup Patel anup.patel@wdc.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- v2: nothing. drivers/net/macb.c | 6 +++++- drivers/net/macb.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 0032d4e000..0fed43bbe2 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -903,8 +903,12 @@ static u32 gem_mdc_clk_div(int id, struct macb_device *macb) config = GEM_BF(CLK, GEM_CLK_DIV48); else if (macb_hz < 160000000) config = GEM_BF(CLK, GEM_CLK_DIV64); - else + else if (macb_hz < 240000000) config = GEM_BF(CLK, GEM_CLK_DIV96); + else if (macb_hz < 320000000) + config = GEM_BF(CLK, GEM_CLK_DIV128); + else + config = GEM_BF(CLK, GEM_CLK_DIV224);
return config; } diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 8966c793a7..9b16383eba 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -613,6 +613,8 @@ #define GEM_CLK_DIV48 3 #define GEM_CLK_DIV64 4 #define GEM_CLK_DIV96 5 +#define GEM_CLK_DIV128 6 +#define GEM_CLK_DIV224 7
/* Constants for MAN register */ #define MACB_MAN_SOF 1

macb.h provides macros for reading/setting bitfields, in macb registers and descriptors. use that instead of redefining them in the source file.
Signed-off-by: Ramon Fried rfried.dev@gmail.com Reviewed-by: Anup Patel anup.patel@wdc.com Tested-by: Anup Patel anup.patel@wdc.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- v2: nothing. drivers/net/macb.c | 48 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 33 deletions(-)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 0fed43bbe2..a968a4bd06 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -77,27 +77,8 @@ struct macb_dma_desc { #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) #define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1))
-#define RXADDR_USED 0x00000001 -#define RXADDR_WRAP 0x00000002 - #define RXBUF_FRMLEN_MASK 0x00000fff -#define RXBUF_FRAME_START 0x00004000 -#define RXBUF_FRAME_END 0x00008000 -#define RXBUF_TYPEID_MATCH 0x00400000 -#define RXBUF_ADDR4_MATCH 0x00800000 -#define RXBUF_ADDR3_MATCH 0x01000000 -#define RXBUF_ADDR2_MATCH 0x02000000 -#define RXBUF_ADDR1_MATCH 0x04000000 -#define RXBUF_BROADCAST 0x80000000 - #define TXBUF_FRMLEN_MASK 0x000007ff -#define TXBUF_FRAME_END 0x00008000 -#define TXBUF_NOCRC 0x00010000 -#define TXBUF_EXHAUSTED 0x08000000 -#define TXBUF_UNDERRUN 0x10000000 -#define TXBUF_MAXRETRY 0x20000000 -#define TXBUF_WRAP 0x40000000 -#define TXBUF_USED 0x80000000
struct macb_device { void *regs; @@ -316,9 +297,9 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet, paddr = dma_map_single(packet, length, DMA_TO_DEVICE);
ctrl = length & TXBUF_FRMLEN_MASK; - ctrl |= TXBUF_FRAME_END; + ctrl |= MACB_BIT(TX_LAST); if (tx_head == (MACB_TX_RING_SIZE - 1)) { - ctrl |= TXBUF_WRAP; + ctrl |= MACB_BIT(TX_WRAP); macb->tx_head = 0; } else { macb->tx_head++; @@ -340,7 +321,7 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet, barrier(); macb_invalidate_ring_desc(macb, TX); ctrl = macb->tx_ring[tx_head].ctrl; - if (ctrl & TXBUF_USED) + if (ctrl & MACB_BIT(TX_USED)) break; udelay(1); } @@ -348,9 +329,9 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet, dma_unmap_single(packet, length, paddr);
if (i <= MACB_TX_TIMEOUT) { - if (ctrl & TXBUF_UNDERRUN) + if (ctrl & MACB_BIT(TX_UNDERRUN)) printf("%s: TX underrun\n", name); - if (ctrl & TXBUF_EXHAUSTED) + if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED)) printf("%s: TX buffers exhausted in mid frame\n", name); } else { printf("%s: TX timeout\n", name); @@ -369,14 +350,14 @@ static void reclaim_rx_buffers(struct macb_device *macb,
macb_invalidate_ring_desc(macb, RX); while (i > new_tail) { - macb->rx_ring[i].addr &= ~RXADDR_USED; + macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED); i++; if (i > MACB_RX_RING_SIZE) i = 0; }
while (i < new_tail) { - macb->rx_ring[i].addr &= ~RXADDR_USED; + macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED); i++; }
@@ -396,17 +377,17 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp) for (;;) { macb_invalidate_ring_desc(macb, RX);
- if (!(macb->rx_ring[next_rx_tail].addr & RXADDR_USED)) + if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED))) return -EAGAIN;
status = macb->rx_ring[next_rx_tail].ctrl; - if (status & RXBUF_FRAME_START) { + if (status & MACB_BIT(RX_SOF)) { if (next_rx_tail != macb->rx_tail) reclaim_rx_buffers(macb, next_rx_tail); macb->wrapped = false; }
- if (status & RXBUF_FRAME_END) { + if (status & MACB_BIT(RX_EOF)) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK;
@@ -699,7 +680,7 @@ static int gmac_init_multi_queues(struct macb_device *macb) if (queue_mask & (1 << i)) num_queues++;
- macb->dummy_desc->ctrl = TXBUF_USED; + macb->dummy_desc->ctrl = MACB_BIT(TX_USED); macb->dummy_desc->addr = 0; flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN)); @@ -732,7 +713,7 @@ static int _macb_init(struct macb_device *macb, const char *name) paddr = macb->rx_buffer_dma; for (i = 0; i < MACB_RX_RING_SIZE; i++) { if (i == (MACB_RX_RING_SIZE - 1)) - paddr |= RXADDR_WRAP; + paddr |= MACB_BIT(RX_WRAP); macb->rx_ring[i].addr = paddr; macb->rx_ring[i].ctrl = 0; paddr += 128; @@ -743,9 +724,10 @@ static int _macb_init(struct macb_device *macb, const char *name) for (i = 0; i < MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; if (i == (MACB_TX_RING_SIZE - 1)) - macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; + macb->tx_ring[i].ctrl = MACB_BIT(TX_USED) | + MACB_BIT(TX_WRAP); else - macb->tx_ring[i].ctrl = TXBUF_USED; + macb->tx_ring[i].ctrl = MACB_BIT(TX_USED); } macb_flush_ring_desc(macb, TX);

Hi Ramon,
https://patchwork.ozlabs.org/patch/1132905/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe

This patch adds support for the sgmii phy interface, available only to DM users, dictated by current driver design.
Signed-off-by: Ramon Fried rfried.dev@gmail.com Reviewed-by: Anup Patel anup.patel@wdc.com Tested-by: Anup Patel anup.patel@wdc.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- v2: nothing. drivers/net/macb.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index a968a4bd06..cf76270ad8 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -759,6 +759,13 @@ static int _macb_init(struct macb_device *macb, const char *name) gem_writel(macb, USRIO, GEM_BIT(RGMII)); else gem_writel(macb, USRIO, 0); + + if (macb->phy_interface == PHY_INTERFACE_MODE_SGMII) { + unsigned int ncfgr = macb_readl(macb, NCFGR); + + ncfgr |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL); + macb_writel(macb, NCFGR, ncfgr); + } #else #if defined(CONFIG_RGMII) || defined(CONFIG_RMII) gem_writel(macb, USRIO, GEM_BIT(RGMII));

Hi Ramon,
https://patchwork.ozlabs.org/patch/1132906/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe

GEM support higher DMA burst writes/reads than the default (4). add configuration structure with dma burst length so it could be applied later to DMA configuration.
Signed-off-by: Ramon Fried rfried.dev@gmail.com Reviewed-by: Anup Patel anup.patel@wdc.com Tested-by: Anup Patel anup.patel@wdc.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- v2: nothing. drivers/net/macb.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index cf76270ad8..dc6aa6deda 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -82,6 +82,7 @@ struct macb_dma_desc {
struct macb_device { void *regs; + unsigned int dma_burst_length;
unsigned int rx_tail; unsigned int tx_head; @@ -118,6 +119,11 @@ struct macb_device { phy_interface_t phy_interface; #endif }; + +struct macb_config { + unsigned int dma_burst_length; +}; + #ifndef CONFIG_DM_ETH #define to_macb(_nd) container_of(_nd, struct macb_device, netdev) #endif @@ -1135,8 +1141,13 @@ static int macb_enable_clk(struct udevice *dev) } #endif
+static const struct macb_config default_gem_config = { + .dma_burst_length = 16, +}; + static int macb_eth_probe(struct udevice *dev) { + const struct macb_config *macb_config; struct eth_pdata *pdata = dev_get_platdata(dev); struct macb_device *macb = dev_get_priv(dev); const char *phy_mode; @@ -1153,6 +1164,11 @@ static int macb_eth_probe(struct udevice *dev)
macb->regs = (void *)pdata->iobase;
+ macb_config = (struct macb_config *)dev_get_driver_data(dev); + if (!macb_config) + macb_config = &default_gem_config; + + macb->dma_burst_length = macb_config->dma_burst_length; #ifdef CONFIG_CLK ret = macb_enable_clk(dev); if (ret) @@ -1213,12 +1229,16 @@ static int macb_eth_ofdata_to_platdata(struct udevice *dev) return macb_late_eth_ofdata_to_platdata(dev); }
+static const struct macb_config sama5d4_config = { + .dma_burst_length = 4, +}; + static const struct udevice_id macb_eth_ids[] = { { .compatible = "cdns,macb" }, { .compatible = "cdns,at91sam9260-macb" }, { .compatible = "atmel,sama5d2-gem" }, { .compatible = "atmel,sama5d3-gem" }, - { .compatible = "atmel,sama5d4-gem" }, + { .compatible = "atmel,sama5d4-gem", .data = (ulong)&sama5d4_config }, { .compatible = "cdns,zynq-gem" }, { } };

Hi Ramon,
https://patchwork.ozlabs.org/patch/1132904/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe

DMA configuration was heavily dependent on the HW defaults, add function to properly set the required fields, including the new dma_burst_length.
Signed-off-by: Ramon Fried rfried.dev@gmail.com Reviewed-by: Anup Patel anup.patel@wdc.com Tested-by: Anup Patel anup.patel@wdc.com Acked-by: Joe Hershberger joe.hershberger@ni.com --- v2: nothing. drivers/net/macb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index dc6aa6deda..035109dc43 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define MACB_RX_BUFFER_SIZE 4096 #define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128) +#define RX_BUFFER_MULTIPLE 64 #define MACB_TX_RING_SIZE 16 #define MACB_TX_TIMEOUT 1000 #define MACB_AUTONEG_TIMEOUT 5000000 @@ -697,6 +698,31 @@ static int gmac_init_multi_queues(struct macb_device *macb) return 0; }
+static void gmac_configure_dma(struct macb_device *macb) +{ + u32 buffer_size; + u32 dmacfg; + + buffer_size = 128 / RX_BUFFER_MULTIPLE; + dmacfg = gem_readl(macb, DMACFG) & ~GEM_BF(RXBS, -1L); + dmacfg |= GEM_BF(RXBS, buffer_size); + + if (macb->dma_burst_length) + dmacfg = GEM_BFINS(FBLDO, macb->dma_burst_length, dmacfg); + + dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L); + dmacfg &= ~GEM_BIT(ENDIA_PKT); + +#ifdef CONFIG_SYS_LITTLE_ENDIAN + dmacfg &= ~GEM_BIT(ENDIA_DESC); +#else + dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */ +#endif + + dmacfg &= ~GEM_BIT(ADDR64); + gem_writel(macb, DMACFG, dmacfg); +} + #ifdef CONFIG_DM_ETH static int _macb_init(struct udevice *dev, const char *name) #else @@ -750,6 +776,8 @@ static int _macb_init(struct macb_device *macb, const char *name) macb_writel(macb, TBQP, macb->tx_ring_dma);
if (macb_is_gem(macb)) { + /* Initialize DMA properties */ + gmac_configure_dma(macb); /* Check the multi queue and initialize the queue for tx */ gmac_init_multi_queues(macb);

Hi Ramon,
https://patchwork.ozlabs.org/patch/1132907/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe

Hi Ramon,
https://patchwork.ozlabs.org/patch/1132908/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe
participants (2)
-
Joe Hershberger
-
Ramon Fried