[U-Boot] [PATCH 0/2] ARMv7: at91: Enable ICache and DCache for at91 armv7 cpu

First, before we enable DCache. We need add dcache support for macb driver. Then enable ICache/DCache.
Tested on SAMA5D3x-EK board and AT91SAM9M10G45EK.
Josh Wu (2): net: macb: enable dcache in macb ARMv7: at91: enable ICache and DCache.
arch/arm/cpu/armv7/at91/cpu.c | 6 +++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 ++++- drivers/net/macb.c | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-)

Add to code to flush the dcache after we writing in DMA buffer. Also we need invalidate the dcache before we check the status in the DMA buffer.
Tested in SAMA5D3x-EK with gmac0. Tftp download speed shows in below: Disable DCache: 1.1 MiB/s Enable DCache: 1.6 MiB/s Increase speed with about 40%.
The code should have no impact with the boards which are not enable_dcache(). Tested in AT91SAM9M10G45EK.
Signed-off-by: Josh Wu josh.wu@atmel.com --- drivers/net/macb.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 781a272..b18f07b 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -194,6 +194,39 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) } #endif
+#define IS_RX 1 +#define IS_TX 0 +static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool is_rx) +{ + if (is_rx) + invalidate_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + + CONFIG_SYS_MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc)); + else + invalidate_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + + CONFIG_SYS_MACB_TX_RING_SIZE * sizeof(struct macb_dma_desc)); +} + +static inline void macb_flush_ring_desc(struct macb_device *macb, bool is_rx) +{ + if (is_rx) + flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + + CONFIG_SYS_MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc)); + else + flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + + CONFIG_SYS_MACB_TX_RING_SIZE * sizeof(struct macb_dma_desc)); +} + +static inline void macb_flush_rx_buffer(struct macb_device *macb) +{ + flush_dcache_range(macb->rx_buffer_dma, + macb->rx_buffer_dma + CONFIG_SYS_MACB_RX_BUFFER_SIZE); +} + +static inline void macb_invalidate_rx_buffer(struct macb_device *macb) +{ + invalidate_dcache_range(macb->rx_buffer_dma, + macb->rx_buffer_dma + CONFIG_SYS_MACB_RX_BUFFER_SIZE); +}
#if defined(CONFIG_CMD_NET)
@@ -217,6 +250,9 @@ static int macb_send(struct eth_device *netdev, void *packet, int length) macb->tx_ring[tx_head].ctrl = ctrl; macb->tx_ring[tx_head].addr = paddr; barrier(); + macb_flush_ring_desc(macb, IS_TX); + /* Do we need check paddr and length is dcache line aligned? */ + flush_dcache_range(paddr, paddr + length); macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
/* @@ -225,6 +261,7 @@ static int macb_send(struct eth_device *netdev, void *packet, int length) */ for (i = 0; i <= CONFIG_SYS_MACB_TX_TIMEOUT; i++) { barrier(); + macb_invalidate_ring_desc(macb, IS_TX); ctrl = macb->tx_ring[tx_head].ctrl; if (ctrl & TXBUF_USED) break; @@ -253,6 +290,8 @@ static void reclaim_rx_buffers(struct macb_device *macb, unsigned int i;
i = macb->rx_tail; + + macb_invalidate_ring_desc(macb, IS_RX); while (i > new_tail) { macb->rx_ring[i].addr &= ~RXADDR_USED; i++; @@ -266,6 +305,7 @@ static void reclaim_rx_buffers(struct macb_device *macb, }
barrier(); + macb_flush_ring_desc(macb, IS_RX); macb->rx_tail = new_tail; }
@@ -279,6 +319,8 @@ static int macb_recv(struct eth_device *netdev) u32 status;
for (;;) { + macb_invalidate_ring_desc(macb, IS_RX); + if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) return -1;
@@ -292,6 +334,8 @@ static int macb_recv(struct eth_device *netdev) if (status & RXBUF_FRAME_END) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK; + + macb_invalidate_rx_buffer(macb); if (wrapped) { unsigned int headlen, taillen;
@@ -506,6 +550,9 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) macb->rx_ring[i].ctrl = 0; paddr += 128; } + macb_flush_ring_desc(macb, IS_RX); + macb_flush_rx_buffer(macb); + for (i = 0; i < CONFIG_SYS_MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) @@ -513,6 +560,8 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) else macb->tx_ring[i].ctrl = TXBUF_USED; } + macb_flush_ring_desc(macb, IS_TX); + macb->rx_tail = macb->tx_head = macb->tx_tail = 0;
macb_writel(macb, RBQP, macb->rx_ring_dma); @@ -663,6 +712,8 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) * sizeof(struct macb_dma_desc), &macb->tx_ring_dma);
+ /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ + macb->regs = regs; macb->phy_addr = phy_addr;

As SAMA5D3 is a at91 ARMv7 cpu, so we should enable LCD DCache flush for SAMA5D3X-EK.
Signed-off-by: Josh Wu josh.wu@atmel.com --- arch/arm/cpu/armv7/at91/cpu.c | 6 ++++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/cpu/armv7/at91/cpu.c index 2fbf60d..6f2164f 100644 --- a/arch/arm/cpu/armv7/at91/cpu.c +++ b/arch/arm/cpu/armv7/at91/cpu.c @@ -61,6 +61,12 @@ int print_cpuinfo(void)
void enable_caches(void) { +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif }
unsigned int get_chip_id(void) diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c index c835c12..1fc91d9 100644 --- a/board/atmel/sama5d3xek/sama5d3xek.c +++ b/board/atmel/sama5d3xek/sama5d3xek.c @@ -200,8 +200,12 @@ int board_init(void) at91_gmac_hw_init(); #endif #ifdef CONFIG_LCD - if (has_lcdc()) + if (has_lcdc()) { sama5d3xek_lcd_hw_init(); + + /* Enable flushing as we enabled dcache */ + lcd_set_flush_dcache(1); + } #endif return 0; }

