summaryrefslogtreecommitdiffstats
path: root/arch/arm/lib32
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib32')
-rw-r--r--arch/arm/lib32/Makefile2
-rw-r--r--arch/arm/lib32/arm_architected_timer.c17
-rw-r--r--arch/arm/lib32/armlinux.c7
-rw-r--r--arch/arm/lib32/bootm.c2
-rw-r--r--arch/arm/lib32/io.c67
-rw-r--r--arch/arm/lib32/unwind.c20
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;
}