[U-Boot] [PATCH] arm64: Add memcpy_{from, to}io() and memset_io() helpers

Lokesh Vutla lokeshvutla at ti.com
Tue Oct 15 07:05:12 UTC 2019



On 12/10/19 4:29 PM, Vignesh Raghavendra wrote:
> Provide optimized memcpy_{from,to}io() and memset_io(). This is required
> when moving large amount of data to and from IO regions such as IP
> registers or accessing memory mapped flashes.
> 
> Code is borrowed from Linux Kernel v5.4.
> 
> Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>

Reviewed-by: Lokesh Vutla <lokeshvutla at ti.com>

Thanks and regards,
Lokesh

> ---
>  arch/arm/include/asm/io.h | 104 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 101 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
> index e6d27b69f936..fcfb53f0d9d8 100644
> --- a/arch/arm/include/asm/io.h
> +++ b/arch/arm/include/asm/io.h
> @@ -23,6 +23,7 @@
>  #ifdef __KERNEL__
>  
>  #include <linux/types.h>
> +#include <linux/kernel.h>
>  #include <asm/byteorder.h>
>  #include <asm/memory.h>
>  #include <asm/barriers.h>
> @@ -315,6 +316,95 @@ extern void _memset_io(unsigned long, int, size_t);
>  
>  extern void __readwrite_bug(const char *fn);
>  
> +/* Optimized copy functions to read from/write to IO sapce */
> +#ifdef CONFIG_ARM64
> +/*
> + * Copy data from IO memory space to "real" memory space.
> + */
> +static inline
> +void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
> +{
> +	while (count && !IS_ALIGNED((unsigned long)from, 8)) {
> +		*(u8 *)to = __raw_readb(from);
> +		from++;
> +		to++;
> +		count--;
> +	}
> +
> +	while (count >= 8) {
> +		*(u64 *)to = __raw_readq(from);
> +		from += 8;
> +		to += 8;
> +		count -= 8;
> +	}
> +
> +	while (count) {
> +		*(u8 *)to = __raw_readb(from);
> +		from++;
> +		to++;
> +		count--;
> +	}
> +}
> +
> +/*
> + * Copy data from "real" memory space to IO memory space.
> + */
> +static inline
> +void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
> +{
> +	while (count && !IS_ALIGNED((unsigned long)to, 8)) {
> +		__raw_writeb(*(u8 *)from, to);
> +		from++;
> +		to++;
> +		count--;
> +	}
> +
> +	while (count >= 8) {
> +		__raw_writeq(*(u64 *)from, to);
> +		from += 8;
> +		to += 8;
> +		count -= 8;
> +	}
> +
> +	while (count) {
> +		__raw_writeb(*(u8 *)from, to);
> +		from++;
> +		to++;
> +		count--;
> +	}
> +}
> +
> +/*
> + * "memset" on IO memory space.
> + */
> +static inline
> +void __memset_io(volatile void __iomem *dst, int c, size_t count)
> +{
> +	u64 qc = (u8)c;
> +
> +	qc |= qc << 8;
> +	qc |= qc << 16;
> +	qc |= qc << 32;
> +
> +	while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
> +		__raw_writeb(c, dst);
> +		dst++;
> +		count--;
> +	}
> +
> +	while (count >= 8) {
> +		__raw_writeq(qc, dst);
> +		dst += 8;
> +		count -= 8;
> +	}
> +
> +	while (count) {
> +		__raw_writeb(c, dst);
> +		dst++;
> +		count--;
> +	}
> +}
> +#endif /* CONFIG_ARM64 */
>  /*
>   * If this architecture has PCI memory IO, then define the read/write
>   * macros.  These should only be used with the cookie passed from
> @@ -355,9 +445,17 @@ out:
>  }
>  
>  #else
> -#define memset_io(a, b, c)		memset((void *)(a), (b), (c))
> -#define memcpy_fromio(a, b, c)		memcpy((a), (void *)(b), (c))
> -#define memcpy_toio(a, b, c)		memcpy((void *)(a), (b), (c))
> +
> +#ifdef CONFIG_ARM64
> +#define memset_io(a, b, c)		__memset_io((a), (b), (c))
> +#define memcpy_fromio(a, b, c)		__memcpy_fromio((a), (b), (c))
> +#define memcpy_toio(a, b, c)		__memcpy_toio((a), (b), (c))
> +#else
> +#define memset_io(a, b, c)             memset((void *)(a), (b), (c))
> +#define memcpy_fromio(a, b, c)         memcpy((a), (void *)(b), (c))
> +#define memcpy_toio(a, b, c)           memcpy((void *)(a), (b), (c))
> +#endif
> +
>  
>  #if !defined(readb)
>  
> 


More information about the U-Boot mailing list