Skip to contentSkip to conversation

nios2: convert dma mapping to use dm cpu data

PATCH New Thomas Chou 3 participants 28 messages Oct 5, 2015 – Oct 19, 2015 NIOS2 architecture

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 nios2: convert dma mapping to use dm cpu data

Convert dma mapping to use dm cpu data.

---
 arch/nios2/include/asm/dma-mapping.h | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)
arch/nios2/include/asm/dma-mapping.h +11 -10
index 1350e3b..403166b 100644
@@ -1,23 +1,24 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is mapped
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is mapped
  * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- *   0x80000000 for nommu, 0xe0000000 for mmu
  */
 
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned long addr =
+		(unsigned long)malloc(len + gd->arch.dcache_line_size);
+
 	if (!addr)
 		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	flush_dcache(addr, len + gd->arch.dcache_line_size);
+	*handle = (addr + gd->arch.dcache_line_size - 1) &
+		~(gd->arch.dcache_line_size - 1) & ~gd->arch.io_region_base;
+
+	return (void *)(*handle | gd->arch.io_region_base);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */
Signature · 1 line
2.1.4
#1 lore raw

PATCH v2 1/1 nios2: convert dma_alloc_coherent to use memalign

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.

 arch/nios2/include/asm/dma-mapping.h | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)
arch/nios2/include/asm/dma-mapping.h +8 -13
index 1350e3b..e3a338d 100644
@@ -1,23 +1,18 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is mapped
+#include <asm/io.h>
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is mapped
  * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- *   0x80000000 for nommu, 0xe0000000 for mmu
  */
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
+	flush_dcache_range(*handle, *handle + len);
+
+	return ioremap(*handle, len);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */
Signature · 1 line
2.1.4
#2 lore raw

PATCH v2 1/1 nios2: convert dma_alloc_coherent to use memalign

Quoted 33 lines · Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.

 arch/nios2/include/asm/dma-mapping.h | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)
(quoted diff) +0 -0

b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..e3a338d 100644

arch/nios2/include/asm/dma-mapping.h +0 -1
@@ -1,23 +1,18 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is

mapped +#include <asm/io.h>

arch/nios2/include/asm/dma-mapping.h +3 -0
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is

mapped * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- * 0x80000000 for nommu, 0xe0000000 for mmu
*/

arch/nios2/include/asm/dma-mapping.h +0 -3
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)

arch/nios2/include/asm/dma-mapping.h line 15

Quoted 10 lines
arch/nios2/include/asm/dma-mapping.h +4 -6
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
+	flush_dcache_range(*handle, *handle + len);
+
+	return ioremap(*handle, len);

I'd suggest that you do this:

void *reg;
unsigned long *h = memalign(...);
flush_dcache_range();

reg = ioremap();
if (!reg)
fail here

*handle = h; // modify handle after we know ioremap succeeded.

return reg;

Quoted 3 lines

}

#endif /* __ASM_NIOS2_DMA_MAPPING_H */

Best regards,
Marek Vasut

#3 lore raw

PATCH v2 1/1 nios2: convert dma_alloc_coherent to use memalign

Hi Marek,

Quoted 6 lines · Marek Vasut

I'd suggest that you do this:

void *reg;
unsigned long *h = memalign(...);
flush_dcache_range();

Quoted 8 lines

reg = ioremap();
if (!reg)
fail here

*handle = h; // modify handle after we know ioremap succeeded.

return reg;

Thanks a lot for your suggestion. It is much clear with this.

Best regards,
Thomas

#4 lore raw

PATCH v2 1/1 nios2: convert dma_alloc_coherent to use memalign

Hi Marek,

I look into the code again. I think it is the memalign() that might fail due to out of memory. While the ioremap() of nios2 won't fail. So I added a check on memalign() return. Please see v3.

Best regards,
Thomas

#5 lore raw

PATCH v3 1/1 nios2: convert dma_alloc_coherent to use memalign

In reply to Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.

 arch/nios2/include/asm/dma-mapping.h | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)
arch/nios2/include/asm/dma-mapping.h +10 -13
index 1350e3b..0618dc2 100644
@@ -1,23 +1,20 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is mapped
+#include <asm/io.h>
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is mapped
  * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- *   0x80000000 for nommu, 0xe0000000 for mmu
  */
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
+	if (!*handle)
+		return NULL;
+	flush_dcache_range(*handle, *handle + len);
+
+	return ioremap(*handle, len);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */
Signature · 1 line
2.1.4
#6 lore raw

