ARMv7: at91: Enable ICache and DCache for at91 armv7 cpu
Subsystems (3)
cover 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(-)
Signature · 1 line
1.7.9.5
PATCH 1/2 net: macb: enable dcache in macb
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.
--- drivers/net/macb.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
drivers/net/macb.c +51 -0
@@ -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;
Signature · 1 line
1.7.9.5
PATCH 2/2 ARMv7: at91: enable ICache and DCache.
In reply to Josh WuAs SAMA5D3 is a at91 ARMv7 cpu, so we should enable LCD DCache flush for SAMA5D3X-EK.
--- arch/arm/cpu/armv7/at91/cpu.c | 6 ++++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-)
arch/arm/cpu/armv7/at91/cpu.c +6 -0
@@ -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 )
board/atmel/sama5d3xek/sama5d3xek.c +5 -1
@@ -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 ; }
Signature · 1 line
1.7.9.5
PATCH 2/2 ARMv7: at91: enable ICache and DCache.
Hi Josh,
Quoted 14 lines · Josh Wu
As SAMA5D3 is a at91 ARMv7 cpu, so we should enable LCD DCache flush for SAMA5D3X-EK.
Signed-off-by Josh Wu <[email protected]>--- arch/arm/cpu/armv7/at91/cpu.c | 6 ++++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-)arch/arm/cpu/armv7/at91/cpu.c +0
-0
arch/arm/cpu/armv7/at91/cpu.c int print_cpuinfo(void) · line 66
Quoted 6 lines
arch/arm/cpu/armv7/at91/cpu.c +3
-0@@ -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.
Quoted 11 lines
arch/arm/cpu/armv7/at91/cpu.c +3
-0+#ifndef CONFIG_SYS_DCACHE_OFF +dcache_enable (); +#endif }unsigned int get_chip_id (void )board/atmel/sama5d3xek/sama5d3xek.c +0
-0
board/atmel/sama5d3xek/sama5d3xek.c int board_init(void) · line 207
Quoted 9 lines
board/atmel/sama5d3xek/sama5d3xek.c +4
-1@@ -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.
board/atmel/sama5d3xek/sama5d3xek.c int board_init(void) · line 211
Quoted 5 lines
board/atmel/sama5d3xek/sama5d3xek.c +1
-0+ }#endif return 0 ; }
Best Regards,
Bo Shen
PATCH 2/2 ARMv7: at91: enable ICache and DCache.
Hi, Bo
Thanks for the review ;-)
Quoted 19 lines · Bo Shen
Hi Josh,
Quoted 16 lines · Josh Wu
As SAMA5D3 is a at91 ARMv7 cpu, so we should enable LCD DCache flush for SAMA5D3X-EK.
Signed-off-by Josh Wu <[email protected]>--- arch/arm/cpu/armv7/at91/cpu.c | 6 ++++++ board/atmel/sama5d3xek/sama5d3xek.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-)arch/arm/cpu/armv7/at91/cpu.c +0
-0@@ -61,6 +61,12 @@ int print_cpuinfo(void)
Quoted 7 lines
arch/arm/cpu/armv7/at91/cpu.c int print_cpuinfo(void) · line 66
Quoted 5 lines
arch/arm/cpu/armv7/at91/cpu.c +3
-0void 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.
Quoted 4 lines
arch/arm/cpu/armv7/at91/cpu.c int print_cpuinfo(void) · line 69
Quoted 4 lines
arch/arm/cpu/armv7/at91/cpu.c +3
-0+#ifndef CONFIG_SYS_DCACHE_OFF +dcache_enable (); +#endif
This will be removed too.
Quoted 13 lines
Quoted 13 lines
arch/arm/cpu/armv7/at91/cpu.c +0
-0}unsigned int get_chip_id (void )board/atmel/sama5d3xek/sama5d3xek.c +0
-1@@ -200,8 +200,12 @@ int board_init(void)at91_gmac_hw_init ();#endif #ifdef CONFIG_LCD -if (has_lcdc ())
Quoted 8 lines
board/atmel/sama5d3xek/sama5d3xek.c int board_init(void) · line 207
Quoted 5 lines
board/atmel/sama5d3xek/sama5d3xek.c +4
-0+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
Quoted 10 lines
board/atmel/sama5d3xek/sama5d3xek.c int board_init(void) · line 211
Quoted 6 lines
board/atmel/sama5d3xek/sama5d3xek.c +1
-0+ }#endif return 0 ; }Best Regards,
Bo Shen
PATCH 2/2 ARMv7: at91: enable ICache and DCache.
Hi Josh,
Quoted 19 lines · Josh Wu
Quoted 10 lines
Quoted 10 lines
board/atmel/sama5d3xek/sama5d3xek.c +0
-1@@ -200,8 +200,12 @@ int board_init(void)at91_gmac_hw_init ();#endif #ifdef CONFIG_LCD -if (has_lcdc ())Quoted 8 lines
board/atmel/sama5d3xek/sama5d3xek.c int board_init(void) · line 207
Quoted 5 lines
board/atmel/sama5d3xek/sama5d3xek.c +4
-0+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.
Quoted 8 lines
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 implementdcache_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 calllcd_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?
Quoted 2 lines
Best Regards,
Josh Wu
Best Regards,
Bo Shen