Hi Josh,
On 05/16/2014 04:15 PM, Josh Wu wrote:
As SAMA5D3 is a at91 ARMv7 cpu, so we should enable LCD DCache flush for SAMA5D3X-EK.
Signed-off-by: Josh Wu josh.wu@atmel.com
arch/arm/cpu/armv7/at91/cpu.c | 6 ++++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/cpu/armv7/at91/cpu.c index 2fbf60d..6f2164f 100644 --- a/arch/arm/cpu/armv7/at91/cpu.c +++ b/arch/arm/cpu/armv7/at91/cpu.c @@ -61,6 +61,12 @@ int print_cpuinfo(void)
void enable_caches(void) { +#ifndef CONFIG_SYS_ICACHE_OFF
- icache_enable();
+#endif
No need this one. Ifdef CONFIG_SYS_ICACHE_OFF, it will be disabled.
+#ifndef CONFIG_SYS_DCACHE_OFF
- dcache_enable();
+#endif }
unsigned int get_chip_id(void) diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c index c835c12..1fc91d9 100644 --- a/board/atmel/sama5d3xek/sama5d3xek.c +++ b/board/atmel/sama5d3xek/sama5d3xek.c @@ -200,8 +200,12 @@ int board_init(void) at91_gmac_hw_init(); #endif #ifdef CONFIG_LCD
- if (has_lcdc())
- if (has_lcdc()) { sama5d3xek_lcd_hw_init();
/* Enable flushing as we enabled dcache */
lcd_set_flush_dcache(1);
Why not implement in driver, or else, each SoC enable dcache will need add this.
- } #endif return 0; }
Best Regards, Bo Shen

Hi, Bo
Thanks for the review ;-)
On 5/16/2014 4:29 PM, Bo Shen wrote:
Hi Josh,
On 05/16/2014 04:15 PM, Josh Wu wrote:
As SAMA5D3 is a at91 ARMv7 cpu, so we should enable LCD DCache flush for SAMA5D3X-EK.
Signed-off-by: Josh Wu josh.wu@atmel.com
arch/arm/cpu/armv7/at91/cpu.c | 6 ++++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/cpu/armv7/at91/cpu.c index 2fbf60d..6f2164f 100644 --- a/arch/arm/cpu/armv7/at91/cpu.c +++ b/arch/arm/cpu/armv7/at91/cpu.c @@ -61,6 +61,12 @@ int print_cpuinfo(void)
void enable_caches(void) { +#ifndef CONFIG_SYS_ICACHE_OFF
- icache_enable();
+#endif
No need this one. Ifdef CONFIG_SYS_ICACHE_OFF, it will be disabled.
ok, good. I will remove this #if.
+#ifndef CONFIG_SYS_DCACHE_OFF
- dcache_enable();
+#endif
This will be removed too.
}
unsigned int get_chip_id(void) diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c index c835c12..1fc91d9 100644 --- a/board/atmel/sama5d3xek/sama5d3xek.c +++ b/board/atmel/sama5d3xek/sama5d3xek.c @@ -200,8 +200,12 @@ int board_init(void) at91_gmac_hw_init(); #endif #ifdef CONFIG_LCD
- if (has_lcdc())
- if (has_lcdc()) { sama5d3xek_lcd_hw_init();
/* Enable flushing as we enabled dcache */
lcd_set_flush_dcache(1);
Why not implement in driver, or else, each SoC enable dcache will need add this.
hmm, the thing is some at91 board, for example at91sam9x5ek board, not defined CONFIG_SYS_DCACHE_OFF, that means DCache is enabled. But actually it doesn't implement dcache_enable(). In above situation, if we implement it in driver, I can't tell whether dcache is really enabled or not. For this reason, I manually call lcd_set_flush_dcache(1) in the board file. In the future if all boards (use hlcd driver) enabled dcache I will move this function to hlcd driver.
Best Regards, Josh Wu
- } #endif return 0; }
Best Regards, Bo Shen

Hi Josh,
On 05/16/2014 05:17 PM, Josh Wu wrote:
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c index c835c12..1fc91d9 100644 --- a/board/atmel/sama5d3xek/sama5d3xek.c +++ b/board/atmel/sama5d3xek/sama5d3xek.c @@ -200,8 +200,12 @@ int board_init(void) at91_gmac_hw_init(); #endif #ifdef CONFIG_LCD
- if (has_lcdc())
- if (has_lcdc()) { sama5d3xek_lcd_hw_init();
/* Enable flushing as we enabled dcache */
lcd_set_flush_dcache(1);
Why not implement in driver, or else, each SoC enable dcache will need add this.
hmm, the thing is some at91 board, for example at91sam9x5ek board, not defined CONFIG_SYS_DCACHE_OFF, that means DCache is enabled. But actually it doesn't implement dcache_enable(). In above situation, if we implement it in driver, I can't tell whether dcache is really enabled or not. For this reason, I manually call lcd_set_flush_dcache(1) in the board file. In the future if all boards (use hlcd driver) enabled dcache I will move this function to hlcd driver.
I don't see any issue to implement this in driver, may be I am wrong? Can you figure out what issue you met?
Btw, if there is really have issues, can make this condition with CONFIG_SYS_DCACHE_OFF?
Best Regards, Josh Wu
Best Regards, Bo Shen
participants (2)
-
Bo Shen
-
Josh Wu