diff options
Diffstat (limited to 'arch/arm/lib32')
-rw-r--r-- | arch/arm/lib32/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/lib32/arm_architected_timer.c | 17 | ||||
-rw-r--r-- | arch/arm/lib32/armlinux.c | 7 | ||||
-rw-r--r-- | arch/arm/lib32/bootm.c | 2 | ||||
-rw-r--r-- | arch/arm/lib32/io.c | 67 | ||||
-rw-r--r-- | arch/arm/lib32/unwind.c | 20 |
6 files changed, 90 insertions, 25 deletions
diff --git a/arch/arm/lib32/Makefile b/arch/arm/lib32/Makefile index 82507fffc0..d54fb7644c 100644 --- a/arch/arm/lib32/Makefile +++ b/arch/arm/lib32/Makefile @@ -31,6 +31,8 @@ extra-y += barebox.lds pbl-y += lib1funcs.o pbl-y += ashldi3.o pbl-y += div0.o +pbl-$(CONFIG_CPU_32v7) += arm_architected_timer.o +CFLAGS_arm_architected_timer.o := -march=armv7-a obj-pbl-y += setjmp.o diff --git a/arch/arm/lib32/arm_architected_timer.c b/arch/arm/lib32/arm_architected_timer.c new file mode 100644 index 0000000000..54eca13f8b --- /dev/null +++ b/arch/arm/lib32/arm_architected_timer.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <asm/system.h> +#include <clock.h> +#include <common.h> + +/* Unlike the ARMv8, the timer is not generic to ARM32 */ +void arm_architected_timer_udelay(unsigned long us) +{ + unsigned long long ticks, cntfrq = get_cntfrq(); + unsigned long long start = get_cntpct(); + + ticks = DIV_ROUND_DOWN_ULL((us * cntfrq), 1000000); + + while ((long)(start + ticks - get_cntpct()) > 0) + ; +} diff --git a/arch/arm/lib32/armlinux.c b/arch/arm/lib32/armlinux.c index 6cb7d4b5f3..eb30f4a952 100644 --- a/arch/arm/lib32/armlinux.c +++ b/arch/arm/lib32/armlinux.c @@ -18,6 +18,7 @@ #include <memory.h> #include <of.h> #include <magicvar.h> +#include <zero_page.h> #include <asm/byteorder.h> #include <asm/setup.h> @@ -265,8 +266,12 @@ void start_linux(void *adr, int swap, unsigned long initrd_address, pr_debug("booting kernel with devicetree\n"); params = oftree; } else { - setup_tags(initrd_address, initrd_size, swap); params = armlinux_get_bootparams(); + + if ((unsigned long)params < PAGE_SIZE) + zero_page_access(); + + setup_tags(initrd_address, initrd_size, swap); } architecture = armlinux_get_architecture(); diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c index e814593dce..aeb873a3a7 100644 --- a/arch/arm/lib32/bootm.c +++ b/arch/arm/lib32/bootm.c @@ -294,7 +294,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, } if (IS_ENABLED(CONFIG_BOOTM_OPTEE)) { - if (data->tee_file && !IS_ENABLED(CONFIG_BOOTM_FORCE_SIGNED_IMAGES)) { + if (data->tee_file && !bootm_signed_images_are_forced()) { ret = bootm_load_tee_from_file(data); if (ret) return ret; diff --git a/arch/arm/lib32/io.c b/arch/arm/lib32/io.c index a12da49c0a..780b1083a6 100644 --- a/arch/arm/lib32/io.c +++ b/arch/arm/lib32/io.c @@ -2,48 +2,89 @@ #include <module.h> #include <linux/types.h> +#include <asm/unaligned.h> #include <io.h> /* * Copy data from IO memory space to "real" memory space. - * This needs to be optimized. */ void memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { - unsigned char *t = to; - while (count) { + while (count && !PTR_IS_ALIGNED(from, 4)) { + *(u8 *)to = __raw_readb(from); + from++; + to++; count--; - *t = readb(from); - t++; + } + + while (count >= 4) { + put_unaligned(__raw_readl(from), (u32 *)to); + from += 4; + to += 4; + count -= 4; + } + + while (count) { + *(u8 *)to = __raw_readb(from); from++; + to++; + count--; } } /* * Copy data from "real" memory space to IO memory space. - * This needs to be optimized. */ void memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { - const unsigned char *f = from; - while (count) { + while (count && !IS_ALIGNED((unsigned long)to, 4)) { + __raw_writeb(*(u8 *)from, to); + from++; + to++; count--; - writeb(*f, to); - f++; + } + + while (count >= 4) { + __raw_writel(get_unaligned((u32 *)from), to); + from += 4; + to += 4; + count -= 4; + } + + while (count) { + __raw_writeb(*(u8 *)from, to); + from++; to++; + count--; } } /* * "memset" on IO memory space. - * This needs to be optimized. */ void memset_io(volatile void __iomem *dst, int c, size_t count) { - while (count) { + u32 qc = (u8)c; + + qc |= qc << 8; + qc |= qc << 16; + + while (count && !PTR_IS_ALIGNED(dst, 4)) { + __raw_writeb(c, dst); + dst++; count--; - writeb(c, dst); + } + + while (count >= 4) { + __raw_writel(qc, dst); + dst += 4; + count -= 4; + } + + while (count) { + __raw_writeb(c, dst); dst++; + count--; } } diff --git a/arch/arm/lib32/unwind.c b/arch/arm/lib32/unwind.c index 6f73cb1b73..c355bba1b7 100644 --- a/arch/arm/lib32/unwind.c +++ b/arch/arm/lib32/unwind.c @@ -65,9 +65,9 @@ static void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS - pr_warning("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); + eprintf("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); #else - pr_warning("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); + eprintf("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); #endif } @@ -124,7 +124,7 @@ static const struct unwind_idx *search_index(unsigned long addr, if (likely(start->addr_offset <= addr_prel31)) return start; else { - pr_warning("unwind: Unknown symbol address %08lx\n", addr); + eprintf("unwind: Unknown symbol address %08lx\n", addr); return NULL; } } @@ -177,7 +177,7 @@ static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) unsigned long ret; if (ctrl->entries <= 0) { - pr_warning("unwind: Corrupt unwind table\n"); + eprintf("unwind: Corrupt unwind table\n"); return 0; } @@ -214,7 +214,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) insn = (insn << 8) | unwind_get_byte(ctrl); mask = insn & 0x0fff; if (mask == 0) { - pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n", + eprintf("unwind: 'Refuse to unwind' instruction %04lx\n", insn); return -URC_FAILURE; } @@ -253,7 +253,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) int reg = 0; if (mask == 0 || mask & 0xf0) { - pr_warning("unwind: Spare encoding %04lx\n", + eprintf("unwind: Spare encoding %04lx\n", (insn << 8) | mask); return -URC_FAILURE; } @@ -271,7 +271,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) ctrl->vrs[SP] += 0x204 + (uleb128 << 2); } else { - pr_warning("unwind: Unhandled instruction %02lx\n", insn); + eprintf("unwind: Unhandled instruction %02lx\n", insn); return -URC_FAILURE; } @@ -303,7 +303,7 @@ int unwind_frame(struct stackframe *frame) idx = unwind_find_idx(frame->pc); if (!idx) { - pr_warning("unwind: Index not found %08lx\n", frame->pc); + eprintf("unwind: Index not found %08lx\n", frame->pc); return -URC_FAILURE; } @@ -322,7 +322,7 @@ int unwind_frame(struct stackframe *frame) /* only personality routine 0 supported in the index */ ctrl.insn = &idx->insn; else { - pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n", + eprintf("unwind: Unsupported personality routine %08lx in the index at %p\n", idx->insn, idx); return -URC_FAILURE; } @@ -335,7 +335,7 @@ int unwind_frame(struct stackframe *frame) ctrl.byte = 1; ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16); } else { - pr_warning("unwind: Unsupported personality routine %08lx at %p\n", + eprintf("unwind: Unsupported personality routine %08lx at %p\n", *ctrl.insn, ctrl.insn); return -URC_FAILURE; } |