PATCH v3 1/1 nios2: convert dma_alloc_coherent to use memalign

Quoted 32 lines · Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.

 arch/nios2/include/asm/dma-mapping.h | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)
(quoted diff) +0 -0

b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..0618dc2 100644

arch/nios2/include/asm/dma-mapping.h +0 -1
@@ -1,23 +1,20 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is

mapped +#include <asm/io.h>

arch/nios2/include/asm/dma-mapping.h +3 -0
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is

mapped * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- * 0x80000000 for nommu, 0xe0000000 for mmu
*/

arch/nios2/include/asm/dma-mapping.h +0 -1
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)

arch/nios2/include/asm/dma-mapping.h line 12

Quoted 10 lines
arch/nios2/include/asm/dma-mapping.h +1 -8
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);

This still modifies the handle in both cases (failure and success). We really want to modify external variables in case of failure, no?

arch/nios2/include/asm/dma-mapping.h line 20

Quoted 8 lines
arch/nios2/include/asm/dma-mapping.h +5 -0
+	if (!*handle)
+		return NULL;
+	flush_dcache_range(*handle, *handle + len);
+
+	return ioremap(*handle, len);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */

Best regards,
Marek Vasut

#7 lore raw

PATCH v3 1/1 nios2: convert dma_alloc_coherent to use memalign

Hi Marek,

Quoted 4 lines · Marek Vasut

arch/nios2/include/asm/dma-mapping.h line 12

Quoted 1 line
arch/nios2/include/asm/dma-mapping.h +1 -0
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);

This still modifies the handle in both cases (failure and success). We really want to modify external variables in case of failure, no?

The *handle return a DMA address, and the function itself return a virtual address. Both of them should be set to NULL in case of failure. It might be wrong to keep DMA address looks alive but actually dead.

Best regards,
Thomas Chou

#8 lore raw

PATCH v3 1/1 nios2: convert dma_alloc_coherent to use memalign

Quoted 1 line · Thomas Chou

Hi Marek,

Hi!

Quoted 8 lines · Marek Vasut
Quoted 4 lines

arch/nios2/include/asm/dma-mapping.h line 12

Quoted 1 line
arch/nios2/include/asm/dma-mapping.h +1 -0
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);

This still modifies the handle in both cases (failure and success). We really want to modify external variables in case of failure, no?

The *handle return a DMA address, and the function itself return a virtual address. Both of them should be set to NULL in case of failure.

So you depend on this property of memalign(), ok, I see. Thanks for clarifying!

Quoted 1 line

It might be wrong to keep DMA address looks alive but actually dead.

I don't quite understand this sentence, can you please rephrase it ?

Best regards,
Marek Vasut

#9 lore raw

PATCH v3 1/1 nios2: convert dma_alloc_coherent to use memalign

Hi Marek,

Quoted 3 lines · Marek Vasut

It might be wrong to keep DMA address looks alive but actually dead.

I don't quite understand this sentence, can you please rephrase it ?

Sorry. I meant the *handle, which is the DMA address, should be invalidated to NULL when the allocation failed.

Best regards,
Thomas

#10 lore raw

PATCH v3 1/1 nios2: convert dma_alloc_coherent to use memalign

Quoted 1 line · Thomas Chou

Hi Marek,

Hi,

Quoted 7 lines · Marek Vasut
Quoted 3 lines

It might be wrong to keep DMA address looks alive but actually dead.

I don't quite understand this sentence, can you please rephrase it ?

Sorry. I meant the *handle, which is the DMA address, should be invalidated to NULL when the allocation failed.

OK

Best regards,
Marek Vasut

#11 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

In reply to Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.
v4
use malloc_cache_aligned().

 arch/nios2/include/asm/dma-mapping.h | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
arch/nios2/include/asm/dma-mapping.h +11 -13
index 1350e3b..bfaf662 100644
@@ -1,23 +1,21 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is mapped
+#include <memalign.h>
+#include <asm/io.h>
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is mapped
  * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- *   0x80000000 for nommu, 0xe0000000 for mmu
  */
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)malloc_cache_aligned(len);
+	if (!*handle)
+		return NULL;
+	flush_dcache_range(*handle, *handle + len);
+
+	return ioremap(*handle, len);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */
Signature · 1 line
2.1.4
#12 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Quoted 38 lines · Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.
v4
use malloc_cache_aligned().

 arch/nios2/include/asm/dma-mapping.h | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
