[U-Boot] [PATCH] nios2: convert dma mapping to use dm cpu data

Convert dma mapping to use dm cpu data.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- arch/nios2/include/asm/dma-mapping.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..403166b 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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 */

Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- v2 use memalign.
arch/nios2/include/asm/dma-mapping.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..e3a338d 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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 */

On Tuesday, October 06, 2015 at 08:49:49 AM, Thomas Chou wrote:
Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
v2 use memalign.
arch/nios2/include/asm/dma-mapping.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..e3a338d 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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);
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;
}
#endif /* __ASM_NIOS2_DMA_MAPPING_H */
Best regards, Marek Vasut

Hi Marek,
On 10/09/2015 05:43 AM, Marek Vasut wrote:
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;
Thanks a lot for your suggestion. It is much clear with this.
Best regards, Thomas

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

Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- 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(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..0618dc2 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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 */

On Friday, October 09, 2015 at 01:31:02 PM, Thomas Chou wrote:
Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
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(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..0618dc2 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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);
This still modifies the handle in both cases (failure and success). We really want to modify external variables in case of failure, no?
- if (!*handle)
return NULL;
- flush_dcache_range(*handle, *handle + len);
- return ioremap(*handle, len);
}
#endif /* __ASM_NIOS2_DMA_MAPPING_H */
Best regards, Marek Vasut

Hi Marek,
On 10/09/2015 10:49 PM, Marek Vasut wrote:
- *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

On Saturday, October 10, 2015 at 07:33:06 AM, Thomas Chou wrote:
Hi Marek,
Hi!
On 10/09/2015 10:49 PM, Marek Vasut wrote:
- *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!
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

Hi Marek,
On 10/11/2015 02:19 AM, Marek Vasut wrote:
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

On Sunday, October 11, 2015 at 03:48:58 AM, Thomas Chou wrote:
Hi Marek,
Hi,
On 10/11/2015 02:19 AM, Marek Vasut wrote:
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

Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- 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(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..bfaf662 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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 */

On Monday, October 12, 2015 at 07:29:43 AM, Thomas Chou wrote:
Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
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(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..bfaf662 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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);
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.
- return ioremap(*handle, len);
}
#endif /* __ASM_NIOS2_DMA_MAPPING_H */
Best regards, Marek Vasut

Hi Marek,
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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

On Monday, October 12, 2015 at 02:55:03 PM, Thomas Chou wrote:
Hi Marek,
Hi Thomas,
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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

Hi Marek,
On 10/12/2015 09:46 PM, Marek Vasut wrote:
On Monday, October 12, 2015 at 02:55:03 PM, Thomas Chou wrote:
Hi Marek,
Hi Thomas,
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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 ?
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/h...
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/h...
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.
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

Hi Marek,
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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

On Wednesday, October 14, 2015 at 03:48:21 AM, Thomas Chou wrote:
Hi Marek,
Hi!
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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

On Tuesday, October 13, 2015 at 02:17:53 AM, Thomas Chou wrote:
Hi Marek,
Hi!
On 10/12/2015 09:46 PM, Marek Vasut wrote:
On Monday, October 12, 2015 at 02:55:03 PM, Thomas Chou wrote:
Hi Marek,
Hi Thomas,
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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 ?
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.
I'd say that's the instruction we need, yep.
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 ?
Of course, we can add the invalidate cache ops if we can drop the support of nios2 cpu with 4 bytes dcache line size.
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

On 10/17/2015 06:56 AM, Marek Vasut wrote:
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

On Saturday, October 17, 2015 at 04:59:06 AM, Thomas Chou wrote:
On 10/17/2015 06:56 AM, Marek Vasut wrote:
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.
I see, thank you for looking it up for me. This inconsistency is sad :-(
Best regards, Marek Vasut

Hello Thomas,
On Mon, 12 Oct 2015 20:55:03 +0800, Thomas Chou thomas@wytron.com.tw wrote:
Hi Marek,
On 10/12/2015 06:32 PM, Marek Vasut wrote:
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?
Best regards, Thomas
Amicalement,

Hi Albert,
On 10/19/2015 01:52 PM, Albert ARIBAUD wrote:
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

Hello Thomas,
On Mon, 19 Oct 2015 16:18:06 +0800, Thomas Chou thomas@wytron.com.tw wrote:
Hi Albert,
On 10/19/2015 01:52 PM, Albert ARIBAUD wrote:
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.
Now I understand. Thanks!
Best regards, Thomas
Amicalement,

Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- 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(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..118f734 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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 */

Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- 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(-)
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index 1350e3b..1562d35 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -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 */

On Friday, October 16, 2015 at 10:29:07 AM, Thomas Chou wrote:
Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
Reviewed-by: Marek Vasut marex@denx.de
Thanks!
Best regards, Marek Vasut

On 10/16/2015 04:29 PM, Thomas Chou wrote:
Convert dma_alloc_coherent to use memalign.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
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(-)
Applied to u-boot-nios.
participants (3)
-
Albert ARIBAUD
-
Marek Vasut
-
Thomas Chou