From ca1c292d2ee6bcb06be71400d25ae37e9dc2c1aa Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Apr 2026 09:54:31 +0200 Subject: string: fix prototype of memdup() It doesn't make sense to restrict memdup() to only return char* pointers, especially when it is already defined to accept void*. This makes it uglier to use to e.g. duplicate a struct. Make it return void*, just as kmemdup() does in the kernel (and which our kmemdup() in fact also does). While in here, make a small optimization: memcpy() is defined to return the destination register, so we write this in a way that the compiler may do a tail call. Reviewed-by: Simon Glass Signed-off-by: Rasmus Villemoes --- include/linux/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index d943fcce690..9e47fe01c16 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -142,7 +142,7 @@ void *memchr_inv(const void *, int, size_t); * memory is available * */ -char *memdup(const void *src, size_t len); +void *memdup(const void *src, size_t len); unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); -- cgit v1.3.1 From 349d148f16d83da3b1e3475be0e43bfda4f4ab71 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Apr 2026 09:54:33 +0200 Subject: lib/string.c: drop pointless __HAVE_ARCH_STRDUP There has never been an arch-specific optimized implementation of str[n]dup, nor is there likely to ever be one, because unlike their cousins strlen(), strcpy() and similar that simply read/write the src/dst, the dup functions by definition involve memory allocation. So drop this irrelevant cpp guard. Reviewed-by: Simon Glass Signed-off-by: Rasmus Villemoes --- include/linux/string.h | 3 +-- lib/string.c | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index 9e47fe01c16..a28150fa578 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -101,10 +101,9 @@ size_t strcspn(const char *s, const char *reject); # define strndup sandbox_strndup #endif -#ifndef __HAVE_ARCH_STRDUP extern char * strdup(const char *); extern char * strndup(const char *, size_t); -#endif + #ifndef __HAVE_ARCH_STRSWAB extern char * strswab(const char *); #endif diff --git a/lib/string.c b/lib/string.c index c2813e0f854..2c1baa568b9 100644 --- a/lib/string.c +++ b/lib/string.c @@ -343,7 +343,6 @@ size_t strcspn(const char *s, const char *reject) } #endif -#ifndef __HAVE_ARCH_STRDUP char * strdup(const char *s) { char *new; @@ -379,7 +378,6 @@ char * strndup(const char *s, size_t n) return new; } -#endif #ifndef __HAVE_ARCH_STRSPN /** -- cgit v1.3.1 From 8c664d2135723a110a60b792a8614c4864ad82a3 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 21 Apr 2026 09:54:34 +0200 Subject: lib/string.c: introduce memdup_nul() helper This is completely analogous to the linux kernel's kmemdup_nul() helper, apart from the lack of the gfp_t argument: Allocate a buffer of size {len}+1, copy {len} bytes from the given buffer, and add a final nul byte. This pattern exists in a number of places, so this helper can reduce some boilerplate code. Reviewed-by: Simon Glass Signed-off-by: Rasmus Villemoes --- include/linux/string.h | 13 +++++++++++++ lib/string.c | 15 +++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index a28150fa578..b2e38ecf26e 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -143,6 +143,19 @@ void *memchr_inv(const void *, int, size_t); */ void *memdup(const void *src, size_t len); +/** + * memdup_nul() - allocate a buffer and copy in the contents, appending a nul byte + * + * Note that this returns a valid pointer even if @len is 0 + * + * @src: data to copy in + * @len: number of bytes to copy + * Return: allocated buffer with the copied contents and an extra nul byte, + * or NULL if not enough memory is available + * + */ +void *memdup_nul(const void *src, size_t len); + unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); diff --git a/lib/string.c b/lib/string.c index 2c1baa568b9..3923cce5561 100644 --- a/lib/string.c +++ b/lib/string.c @@ -343,6 +343,21 @@ size_t strcspn(const char *s, const char *reject) } #endif +void *memdup_nul(const void *src, size_t len) +{ + char *dst; + + if (len + 1 < len) + return NULL; + + dst = malloc(len + 1); + if (!dst) + return NULL; + + dst[len] = '\0'; + return memcpy(dst, src, len); +} + char * strdup(const char *s) { char *new; -- cgit v1.3.1 From 3c9cb48b4757f631e30a6cba634d62be815ac066 Mon Sep 17 00:00:00 2001 From: Brian Ruley Date: Tue, 16 Jun 2026 15:51:40 +0300 Subject: clk: clk-divider: add clk_register_divider_table() The existing clk_register_divider() only supports linear or power-of-two divider mappings. Some hardware (e.g. i.MX6 PLL5 post_div and video_div) uses non-linear register-value-to-divisor mappings that require a lookup table. Add clk_register_divider_table() which accepts a clk_div_table, and reimplement clk_register_divider() as a wrapper passing table=NULL. Signed-off-by: Brian Ruley --- drivers/clk/clk-divider.c | 16 +++++++++++++--- include/linux/clk-provider.h | 5 +++++ 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index e692b9c2167..d30786a9e6c 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -228,20 +228,30 @@ static struct clk *_register_divider(struct udevice *dev, const char *name, return clk; } -struct clk *clk_register_divider(struct udevice *dev, const char *name, +struct clk *clk_register_divider_table(struct udevice *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags) + u8 clk_divider_flags, const struct clk_div_table *table) { struct clk *clk; clk = _register_divider(dev, name, parent_name, flags, reg, shift, - width, clk_divider_flags, NULL); + width, clk_divider_flags, table); if (IS_ERR(clk)) return ERR_CAST(clk); return clk; } +struct clk *clk_register_divider(struct udevice *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags) +{ + return clk_register_divider_table(dev, name, parent_name, flags, reg, + shift, width, clk_divider_flags, + NULL); +} + U_BOOT_DRIVER(ccf_clk_divider) = { .name = UBOOT_DM_CLK_CCF_DIVIDER, .id = UCLASS_CLK, diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 2d754fa4287..366f2d968a3 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -246,6 +246,11 @@ struct clk *clk_register_fixed_factor(struct udevice *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div); +struct clk *clk_register_divider_table(struct udevice *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, const struct clk_div_table *table); + struct clk *clk_register_divider(struct udevice *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, -- cgit v1.3.1