(quoted diff) +0 -0

b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..bfaf662 100644

arch/nios2/include/asm/dma-mapping.h +0 -1
@@ -1,23 +1,21 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is

mapped +#include <memalign.h>

arch/nios2/include/asm/dma-mapping.h +4 -0
+#include <asm/io.h>
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is

mapped * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- * 0x80000000 for nommu, 0xe0000000 for mmu
*/

arch/nios2/include/asm/dma-mapping.h +0 -3
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)

arch/nios2/include/asm/dma-mapping.h line 16

Quoted 10 lines
arch/nios2/include/asm/dma-mapping.h +4 -6
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)malloc_cache_aligned(len);
+	if (!*handle)
+		return NULL;
+	flush_dcache_range(*handle, *handle + len);

Wouldn't invalidate_dcache_range() be enough here ? You don't care about the data in the newly allocated area at this point I guess -- either you fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

arch/nios2/include/asm/dma-mapping.h line 21

Quoted 4 lines
arch/nios2/include/asm/dma-mapping.h +1 -0
+	return ioremap(*handle, len);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */

Best regards,
Marek Vasut

#13 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Hi Marek,

Quoted 4 lines · Marek Vasut

Wouldn't invalidate_dcache_range() be enough here ? You don't care about the data in the newly allocated area at this point I guess -- either you fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

No. We cannot use invalidate cache here. This is related to cache design of nios2, kind of direct mapped cache.

Best regards,
Thomas

#14 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Quoted 1 line · Thomas Chou

Hi Marek,

Hi Thomas,

Quoted 8 lines · Marek Vasut
Quoted 4 lines

Wouldn't invalidate_dcache_range() be enough here ? You don't care about the data in the newly allocated area at this point I guess -- either you fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

No. We cannot use invalidate cache here. This is related to cache design of nios2, kind of direct mapped cache.

Can you please expand on this ?

btw. I was thinking about this whole cache situation. Please don't get me wrong, my intention is not to put way more work unto you and/or grind you about minor details. I hope it doesn't look that way to you.

Best regards,
Marek Vasut

#15 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Hi Marek,

Quoted 11 lines · Marek Vasut
Quoted 1 line · Thomas Chou

Hi Marek,

Hi Thomas,

Quoted 6 lines · Marek Vasut
Quoted 4 lines

Wouldn't invalidate_dcache_range() be enough here ? You don't care about the data in the newly allocated area at this point I guess -- either you fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

Quoted 4 lines
Quoted 2 lines

No. We cannot use invalidate cache here. This is related to cache design of nios2, kind of direct mapped cache.

Can you please expand on this ?

This is rather hardware depended.

Please refer to page 7 about cache implementation on the "Nios II Core Implementation Detail" manual,

https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/nios2/n2cpu_nii51015.pdf

And page 227, 8-44 about initd and initda instructions on the "Nios II Classic Processor Reference Guide",

https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/nios2/n2cpu_nii5v1.pdf

The initda instruction might do the job. But nios2 cpu with 4 bytes dcache line size does not support this instruction. So we don't implement the invalidate_dcache_range/all() in u-boot yet.

Of course, we can add the invalidate cache ops if we can drop the support of nios2 cpu with 4 bytes dcache line size.

Quoted 4 lines

btw. I was thinking about this whole cache situation. Please don't get me wrong, my intention is not to put way more work unto you and/or grind you about minor details. I hope it doesn't look that way to you.

No worries. It is just that I had very little free time last night to give more details. You are welcome.

Best regards,
Thomas

#16 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Hi Marek,

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines · Marek Vasut
Quoted 6 lines

Wouldn't invalidate_dcache_range() be enough here ? You don't care about
the data in the newly allocated area at this point I guess -- either you
fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

Thanks a lot for your suggestion. I added invalidate_dcache_range() which will check if the initda instruction is supported by the nios2 cpu.

Best regards,
Thomas

#17 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Quoted 1 line · Thomas Chou

Hi Marek,

Hi!

Quoted 10 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines · Marek Vasut
Quoted 6 lines

Wouldn't invalidate_dcache_range() be enough here ? You don't care about
the data in the newly allocated area at this point I guess -- either you
fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

