From: Peng Fan <[email protected]> memcpy_{from,to}io and memset_io is needed for i.MX8M to write TCM area. So import the APIs from Linux Kernel 6.17.
Reviewed-by: Ye Li <[email protected]> Signed-off-by: Peng Fan <[email protected]> --- include/asm-generic/io.h | 37 +++++++++++++ lib/Makefile | 1 + lib/iomem_copy.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 13d99cfb5973399209c00adee0080ff83414c064..cf981ad3501f935c714b7580536540e7aba249c1 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -3,6 +3,7 @@ * Generic I/O functions. * * Copyright (c) 2016 Imagination Technologies Ltd. + * Copyright 2025 NXP */ #ifndef __ASM_GENERIC_IO_H__ @@ -453,5 +454,41 @@ static inline void iowrite64_rep(volatile void __iomem *addr, #endif #endif /* CONFIG_64BIT */ +#ifndef memset_io +/** + * memset_io - Set a range of I/O memory to a constant value + * @addr: The beginning of the I/O-memory range to set + * @val: The value to set the memory to + * @count: The number of bytes to set + * + * Set a range of I/O memory to a given value. + */ +void memset_io(volatile void __iomem *addr, int val, size_t count); +#endif + +#ifndef memcpy_fromio +/** + * memcpy_fromio - Copy a block of data from I/O memory + * @dst: The (RAM) destination for the copy + * @src: The (I/O memory) source for the data + * @count: The number of bytes to copy + * + * Copy a block of data from I/O memory. + */ +void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count); +#endif + +#ifndef memcpy_toio +/** + * memcpy_toio - Copy a block of data into I/O memory + * @dst: The (I/O memory) destination for the copy + * @src: The (RAM) source for the data + * @count: The number of bytes to copy + * + * Copy a block of data to I/O memory. + */ +void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count); +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_GENERIC_IO_H__ */ diff --git a/lib/Makefile b/lib/Makefile index a2e6066886495502a47bb1595217e8eb82374763..6e4f59141f3faca156b13e7f78c5d4312af20193 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -123,6 +123,7 @@ obj-y += ctype.o obj-y += div64.o obj-$(CONFIG_$(PHASE_)OF_LIBFDT) += fdtdec.o fdtdec_common.o obj-y += hang.o +obj-y += iomem_copy.o obj-y += linux_compat.o obj-y += linux_string.o obj-$(CONFIG_$(PHASE_)LMB) += lmb.o diff --git a/lib/iomem_copy.c b/lib/iomem_copy.c new file mode 100644 index 0000000000000000000000000000000000000000..10661fe216f780b9ebb27828b2618d4306bb07e4 --- /dev/null +++ b/lib/iomem_copy.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2024 Kalray, Inc. All Rights Reserved. + */ + +#include <linux/compat.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <asm-generic/unaligned.h> + +#ifndef memset_io +/** + * memset_io() - Set a range of I/O memory to a constant value + * @addr: The beginning of the I/O-memory range to set + * @val: The value to set the memory to + * @count: The number of bytes to set + * + * Set a range of I/O memory to a given value. + */ +void memset_io(volatile void __iomem *addr, int val, size_t count) +{ + long qc = (u8)val; + + qc *= ~0UL / 0xff; + + while (count && !IS_ALIGNED((long)addr, sizeof(long))) { + __raw_writeb(val, addr); + addr++; + count--; + } + + while (count >= sizeof(long)) { +#ifdef CONFIG_64BIT + __raw_writeq(qc, addr); +#else + __raw_writel(qc, addr); +#endif + + addr += sizeof(long); + count -= sizeof(long); + } + + while (count) { + __raw_writeb(val, addr); + addr++; + count--; + } +} +EXPORT_SYMBOL(memset_io); +#endif + +#ifndef memcpy_fromio +/** + * memcpy_fromio() - Copy a block of data from I/O memory + * @dst: The (RAM) destination for the copy + * @src: The (I/O memory) source for the data + * @count: The number of bytes to copy + * + * Copy a block of data from I/O memory. + */ +void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count) +{ + while (count && !IS_ALIGNED((long)src, sizeof(long))) { + *(u8 *)dst = __raw_readb(src); + src++; + dst++; + count--; + } + + while (count >= sizeof(long)) { +#ifdef CONFIG_64BIT + long val = __raw_readq(src); +#else + long val = __raw_readl(src); +#endif + put_unaligned(val, (long *)dst); + + + src += sizeof(long); + dst += sizeof(long); + count -= sizeof(long); + } + + while (count) { + *(u8 *)dst = __raw_readb(src); + src++; + dst++; + count--; + } +} +EXPORT_SYMBOL(memcpy_fromio); +#endif + +#ifndef memcpy_toio +/** + * memcpy_toio() -Copy a block of data into I/O memory + * @dst: The (I/O memory) destination for the copy + * @src: The (RAM) source for the data + * @count: The number of bytes to copy + * + * Copy a block of data to I/O memory. + */ +void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count) +{ + while (count && !IS_ALIGNED((long)dst, sizeof(long))) { + __raw_writeb(*(u8 *)src, dst); + src++; + dst++; + count--; + } + + while (count >= sizeof(long)) { + long val = get_unaligned((long *)src); +#ifdef CONFIG_64BIT + __raw_writeq(val, dst); +#else + __raw_writel(val, dst); +#endif + + src += sizeof(long); + dst += sizeof(long); + count -= sizeof(long); + } + + while (count) { + __raw_writeb(*(u8 *)src, dst); + src++; + dst++; + count--; + } +} +EXPORT_SYMBOL(memcpy_toio); +#endif + + -- 2.35.3

