diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libfile.c | 61 | ||||
-rw-r--r-- | lib/math/div64.c | 30 |
2 files changed, 91 insertions, 0 deletions
diff --git a/lib/libfile.c b/lib/libfile.c index 67fc9cc7f3..a34e011f4f 100644 --- a/lib/libfile.c +++ b/lib/libfile.c @@ -12,6 +12,8 @@ * */ #include <common.h> +#include <memory.h> +#include <zero_page.h> #include <fs.h> #include <fcntl.h> #include <malloc.h> @@ -741,3 +743,62 @@ int cache_file(const char *path, char **newpath) return 0; } + +#define BUFSIZ (PAGE_SIZE * 32) + +struct resource *file_to_sdram(const char *filename, unsigned long adr) +{ + struct resource *res; + size_t size = BUFSIZ; + size_t ofs = 0; + ssize_t now; + int fd; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return NULL; + + while (1) { + res = request_sdram_region("image", adr, size); + if (!res) { + printf("unable to request SDRAM 0x%08lx-0x%08lx\n", + adr, adr + size - 1); + goto out; + } + + if (zero_page_contains(res->start + ofs)) { + void *tmp = malloc(BUFSIZ); + if (!tmp) + now = -ENOMEM; + else + now = read_full(fd, tmp, BUFSIZ); + + if (now > 0) + zero_page_memcpy((void *)(res->start + ofs), tmp, now); + free(tmp); + } else { + now = read_full(fd, (void *)(res->start + ofs), BUFSIZ); + } + + if (now < 0) { + release_sdram_region(res); + res = NULL; + goto out; + } + + if (now < BUFSIZ) { + release_sdram_region(res); + res = request_sdram_region("image", adr, ofs + now); + goto out; + } + + release_sdram_region(res); + + ofs += BUFSIZ; + size += BUFSIZ; + } +out: + close(fd); + + return res; +} diff --git a/lib/math/div64.c b/lib/math/div64.c index 386497592b..3d646c487b 100644 --- a/lib/math/div64.c +++ b/lib/math/div64.c @@ -21,6 +21,7 @@ #include <linux/bitops.h> #include <module.h> #include <linux/kernel.h> +#include <linux/ktime.h> #include <linux/math64.h> #include <linux/log2.h> @@ -233,3 +234,32 @@ u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c) return res + div64_u64(a * b, c); } #endif + +/* + * Functions for the union type storage format of ktime_t which are + * too large for inlining: + */ +#if BITS_PER_LONG < 64 +/* + * Divide a ktime value by a nanosecond value + */ +s64 __ktime_divns(const ktime_t kt, s64 div) +{ + int sft = 0; + s64 dclc; + u64 tmp; + + dclc = ktime_to_ns(kt); + tmp = dclc < 0 ? -dclc : dclc; + + /* Make sure the divisor is less than 2^32: */ + while (div >> 32) { + sft++; + div >>= 1; + } + tmp >>= sft; + do_div(tmp, (u32) div); + return dclc < 0 ? -tmp : tmp; +} +EXPORT_SYMBOL_GPL(__ktime_divns); +#endif /* BITS_PER_LONG >= 64 */ |