Thanks a lot for your suggestion. I added invalidate_dcache_range() which will check if the initda instruction is supported by the nios2 cpu.

Ah, thanks!

Best regards,
Marek Vasut

#18 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

In reply to Thomas Chou
Quoted 1 line · Thomas Chou

Hi Marek,

Hi!

Quoted 26 lines · Marek Vasut
Quoted 12 lines · Thomas Chou
Quoted 1 line

Hi Marek,

Hi Thomas,

Quoted 7 lines · Marek Vasut
Quoted 5 lines

Wouldn't invalidate_dcache_range() be enough here ? You don't care about the data in the newly allocated area at this point I guess -- either you fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

Quoted 4 lines
Quoted 2 lines

No. We cannot use invalidate cache here. This is related to cache design of nios2, kind of direct mapped cache.

Can you please expand on this ?

This is rather hardware depended.

Please refer to page 7 about cache implementation on the "Nios II Core Implementation Detail" manual,

https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/
hb/nios2/n2cpu_nii51015.pdf

Quoted 7 lines

And page 227, 8-44 about initd and initda instructions on the "Nios II Classic Processor Reference Guide",

https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/
hb/nios2/n2cpu_nii5v1.pdf

The initda instruction might do the job.

I'd say that's the instruction we need, yep.

Quoted 3 lines

But nios2 cpu with 4 bytes
dcache line size does not support this instruction. So we don't implement the invalidate_dcache_range/all() in u-boot yet.

Where did you find this information ?

Quoted 9 lines

Of course, we can add the invalidate cache ops if we can drop the support of nios2 cpu with 4 bytes dcache line size.

Quoted 3 lines

btw. I was thinking about this whole cache situation. Please don't get me wrong, my intention is not to put way more work unto you and/or grind you about minor details. I hope it doesn't look that way to you.

No worries. It is just that I had very little free time last night to give more details. You are welcome.

Thanks!

Best regards,
Marek Vasut

#19 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Quoted 5 lines · Marek Vasut
Quoted 3 lines

But nios2 cpu with 4 bytes
dcache line size does not support this instruction. So we don't implement the invalidate_dcache_range/all() in u-boot yet.

Where did you find this information ?

Please find it on the foot note of table 7, page 8 of "Nios II Core Implementation Detail" manual,

The 4-byte line data cache implementation substitutes the flushd instruction for the flushda
instruction and triggers an unimplemented instruction exception for the initda instruction. The
16-byte and 32-byte line data cache implementations fully support the flushda and initda
instructions.

Best regards,
Thomas

#20 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Quoted 10 lines · Thomas Chou
Quoted 5 lines · Marek Vasut
Quoted 3 lines

But nios2 cpu with 4 bytes
dcache line size does not support this instruction. So we don't implement the invalidate_dcache_range/all() in u-boot yet.

Where did you find this information ?

Please find it on the foot note of table 7, page 8 of "Nios II Core Implementation Detail" manual,

Quoted 7 lines

The 4-byte line data cache implementation substitutes the flushd instruction for the flushda
instruction and triggers an unimplemented instruction exception for the initda instruction. The
16-byte and 32-byte line data cache implementations fully support the flushda and initda
instructions.

I see, thank you for looking it up for me. This inconsistency is sad :-(

Best regards,
Marek Vasut

#21 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

In reply to Thomas Chou

Hello Thomas,

Quoted 10 lines · Thomas Chou

Hi Marek,

Quoted 4 lines · Marek Vasut

Wouldn't invalidate_dcache_range() be enough here ? You don't care about the data in the newly allocated area at this point I guess -- either you fill them in and then flush, for DMA from CPU to device OR you receive data from device to CPU and then you invalidate this buffer again.

No. We cannot use invalidate cache here. This is related to cache design of nios2, kind of direct mapped cache.

Not sure I'm getting this, so for my own education: what prevents from invalidating the cache, or IOW, what would happen if it was invalidated at this point rather than flushed?

Quoted 2 lines

Best regards,
Thomas

Amicalement,

Signature · 1 line
Albert.
#22 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Hi Albert,

Quoted 3 lines · Albert ARIBAUD

Not sure I'm getting this, so for my own education: what prevents from invalidating the cache, or IOW, what would happen if it was invalidated at this point rather than flushed?

This is a hardware limitation. The nios2 cpu with 4 bytes dcache line size does not support the initda instruction, which is needed to invalidate dcache.

Recently we added a check, if the nios2 cpu support initda instruction, then we use invalidate_dcache, otherwise we use flush_dcache.

Best regards,
Thomas

#23 lore raw

PATCH v4 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

Hello Thomas,

Quoted 7 lines · Thomas Chou

Hi Albert,

Quoted 3 lines · Albert ARIBAUD

Not sure I'm getting this, so for my own education: what prevents from invalidating the cache, or IOW, what would happen if it was invalidated at this point rather than flushed?

Quoted 6 lines

This is a hardware limitation. The nios2 cpu with 4 bytes dcache line size does not support the initda instruction, which is needed to invalidate dcache.

Recently we added a check, if the nios2 cpu support initda instruction, then we use invalidate_dcache, otherwise we use flush_dcache.

Now I understand. Thanks!

Quoted 2 lines

Best regards,
Thomas

Amicalement,

Signature · 1 line
Albert.
#24 lore raw

PATCH v5 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

In reply to Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.
v4
use malloc_cache_aligned().
v5
use invalidate_dcache_range() as Marek suggested.

 arch/nios2/include/asm/dma-mapping.h | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
arch/nios2/include/asm/dma-mapping.h +11 -13
index 1350e3b..118f734 100644
@@ -1,23 +1,21 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is mapped
+#include <memalign.h>
+#include <asm/io.h>
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is mapped
  * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- *   0x80000000 for nommu, 0xe0000000 for mmu
  */
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
-	if (!addr)
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
+	*handle = (unsigned long)malloc_cache_aligned(len);
+	if (!*handle)
+		return NULL;
+	invalidate_dcache_range(*handle, *handle + len);
+
+	return ioremap(*handle, len);
 }
 
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */
Signature · 1 line
2.1.4
#25 lore raw

PATCH v6 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

In reply to Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.
v4
use malloc_cache_aligned().
v5
use invalidate_dcache_range() as Marek suggested.
v6
defer assignment of handle as Marek suggested.

 arch/nios2/include/asm/dma-mapping.h | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)
arch/nios2/include/asm/dma-mapping.h +14 -13
index 1350e3b..1562d35 100644
@@ -1,23 +1,24 @@
 #ifndef __ASM_NIOS2_DMA_MAPPING_H
 #define __ASM_NIOS2_DMA_MAPPING_H
 
-/* dma_alloc_coherent() return cache-line aligned allocation which is mapped
+#include <memalign.h>
+#include <asm/io.h>
+
+/*
+ * dma_alloc_coherent() return cache-line aligned allocation which is mapped
  * to uncached io region.
- *
- * IO_REGION_BASE should be defined in board config header file
- *   0x80000000 for nommu, 0xe0000000 for mmu
  */
-
 static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
-	void *addr = malloc(len + CONFIG_SYS_DCACHELINE_SIZE);
+	unsigned long addr = (unsigned long)malloc_cache_aligned(len);
+
 	if (!addr)
-		return 0;
-	flush_dcache((unsigned long)addr, len + CONFIG_SYS_DCACHELINE_SIZE);
-	*handle = ((unsigned long)addr +
-		   (CONFIG_SYS_DCACHELINE_SIZE - 1)) &
-		~(CONFIG_SYS_DCACHELINE_SIZE - 1) & ~(IO_REGION_BASE);
-	return (void *)(*handle | IO_REGION_BASE);
-}
+		return NULL;
+
+	invalidate_dcache_range(addr, addr + len);
+	if (handle)
+		*handle = addr;
 
+	return ioremap(addr, len);
+}
 #endif /* __ASM_NIOS2_DMA_MAPPING_H */
Signature · 1 line
2.1.4
#27 lore raw

PATCH v6 1/1 nios2: convert dma_alloc_coherent to use malloc_cache_aligned

In reply to Thomas Chou
Quoted 15 lines · Thomas Chou

Convert dma_alloc_coherent to use memalign.

---
v2
use memalign.
v3
check memalign() return for out of memory.
v4
use malloc_cache_aligned().
v5
use invalidate_dcache_range() as Marek suggested.
v6
defer assignment of handle as Marek suggested.

Quoted 3 lines
  arch/nios2/include/asm/dma-mapping.h | 27 ++++++++++++++-------------
  1 file changed, 14 insertions(+), 13 deletions(-)

Applied to u-boot-nios.